You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fj...@apache.org on 2019/04/02 06:06:57 UTC

[incubator-druid] branch master updated: Migrate the web console back to Blueprint v3 (#7398)

This is an automated email from the ASF dual-hosted git repository.

fjy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git


The following commit(s) were added to refs/heads/master by this push:
     new d2ff3eb  Migrate the web console back to Blueprint v3 (#7398)
d2ff3eb is described below

commit d2ff3eb1999fc560c98ba4ea5014583d9cf827a9
Author: Vadim Ogievetsky <va...@gmail.com>
AuthorDate: Mon Apr 1 23:06:48 2019 -0700

    Migrate the web console back to Blueprint v3 (#7398)
    
    * migrate back to Blueprint v3
    
    * rename filler file
    
    * fix missing icon
---
 .../druid/cli/RouterJettyServerInitializer.java    |    1 -
 web-console/.gitignore                             |    3 +-
 web-console/package-lock.json                      | 1286 +++++++++++++++++++-
 web-console/package.json                           |    6 +-
 web-console/script/build                           |    4 -
 web-console/script/clean                           |    1 -
 web-console/script/cp-to                           |    1 -
 web-console/src/bootstrap/react-table-defaults.tsx |    2 +-
 web-console/src/components/auto-form.tsx           |    3 +-
 web-console/src/components/filler.tsx              |  375 ------
 web-console/src/components/header-bar.scss         |    6 +-
 web-console/src/components/header-bar.tsx          |   38 +-
 web-console/src/components/json-collapse.tsx       |   61 +
 web-console/src/components/json-input.tsx          |   92 ++
 web-console/src/components/rule-editor.tsx         |   21 +-
 web-console/src/components/sql-control.tsx         |    7 +-
 .../src/components/table-column-selection.scss     |    9 +-
 .../src/components/table-column-selection.tsx      |    7 +-
 web-console/src/console-application.tsx            |    3 +-
 web-console/src/dialogs/about-dialog.tsx           |    4 +-
 web-console/src/dialogs/async-action-dialog.tsx    |    9 +-
 web-console/src/dialogs/compaction-dialog.scss     |    2 +-
 .../src/dialogs/coordinator-dynamic-config.scss    |    4 +-
 .../src/dialogs/coordinator-dynamic-config.tsx     |    6 +-
 web-console/src/dialogs/history-dialog.scss        |    4 +-
 web-console/src/dialogs/history-dialog.tsx         |    4 +-
 web-console/src/dialogs/lookup-edit-dialog.scss    |    2 +-
 web-console/src/dialogs/lookup-edit-dialog.tsx     |   19 +-
 .../src/dialogs/overlord-dynamic-config.scss       |    4 +-
 .../src/dialogs/overlord-dynamic-config.tsx        |    6 +-
 web-console/src/dialogs/retention-dialog.scss      |    2 +-
 web-console/src/dialogs/retention-dialog.tsx       |    6 +-
 .../filler.scss => dialogs/snitch-dialog.scss}     |   15 +-
 web-console/src/dialogs/snitch-dialog.tsx          |   23 +-
 web-console/src/dialogs/spec-dialog.scss           |    2 +-
 web-console/src/entry.scss                         |    4 +-
 web-console/src/utils/general.tsx                  |    7 +-
 web-console/src/views/datasource-view.tsx          |    6 +-
 web-console/src/views/home-view.scss               |    2 +-
 web-console/src/views/home-view.tsx                |    7 +-
 web-console/src/views/lookups-view.tsx             |   13 +-
 web-console/src/views/segments-view.tsx            |    7 +-
 web-console/src/views/servers-view.tsx             |    8 +-
 web-console/src/views/tasks-view.tsx               |   24 +-
 web-console/unified-console.html                   |    4 +-
 45 files changed, 1538 insertions(+), 582 deletions(-)

diff --git a/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java b/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java
index d76fe83..57b6cbb 100644
--- a/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java
+++ b/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java
@@ -66,7 +66,6 @@ public class RouterJettyServerInitializer implements JettyServerInitializer
       "/",
       "/coordinator-console/*",
       "/public/*",
-      "/assets/*",
       "/old-console/*",
       "/pages/*",
       "/unified-console.html",
diff --git a/web-console/.gitignore b/web-console/.gitignore
index be63fe3..a18416a 100644
--- a/web-console/.gitignore
+++ b/web-console/.gitignore
@@ -2,7 +2,6 @@ node/
 node_modules/
 resources/
 public/
-assets/
 lib/*.css
 
 coordinator-console/
@@ -14,4 +13,4 @@ lib/sql-function-doc.ts
 .tscache
 tscommand-*.tmp.txt
 
-licenses.json
\ No newline at end of file
+licenses.json
diff --git a/web-console/package-lock.json b/web-console/package-lock.json
index 5c60be7..61dba3c 100644
--- a/web-console/package-lock.json
+++ b/web-console/package-lock.json
@@ -219,15 +219,42 @@
       }
     },
     "@blueprintjs/core": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-1.0.1.tgz",
-      "integrity": "sha1-gfv9/g6gK7kLgLG+MaAec+tiWAY=",
+      "version": "3.15.0",
+      "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.15.0.tgz",
+      "integrity": "sha512-znXO0UaWBJO7Nm2qEvZzURCDuogsJ9DJlIw3N2XnIi+k/c8mQ1xlvtg0TT2pS88lMG9HUEKky3b0UQaSXBw4LA==",
+      "requires": {
+        "@blueprintjs/icons": "^3.7.0",
+        "@types/dom4": "^2.0.1",
+        "classnames": "^2.2",
+        "dom4": "^2.0.1",
+        "normalize.css": "^8.0.0",
+        "popper.js": "^1.14.1",
+        "react-popper": "^1.0.0",
+        "react-transition-group": "^2.2.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "tslib": "^1.9.0"
+      },
+      "dependencies": {
+        "react-transition-group": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.7.1.tgz",
+          "integrity": "sha512-b0VJTzNRnXxRpCuxng6QJbAzmmrhBn1BZJfPPnHbH2PIo8msdkajqwtfdyGm/OypPXZNfAHKEqeN15wjMXrRJQ==",
+          "requires": {
+            "dom-helpers": "^3.3.1",
+            "loose-envify": "^1.4.0",
+            "prop-types": "^15.6.2",
+            "react-lifecycles-compat": "^3.0.4"
+          }
+        }
+      }
+    },
+    "@blueprintjs/icons": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.7.0.tgz",
+      "integrity": "sha512-608lQx1okOo85LNp7LyvsXWlgJjoQAiu29wULcktGuAuMmVXgueaGbMEDpuEMbu+uRlg9yqDhmk1eWm7W7R5ag==",
       "requires": {
         "classnames": "^2.2",
-        "dom4": "^1.8",
-        "normalize.css": "4.1.1",
-        "pure-render-decorator": "~1.1.1",
-        "tether": "^1.2"
+        "tslib": "^1.9.0"
       }
     },
     "@csstools/convert-colors": {
@@ -264,6 +291,11 @@
       "integrity": "sha512-/EcY/15X5tnwkMT2txpjiLUNJj5xHA2vGHOXI8NTYGhETK914RRLQLjNm6EpAI1D2IY5vh3CzuLODnqBAwKjPA==",
       "dev": true
     },
+    "@types/dom4": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.1.tgz",
+      "integrity": "sha512-kSkVAvWmMZiCYtvqjqQEwOmvKwcH+V4uiv3qPQ8pAh1Xl39xggGEo8gHUqV4waYGHezdFw0rKBR8Jt0CrQSDZA=="
+    },
     "@types/history": {
       "version": "4.7.2",
       "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.2.tgz",
@@ -370,6 +402,33 @@
         "@types/react": "*"
       }
     },
+    "@types/unist": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
+      "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==",
+      "dev": true
+    },
+    "@types/vfile": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz",
+      "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*",
+        "@types/unist": "*",
+        "@types/vfile-message": "*"
+      }
+    },
+    "@types/vfile-message": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz",
+      "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*",
+        "@types/unist": "*"
+      }
+    },
     "@webassemblyjs/ast": {
       "version": "1.8.3",
       "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.3.tgz",
@@ -1042,6 +1101,12 @@
         "babel-plugin-jest-hoist": "^24.1.0"
       }
     },
+    "bail": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz",
+      "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==",
+      "dev": true
+    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -1511,6 +1576,32 @@
       "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
       "dev": true
     },
+    "caller-callsite": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+      "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+      "dev": true,
+      "requires": {
+        "callsites": "^2.0.0"
+      },
+      "dependencies": {
+        "callsites": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+          "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+          "dev": true
+        }
+      }
+    },
+    "caller-path": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+      "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+      "dev": true,
+      "requires": {
+        "caller-callsite": "^2.0.0"
+      }
+    },
     "callsites": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz",
@@ -1562,10 +1653,11 @@
       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
       "dev": true
     },
-    "chain-function": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz",
-      "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg=="
+    "ccount": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz",
+      "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==",
+      "dev": true
     },
     "chalk": {
       "version": "2.4.2",
@@ -1589,6 +1681,30 @@
         }
       }
     },
+    "character-entities": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz",
+      "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==",
+      "dev": true
+    },
+    "character-entities-html4": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz",
+      "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==",
+      "dev": true
+    },
+    "character-entities-legacy": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz",
+      "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==",
+      "dev": true
+    },
+    "character-reference-invalid": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz",
+      "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==",
+      "dev": true
+    },
     "chokidar": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz",
@@ -1716,6 +1832,16 @@
         "shallow-clone": "^1.0.0"
       }
     },
+    "clone-regexp": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz",
+      "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==",
+      "dev": true,
+      "requires": {
+        "is-regexp": "^1.0.0",
+        "is-supported-regexp-flag": "^1.0.0"
+      }
+    },
     "co": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -1728,6 +1854,12 @@
       "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
       "dev": true
     },
+    "collapse-white-space": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz",
+      "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==",
+      "dev": true
+    },
     "collection-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -1985,6 +2117,15 @@
         "sha.js": "^2.4.8"
       }
     },
+    "create-react-context": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.2.tgz",
+      "integrity": "sha512-KkpaLARMhsTsgp0d2NA/R94F/eDLbhXERdIq3LvX2biCAXcDvHYoOqHfWCHf1+OLj+HKBotLG3KqaOOf+C1C+A==",
+      "requires": {
+        "fbjs": "^0.8.0",
+        "gud": "^1.0.0"
+      }
+    },
     "cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -2192,6 +2333,16 @@
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
       "dev": true
     },
+    "decamelize-keys": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+      "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+      "dev": true,
+      "requires": {
+        "decamelize": "^1.1.0",
+        "map-obj": "^1.0.0"
+      }
+    },
     "decode-uri-component": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@@ -2453,10 +2604,20 @@
         "@babel/runtime": "^7.1.2"
       }
     },
+    "dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
     "dom4": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/dom4/-/dom4-1.8.5.tgz",
-      "integrity": "sha512-ehHzOGGkVQOwU9HyZ99gHwkx4ybrRl/P1vJM7EH1nS9XsgHwO+J0KwCnVQrn8iQvpstGwFrtrX7aSNQ43QuK4A=="
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/dom4/-/dom4-2.1.4.tgz",
+      "integrity": "sha512-7NNKNViuZYu4GaZMUsSbsV6MFsT/ZpYNKP1NT4YIUgAvwPR8ODuvQEZZ7vRC1u5Y4dHwQ7je/UNOlRRWkaCyvw=="
     },
     "domain-browser": {
       "version": "1.2.0",
@@ -2464,6 +2625,12 @@
       "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
       "dev": true
     },
+    "domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+      "dev": true
+    },
     "domexception": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
@@ -2473,6 +2640,34 @@
         "webidl-conversions": "^4.0.2"
       }
     },
+    "domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "1"
+      }
+    },
+    "domutils": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+      "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+      "dev": true,
+      "requires": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
+    "dot-prop": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+      "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+      "dev": true,
+      "requires": {
+        "is-obj": "^1.0.0"
+      }
+    },
     "druid-console": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/druid-console/-/druid-console-0.0.2.tgz",
@@ -2527,6 +2722,12 @@
         "minimalistic-crypto-utils": "^1.0.0"
       }
     },
+    "emoji-regex": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "dev": true
+    },
     "emojis-list": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
@@ -2567,6 +2768,12 @@
         "tapable": "^1.0.0"
       }
     },
+    "entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+      "dev": true
+    },
     "errno": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
@@ -2760,6 +2967,15 @@
         "strip-eof": "^1.0.0"
       }
     },
+    "execall": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz",
+      "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=",
+      "dev": true,
+      "requires": {
+        "clone-regexp": "^1.0.0"
+      }
+    },
     "exit": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -3079,6 +3295,15 @@
       "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
       "dev": true
     },
+    "file-entry-cache": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-4.0.0.tgz",
+      "integrity": "sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA==",
+      "dev": true,
+      "requires": {
+        "flat-cache": "^2.0.1"
+      }
+    },
     "fileset": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
@@ -3187,6 +3412,23 @@
         }
       }
     },
+    "flat-cache": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "dev": true,
+      "requires": {
+        "flatted": "^2.0.0",
+        "rimraf": "2.6.3",
+        "write": "1.0.3"
+      }
+    },
+    "flatted": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
+      "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==",
+      "dev": true
+    },
     "flatten": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
@@ -4041,6 +4283,12 @@
         }
       }
     },
+    "globjoin": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
+      "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=",
+      "dev": true
+    },
     "globule": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
@@ -4052,6 +4300,23 @@
         "minimatch": "~3.0.2"
       }
     },
+    "gonzales-pe": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.4.tgz",
+      "integrity": "sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ==",
+      "dev": true,
+      "requires": {
+        "minimist": "1.1.x"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
+          "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=",
+          "dev": true
+        }
+      }
+    },
     "graceful-fs": {
       "version": "4.1.15",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
@@ -4070,6 +4335,11 @@
       "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
       "dev": true
     },
+    "gud": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
+      "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
+    },
     "handle-thing": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
@@ -4285,6 +4555,39 @@
       "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
       "dev": true
     },
+    "html-tags": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
+      "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
+      "dev": true
+    },
+    "htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
+          "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "http-deceiver": {
       "version": "1.2.7",
       "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
@@ -4414,6 +4717,16 @@
         "import-from": "^2.1.0"
       }
     },
+    "import-fresh": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+      "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+      "dev": true,
+      "requires": {
+        "caller-path": "^2.0.0",
+        "resolve-from": "^3.0.0"
+      }
+    },
     "import-from": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
@@ -4423,6 +4736,12 @@
         "resolve-from": "^3.0.0"
       }
     },
+    "import-lazy": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz",
+      "integrity": "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==",
+      "dev": true
+    },
     "import-local": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
@@ -4564,6 +4883,28 @@
         }
       }
     },
+    "is-alphabetical": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz",
+      "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==",
+      "dev": true
+    },
+    "is-alphanumeric": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz",
+      "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=",
+      "dev": true
+    },
+    "is-alphanumerical": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz",
+      "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==",
+      "dev": true,
+      "requires": {
+        "is-alphabetical": "^1.0.0",
+        "is-decimal": "^1.0.0"
+      }
+    },
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -4623,6 +4964,12 @@
       "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
       "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
     },
+    "is-decimal": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz",
+      "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==",
+      "dev": true
+    },
     "is-descriptor": {
       "version": "0.1.6",
       "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
@@ -4690,6 +5037,12 @@
         "is-extglob": "^2.1.1"
       }
     },
+    "is-hexadecimal": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz",
+      "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==",
+      "dev": true
+    },
     "is-number": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -4710,6 +5063,12 @@
         }
       }
     },
+    "is-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+      "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+      "dev": true
+    },
     "is-path-cwd": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
@@ -4734,6 +5093,12 @@
         "path-is-inside": "^1.0.1"
       }
     },
+    "is-plain-obj": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+      "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+      "dev": true
+    },
     "is-plain-object": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -4751,11 +5116,23 @@
         "has": "^1.0.1"
       }
     },
+    "is-regexp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+      "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
+      "dev": true
+    },
     "is-stream": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
       "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
     },
+    "is-supported-regexp-flag": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz",
+      "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==",
+      "dev": true
+    },
     "is-symbol": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
@@ -4776,12 +5153,24 @@
       "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
       "dev": true
     },
+    "is-whitespace-character": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz",
+      "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==",
+      "dev": true
+    },
     "is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
       "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
       "dev": true
     },
+    "is-word-character": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz",
+      "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==",
+      "dev": true
+    },
     "is-wsl": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
@@ -5441,6 +5830,12 @@
       "integrity": "sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q==",
       "dev": true
     },
+    "known-css-properties": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.11.0.tgz",
+      "integrity": "sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w==",
+      "dev": true
+    },
     "lcid": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
@@ -5632,6 +6027,12 @@
       "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
       "dev": true
     },
+    "longest-streak": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz",
+      "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==",
+      "dev": true
+    },
     "loose-envify": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -5720,6 +6121,24 @@
         "object-visit": "^1.0.0"
       }
     },
+    "markdown-escapes": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz",
+      "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==",
+      "dev": true
+    },
+    "markdown-table": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz",
+      "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==",
+      "dev": true
+    },
+    "mathml-tag-names": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz",
+      "integrity": "sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg==",
+      "dev": true
+    },
     "md5.js": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -5731,6 +6150,15 @@
         "safe-buffer": "^5.1.2"
       }
     },
+    "mdast-util-compact": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz",
+      "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==",
+      "dev": true,
+      "requires": {
+        "unist-util-visit": "^1.1.0"
+      }
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -5984,6 +6412,16 @@
       "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
       "dev": true
     },
+    "minimist-options": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz",
+      "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==",
+      "dev": true,
+      "requires": {
+        "arrify": "^1.0.1",
+        "is-plain-obj": "^1.1.0"
+      }
+    },
     "mississippi": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
@@ -6454,10 +6892,16 @@
       "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
       "dev": true
     },
+    "normalize-selector": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz",
+      "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=",
+      "dev": true
+    },
     "normalize.css": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-4.1.1.tgz",
-      "integrity": "sha1-TwsdWiNTgyUrBNhWa4Zsxfytnww="
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
+      "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
     },
     "npm-run-path": {
       "version": "2.0.2",
@@ -6820,6 +7264,20 @@
         "safe-buffer": "^5.1.1"
       }
     },
+    "parse-entities": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz",
+      "integrity": "sha512-NBWYLQm1KSoDKk7GAHyioLTvCZ5QjdH/ASBBQTD3iLiAWJXS5bg1jEWI8nIJ+vgVvsceBVBcDGRWSo0KVQBvvg==",
+      "dev": true,
+      "requires": {
+        "character-entities": "^1.0.0",
+        "character-entities-legacy": "^1.0.0",
+        "character-reference-invalid": "^1.0.0",
+        "is-alphanumerical": "^1.0.0",
+        "is-decimal": "^1.0.0",
+        "is-hexadecimal": "^1.0.0"
+      }
+    },
     "parse-json": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@@ -6977,6 +7435,11 @@
       "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
       "dev": true
     },
+    "popper.js": {
+      "version": "1.14.7",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.7.tgz",
+      "integrity": "sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ=="
+    },
     "portfinder": {
       "version": "1.0.20",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz",
@@ -7213,6 +7676,15 @@
         "postcss": "^7.0.2"
       }
     },
+    "postcss-html": {
+      "version": "0.36.0",
+      "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz",
+      "integrity": "sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==",
+      "dev": true,
+      "requires": {
+        "htmlparser2": "^3.10.0"
+      }
+    },
     "postcss-image-set-function": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz",
@@ -7233,6 +7705,15 @@
         "postcss": "^7.0.2"
       }
     },
+    "postcss-jsx": {
+      "version": "0.36.0",
+      "resolved": "https://registry.npmjs.org/postcss-jsx/-/postcss-jsx-0.36.0.tgz",
+      "integrity": "sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g==",
+      "dev": true,
+      "requires": {
+        "@babel/core": ">=7.1.0"
+      }
+    },
     "postcss-lab-function": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz",
@@ -7244,6 +7725,15 @@
         "postcss-values-parser": "^2.0.0"
       }
     },
+    "postcss-less": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz",
+      "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==",
+      "dev": true,
+      "requires": {
+        "postcss": "^7.0.14"
+      }
+    },
     "postcss-load-config": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
@@ -7275,6 +7765,16 @@
         "postcss": "^7.0.2"
       }
     },
+    "postcss-markdown": {
+      "version": "0.36.0",
+      "resolved": "https://registry.npmjs.org/postcss-markdown/-/postcss-markdown-0.36.0.tgz",
+      "integrity": "sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ==",
+      "dev": true,
+      "requires": {
+        "remark": "^10.0.1",
+        "unist-util-find-all-after": "^1.0.2"
+      }
+    },
     "postcss-media-minmax": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz",
@@ -7284,7 +7784,13 @@
         "postcss": "^7.0.2"
       }
     },
-    "postcss-modules-extract-imports": {
+    "postcss-media-query-parser": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
+      "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=",
+      "dev": true
+    },
+    "postcss-modules-extract-imports": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
       "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==",
@@ -7437,6 +7943,40 @@
         "postcss": "^7.0.7"
       }
     },
+    "postcss-resolve-nested-selector": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
+      "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=",
+      "dev": true
+    },
+    "postcss-safe-parser": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz",
+      "integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==",
+      "dev": true,
+      "requires": {
+        "postcss": "^7.0.0"
+      }
+    },
+    "postcss-sass": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.3.5.tgz",
+      "integrity": "sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A==",
+      "dev": true,
+      "requires": {
+        "gonzales-pe": "^4.2.3",
+        "postcss": "^7.0.1"
+      }
+    },
+    "postcss-scss": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.0.0.tgz",
+      "integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==",
+      "dev": true,
+      "requires": {
+        "postcss": "^7.0.0"
+      }
+    },
     "postcss-selector-matches": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz",
@@ -7476,6 +8016,12 @@
         }
       }
     },
+    "postcss-syntax": {
+      "version": "0.36.2",
+      "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz",
+      "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==",
+      "dev": true
+    },
     "postcss-value-parser": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
@@ -7642,14 +8188,6 @@
       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
       "dev": true
     },
-    "pure-render-decorator": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pure-render-decorator/-/pure-render-decorator-1.1.1.tgz",
-      "integrity": "sha1-9eC3bOEoeOadpBp+6GJ/71S19Xo=",
-      "requires": {
-        "fbjs": "^0.8.0"
-      }
-    },
     "qs": {
       "version": "6.5.2",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
@@ -7674,6 +8212,12 @@
       "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==",
       "dev": true
     },
+    "quick-lru": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
+      "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=",
+      "dev": true
+    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -7745,14 +8289,6 @@
         "prop-types": "^15.6.2"
       }
     },
-    "react-addons-css-transition-group": {
-      "version": "15.6.2",
-      "resolved": "https://registry.npmjs.org/react-addons-css-transition-group/-/react-addons-css-transition-group-15.6.2.tgz",
-      "integrity": "sha1-nkN2vPQLUhfRTsaFUwgc7ksIptY=",
-      "requires": {
-        "react-transition-group": "^1.2.0"
-      }
-    },
     "react-dom": {
       "version": "16.8.3",
       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.3.tgz",
@@ -7769,6 +8305,34 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
       "integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA=="
     },
+    "react-lifecycles-compat": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+      "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+    },
+    "react-popper": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.3.tgz",
+      "integrity": "sha512-ynMZBPkXONPc5K4P5yFWgZx5JGAUIP3pGGLNs58cfAPgK67olx7fmLp+AdpZ0+GoQ+ieFDa/z4cdV6u7sioH6w==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "create-react-context": "<=0.2.2",
+        "popper.js": "^1.14.4",
+        "prop-types": "^15.6.1",
+        "typed-styles": "^0.0.7",
+        "warning": "^4.0.2"
+      },
+      "dependencies": {
+        "warning": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+          "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+          "requires": {
+            "loose-envify": "^1.0.0"
+          }
+        }
+      }
+    },
     "react-router": {
       "version": "4.3.1",
       "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
@@ -7824,18 +8388,6 @@
         "classnames": "^2.2.5"
       }
     },
-    "react-transition-group": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.1.tgz",
-      "integrity": "sha512-CWaL3laCmgAFdxdKbhhps+c0HRGF4c+hdM4H23+FI1QBNUyx/AMeIJGWorehPNSaKnQNOAxL7PQmqMu78CDj3Q==",
-      "requires": {
-        "chain-function": "^1.0.0",
-        "dom-helpers": "^3.2.0",
-        "loose-envify": "^1.3.1",
-        "prop-types": "^15.5.6",
-        "warning": "^3.0.0"
-      }
-    },
     "read-cache": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -8022,6 +8574,62 @@
         "jsesc": "~0.5.0"
       }
     },
+    "remark": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz",
+      "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==",
+      "dev": true,
+      "requires": {
+        "remark-parse": "^6.0.0",
+        "remark-stringify": "^6.0.0",
+        "unified": "^7.0.0"
+      }
+    },
+    "remark-parse": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz",
+      "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==",
+      "dev": true,
+      "requires": {
+        "collapse-white-space": "^1.0.2",
+        "is-alphabetical": "^1.0.0",
+        "is-decimal": "^1.0.0",
+        "is-whitespace-character": "^1.0.0",
+        "is-word-character": "^1.0.0",
+        "markdown-escapes": "^1.0.0",
+        "parse-entities": "^1.1.0",
+        "repeat-string": "^1.5.4",
+        "state-toggle": "^1.0.0",
+        "trim": "0.0.1",
+        "trim-trailing-lines": "^1.0.0",
+        "unherit": "^1.0.4",
+        "unist-util-remove-position": "^1.0.0",
+        "vfile-location": "^2.0.0",
+        "xtend": "^4.0.1"
+      }
+    },
+    "remark-stringify": {
+      "version": "6.0.4",
+      "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz",
+      "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==",
+      "dev": true,
+      "requires": {
+        "ccount": "^1.0.0",
+        "is-alphanumeric": "^1.0.0",
+        "is-decimal": "^1.0.0",
+        "is-whitespace-character": "^1.0.0",
+        "longest-streak": "^2.0.1",
+        "markdown-escapes": "^1.0.0",
+        "markdown-table": "^1.1.0",
+        "mdast-util-compact": "^1.0.0",
+        "parse-entities": "^1.0.2",
+        "repeat-string": "^1.5.4",
+        "state-toggle": "^1.0.0",
+        "stringify-entities": "^1.0.1",
+        "unherit": "^1.0.4",
+        "xtend": "^4.0.1"
+      }
+    },
     "remove-trailing-separator": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
@@ -8049,6 +8657,12 @@
         "is-finite": "^1.0.0"
       }
     },
+    "replace-ext": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+      "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+      "dev": true
+    },
     "request": {
       "version": "2.88.0",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
@@ -8139,6 +8753,11 @@
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "dev": true
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "resolve": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
@@ -8760,6 +9379,17 @@
       "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
       "dev": true
     },
+    "slice-ansi": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.0",
+        "astral-regex": "^1.0.0",
+        "is-fullwidth-code-point": "^2.0.0"
+      }
+    },
     "slide": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
@@ -9090,6 +9720,12 @@
         }
       }
     },
+    "specificity": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz",
+      "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==",
+      "dev": true
+    },
     "split-string": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
@@ -9137,6 +9773,12 @@
       "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==",
       "dev": true
     },
+    "state-toggle": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz",
+      "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==",
+      "dev": true
+    },
     "static-extend": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
@@ -9329,6 +9971,18 @@
         "safe-buffer": "~5.1.0"
       }
     },
+    "stringify-entities": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz",
+      "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==",
+      "dev": true,
+      "requires": {
+        "character-entities-html4": "^1.0.0",
+        "character-entities-legacy": "^1.0.0",
+        "is-alphanumerical": "^1.0.0",
+        "is-hexadecimal": "^1.0.0"
+      }
+    },
     "strip-ansi": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz",
@@ -9369,6 +10023,339 @@
         "schema-utils": "^1.0.0"
       }
     },
+    "style-search": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
+      "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
+      "dev": true
+    },
+    "stylelint": {
+      "version": "9.10.1",
+      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-9.10.1.tgz",
+      "integrity": "sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ==",
+      "dev": true,
+      "requires": {
+        "autoprefixer": "^9.0.0",
+        "balanced-match": "^1.0.0",
+        "chalk": "^2.4.1",
+        "cosmiconfig": "^5.0.0",
+        "debug": "^4.0.0",
+        "execall": "^1.0.0",
+        "file-entry-cache": "^4.0.0",
+        "get-stdin": "^6.0.0",
+        "global-modules": "^2.0.0",
+        "globby": "^9.0.0",
+        "globjoin": "^0.1.4",
+        "html-tags": "^2.0.0",
+        "ignore": "^5.0.4",
+        "import-lazy": "^3.1.0",
+        "imurmurhash": "^0.1.4",
+        "known-css-properties": "^0.11.0",
+        "leven": "^2.1.0",
+        "lodash": "^4.17.4",
+        "log-symbols": "^2.0.0",
+        "mathml-tag-names": "^2.0.1",
+        "meow": "^5.0.0",
+        "micromatch": "^3.1.10",
+        "normalize-selector": "^0.2.0",
+        "pify": "^4.0.0",
+        "postcss": "^7.0.13",
+        "postcss-html": "^0.36.0",
+        "postcss-jsx": "^0.36.0",
+        "postcss-less": "^3.1.0",
+        "postcss-markdown": "^0.36.0",
+        "postcss-media-query-parser": "^0.2.3",
+        "postcss-reporter": "^6.0.0",
+        "postcss-resolve-nested-selector": "^0.1.1",
+        "postcss-safe-parser": "^4.0.0",
+        "postcss-sass": "^0.3.5",
+        "postcss-scss": "^2.0.0",
+        "postcss-selector-parser": "^3.1.0",
+        "postcss-syntax": "^0.36.2",
+        "postcss-value-parser": "^3.3.0",
+        "resolve-from": "^4.0.0",
+        "signal-exit": "^3.0.2",
+        "slash": "^2.0.0",
+        "specificity": "^0.4.1",
+        "string-width": "^3.0.0",
+        "style-search": "^0.1.0",
+        "sugarss": "^2.0.0",
+        "svg-tags": "^1.0.0",
+        "table": "^5.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
+        },
+        "camelcase-keys": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
+          "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^4.1.0",
+            "map-obj": "^2.0.0",
+            "quick-lru": "^1.0.0"
+          }
+        },
+        "cosmiconfig": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz",
+          "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==",
+          "dev": true,
+          "requires": {
+            "import-fresh": "^2.0.0",
+            "is-directory": "^0.3.1",
+            "js-yaml": "^3.13.0",
+            "parse-json": "^4.0.0"
+          }
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+          "dev": true,
+          "requires": {
+            "locate-path": "^2.0.0"
+          }
+        },
+        "get-stdin": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
+          "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
+          "dev": true
+        },
+        "global-modules": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+          "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+          "dev": true,
+          "requires": {
+            "global-prefix": "^3.0.0"
+          }
+        },
+        "global-prefix": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+          "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+          "dev": true,
+          "requires": {
+            "ini": "^1.3.5",
+            "kind-of": "^6.0.2",
+            "which": "^1.3.1"
+          }
+        },
+        "ignore": {
+          "version": "5.0.6",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.6.tgz",
+          "integrity": "sha512-/+hp3kUf/Csa32ktIaj0OlRqQxrgs30n62M90UBpNd9k+ENEch5S+hmbW3DtcJGz3sYFTh4F3A6fQ0q7KWsp4w==",
+          "dev": true
+        },
+        "indent-string": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+          "dev": true
+        },
+        "js-yaml": {
+          "version": "3.13.0",
+          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz",
+          "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==",
+          "dev": true,
+          "requires": {
+            "argparse": "^1.0.7",
+            "esprima": "^4.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+          "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+          "dev": true,
+          "requires": {
+            "p-locate": "^2.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "map-obj": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz",
+          "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=",
+          "dev": true
+        },
+        "meow": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz",
+          "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==",
+          "dev": true,
+          "requires": {
+            "camelcase-keys": "^4.0.0",
+            "decamelize-keys": "^1.0.0",
+            "loud-rejection": "^1.0.0",
+            "minimist-options": "^3.0.1",
+            "normalize-package-data": "^2.3.4",
+            "read-pkg-up": "^3.0.0",
+            "redent": "^2.0.0",
+            "trim-newlines": "^2.0.0",
+            "yargs-parser": "^10.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+          "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+          "dev": true,
+          "requires": {
+            "p-try": "^1.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+          "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+          "dev": true,
+          "requires": {
+            "p-limit": "^1.1.0"
+          }
+        },
+        "p-try": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+          "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+          "dev": true
+        },
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        },
+        "postcss-selector-parser": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz",
+          "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+          "dev": true,
+          "requires": {
+            "dot-prop": "^4.1.1",
+            "indexes-of": "^1.0.1",
+            "uniq": "^1.0.1"
+          }
+        },
+        "read-pkg-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
+          "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
+          "dev": true,
+          "requires": {
+            "find-up": "^2.0.0",
+            "read-pkg": "^3.0.0"
+          }
+        },
+        "redent": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
+          "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
+          "dev": true,
+          "requires": {
+            "indent-string": "^3.0.0",
+            "strip-indent": "^2.0.0"
+          }
+        },
+        "resolve-from": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+          "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        },
+        "strip-indent": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+          "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+          "dev": true
+        },
+        "trim-newlines": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
+          "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=",
+          "dev": true
+        },
+        "yargs-parser": {
+          "version": "10.1.0",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
+          "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^4.1.0"
+          }
+        }
+      }
+    },
+    "stylelint-config-recommended": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz",
+      "integrity": "sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA==",
+      "dev": true
+    },
+    "stylelint-config-recommended-scss": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-3.2.0.tgz",
+      "integrity": "sha512-M8BFHMRf8KNz5EQPKJd8nMCGmBd2o5coDEObfHVbEkyLDgjIf1V+U5dHjaGgvhm0zToUxshxN+Gc5wpbOOew4g==",
+      "dev": true,
+      "requires": {
+        "stylelint-config-recommended": "^2.0.0"
+      }
+    },
+    "stylelint-scss": {
+      "version": "3.5.4",
+      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.5.4.tgz",
+      "integrity": "sha512-hEdEOfFXVqxWcUbenBONW/cAw5cJcEDasY8tGwKNAAn1GDHoZO1ATdWpr+iIk325mPGIQqVb1sUxsRxuL70trw==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.11",
+        "postcss-media-query-parser": "^0.2.3",
+        "postcss-resolve-nested-selector": "^0.1.1",
+        "postcss-selector-parser": "^5.0.0",
+        "postcss-value-parser": "^3.3.1"
+      }
+    },
     "stylus": {
       "version": "0.54.5",
       "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
@@ -9414,6 +10401,15 @@
         }
       }
     },
+    "sugarss": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz",
+      "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==",
+      "dev": true,
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
     "supports-color": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
@@ -9423,12 +10419,58 @@
         "has-flag": "^3.0.0"
       }
     },
+    "svg-tags": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+      "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
+      "dev": true
+    },
     "symbol-tree": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
       "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=",
       "dev": true
     },
+    "table": {
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz",
+      "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.9.1",
+        "lodash": "^4.17.11",
+        "slice-ansi": "^2.1.0",
+        "string-width": "^3.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        }
+      }
+    },
     "tapable": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz",
@@ -9485,11 +10527,6 @@
         "require-main-filename": "^1.0.1"
       }
     },
-    "tether": {
-      "version": "1.4.5",
-      "resolved": "https://registry.npmjs.org/tether/-/tether-1.4.5.tgz",
-      "integrity": "sha512-fysT1Gug2wbRi7a6waeu39yVDwiNtvwj5m9eRD+qZDSHKNghLo6KqP/U3yM2ap6TNUL2skjXGJaJJTJqoC31vw=="
-    },
     "throat": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
@@ -9606,6 +10643,12 @@
       "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==",
       "dev": true
     },
+    "trim": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+      "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=",
+      "dev": true
+    },
     "trim-newlines": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
@@ -9618,6 +10661,18 @@
       "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
       "dev": true
     },
+    "trim-trailing-lines": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz",
+      "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==",
+      "dev": true
+    },
+    "trough": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz",
+      "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==",
+      "dev": true
+    },
     "true-case-path": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
@@ -9793,6 +10848,11 @@
         "mime-types": "~2.1.18"
       }
     },
+    "typed-styles": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz",
+      "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q=="
+    },
     "typedarray": {
       "version": "0.0.6",
       "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -9821,6 +10881,32 @@
         "source-map": "~0.6.1"
       }
     },
+    "unherit": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz",
+      "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "xtend": "^4.0.1"
+      }
+    },
+    "unified": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz",
+      "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==",
+      "dev": true,
+      "requires": {
+        "@types/unist": "^2.0.0",
+        "@types/vfile": "^3.0.0",
+        "bail": "^1.0.0",
+        "extend": "^3.0.0",
+        "is-plain-obj": "^1.1.0",
+        "trough": "^1.0.0",
+        "vfile": "^3.0.0",
+        "x-is-string": "^0.1.0"
+      }
+    },
     "union-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
@@ -9880,6 +10966,54 @@
         "imurmurhash": "^0.1.4"
       }
     },
+    "unist-util-find-all-after": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz",
+      "integrity": "sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w==",
+      "dev": true,
+      "requires": {
+        "unist-util-is": "^2.0.0"
+      }
+    },
+    "unist-util-is": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz",
+      "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==",
+      "dev": true
+    },
+    "unist-util-remove-position": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz",
+      "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==",
+      "dev": true,
+      "requires": {
+        "unist-util-visit": "^1.1.0"
+      }
+    },
+    "unist-util-stringify-position": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz",
+      "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==",
+      "dev": true
+    },
+    "unist-util-visit": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz",
+      "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==",
+      "dev": true,
+      "requires": {
+        "unist-util-visit-parents": "^2.0.0"
+      }
+    },
+    "unist-util-visit-parents": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz",
+      "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==",
+      "dev": true,
+      "requires": {
+        "unist-util-is": "^2.1.2"
+      }
+    },
     "universalify": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -10074,6 +11208,41 @@
         "extsprintf": "^1.2.0"
       }
     },
+    "vfile": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz",
+      "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==",
+      "dev": true,
+      "requires": {
+        "is-buffer": "^2.0.0",
+        "replace-ext": "1.0.0",
+        "unist-util-stringify-position": "^1.0.0",
+        "vfile-message": "^1.0.0"
+      },
+      "dependencies": {
+        "is-buffer": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+          "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
+          "dev": true
+        }
+      }
+    },
+    "vfile-location": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz",
+      "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==",
+      "dev": true
+    },
+    "vfile-message": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz",
+      "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==",
+      "dev": true,
+      "requires": {
+        "unist-util-stringify-position": "^1.1.1"
+      }
+    },
     "vm-browserify": {
       "version": "0.0.4",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
@@ -10502,6 +11671,15 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
     },
+    "write": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+      "dev": true,
+      "requires": {
+        "mkdirp": "^0.5.1"
+      }
+    },
     "write-file-atomic": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz",
@@ -10522,6 +11700,12 @@
         "async-limiter": "~1.0.0"
       }
     },
+    "x-is-string": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz",
+      "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=",
+      "dev": true
+    },
     "xml-name-validator": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
diff --git a/web-console/package.json b/web-console/package.json
index 7890282..6264842 100644
--- a/web-console/package.json
+++ b/web-console/package.json
@@ -1,6 +1,6 @@
 {
   "name": "web-console",
-  "version": "0.14.0",
+  "version": "0.15.0",
   "description": "A web console for Apache Druid",
   "author": "Imply Data Inc.",
   "license": "Apache-2.0",
@@ -20,7 +20,7 @@
     "stylelint": "stylelint 'src/**/*.scss'"
   },
   "dependencies": {
-    "@blueprintjs/core": "1.0.1",
+    "@blueprintjs/core": "^3.15.0",
     "axios": "^0.18.0",
     "brace": "^0.11.1",
     "classnames": "^2.2.6",
@@ -31,10 +31,8 @@
     "hjson": "^3.1.2",
     "lodash.debounce": "^4.0.8",
     "numeral": "^2.0.6",
-    "prop-types": "^15.7.2",
     "react": "^16.8.3",
     "react-ace": "^6.4.0",
-    "react-addons-css-transition-group": "^15.6.2",
     "react-dom": "^16.8.3",
     "react-router": "^4.3.1",
     "react-router-dom": "^4.3.1",
diff --git a/web-console/script/build b/web-console/script/build
index cbc9092..3bb9bc1 100755
--- a/web-console/script/build
+++ b/web-console/script/build
@@ -23,10 +23,6 @@ cp -r ./node_modules/druid-console/coordinator-console .
 cp -r ./node_modules/druid-console/pages .
 cp ./node_modules/druid-console/index.html .
 
-echo "Copying blueprint assets in..."
-sed 's|url("assets|url("/assets|g' "./node_modules/@blueprintjs/core/dist/blueprint.css" > lib/blueprint.css
-cp -r "./node_modules/@blueprintjs/core/dist/assets" .
-
 echo "Adding SQL function doc..."
 PATH="./target/node:$PATH" ./script/create-sql-function-doc
 
diff --git a/web-console/script/clean b/web-console/script/clean
index fd51cf8..c08a5c2 100755
--- a/web-console/script/clean
+++ b/web-console/script/clean
@@ -22,5 +22,4 @@ rm -rf \
   coordinator-console \
   pages \
   public \
-  assets \
   index.html
diff --git a/web-console/script/cp-to b/web-console/script/cp-to
index d2bdeb7..81240ff 100755
--- a/web-console/script/cp-to
+++ b/web-console/script/cp-to
@@ -24,4 +24,3 @@ cp -r coordinator-console "$1"
 cp -r old-console "$1"
 cp -r pages "$1"
 cp -r public "$1"
-cp -r assets "$1"
diff --git a/web-console/src/bootstrap/react-table-defaults.tsx b/web-console/src/bootstrap/react-table-defaults.tsx
index edb776c..b7ecf46 100644
--- a/web-console/src/bootstrap/react-table-defaults.tsx
+++ b/web-console/src/bootstrap/react-table-defaults.tsx
@@ -25,7 +25,7 @@ import { countBy, makeTextFilter } from '../utils';
 
 class FullButton extends React.Component {
   render() {
-    return <Button className="pt-fill" {...this.props}/>;
+    return <Button fill {...this.props}/>;
   }
 }
 
diff --git a/web-console/src/components/auto-form.tsx b/web-console/src/components/auto-form.tsx
index 686a267..aad21e0 100644
--- a/web-console/src/components/auto-form.tsx
+++ b/web-console/src/components/auto-form.tsx
@@ -17,9 +17,10 @@
  */
 
 import { InputGroup } from "@blueprintjs/core";
+import { FormGroup, HTMLSelect, NumericInput, TagInput } from "@blueprintjs/core";
 import * as React from 'react';
 
-import { FormGroup, HTMLSelect, JSONInput, NumericInput, TagInput } from "../components/filler";
+import { JSONInput } from './json-input';
 
 import "./auto-form.scss";
 
diff --git a/web-console/src/components/filler.tsx b/web-console/src/components/filler.tsx
deleted file mode 100644
index 7df1594..0000000
--- a/web-console/src/components/filler.tsx
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 { Button, Collapse } from '@blueprintjs/core';
-import classNames from 'classnames';
-import * as React from 'react';
-import AceEditor from "react-ace";
-
-import { parseStringToJSON, stringifyJSON, validJson } from "../utils";
-
-import './filler.scss';
-
-export const IconNames = {
-  ERROR: "error" as "error",
-  PLUS: "plus" as "plus",
-  REFRESH: "refresh" as "refresh",
-  APPLICATION: "application" as "application",
-  GRAPH: "graph" as "graph",
-  MAP: "map" as "map",
-  TH: "th" as "th",
-  USER: "user" as "user",
-  GIT_BRANCH: "git-branch" as "git-branch",
-  COG: "cog" as "cog",
-  MULTI_SELECT: "multi-select" as "multi-select",
-  STACKED_CHART: "stacked-chart" as "stacked-chart",
-  GANTT_CHART: "gantt-chart" as "gantt-chart",
-  DATABASE: "database" as "database",
-  SETTINGS: "settings" as "settings",
-  HELP: "help" as "help",
-  SHARE: "share" as "share",
-  CROSS: "cross" as "cross",
-  ARROW_LEFT: "arrow-left" as "arrow-left",
-  CARET_RIGHT: "caret-right" as "caret-right",
-  TICK: "tick" as "tick",
-  ARROW_RIGHT: "arrow-right" as "arrow-right",
-  TRASH: "trash" as "trash",
-  CARET_DOWN: "caret-down" as "caret-down",
-  ARROW_UP: "arrow-up" as "arrow-up",
-  ARROW_DOWN: "arrow-down" as "arrow-down",
-  PROPERTIES: "properties" as "properties",
-  BUILD: "build" as "build",
-  WRENCH: "wrench" as "wrench"
-};
-export type IconNames = typeof IconNames[keyof typeof IconNames];
-
-export class H5 extends React.Component<{}, {}> {
-  render() {
-    const { children } = this.props;
-    return <h5>{children}</h5>;
-  }
-}
-
-export class Card extends React.Component<{ interactive?: boolean }, {}> {
-  render() {
-    const { interactive, children } = this.props;
-    return <div className={classNames("pt-card", { 'pt-interactive': interactive })}>
-      {children}
-    </div>;
-  }
-}
-
-export class Icon extends React.Component<{ icon: string, color?: string }, {}> {
-  render() {
-    const { color, icon } = this.props;
-    return <span className={classNames('pt-icon-standard', 'pt-icon-' + icon)} style={{ color }}/>;
-  }
-}
-
-export class ControlGroup extends React.Component<{}, {}> {
-  render() {
-    return <div className="pt-control-group" {...this.props}/>;
-  }
-}
-
-export class ButtonGroup extends React.Component<{ vertical?: boolean, fixed?: boolean }, {}> {
-  render() {
-    const { vertical, fixed, children } = this.props;
-    return <div className={classNames("pt-button-group", { 'pt-vertical': vertical, 'pt-fixed': fixed })}>
-      {children}
-    </div>;
-  }
-}
-
-export class Label extends React.Component<{}, {}> {
-  render() {
-    const { children } = this.props;
-    return <label className="pt-label">{children}</label>;
-  }
-}
-
-export class FormGroup extends React.Component<{ className?: string, label?: string }, {}> {
-  render() {
-    const { className, label, children } = this.props;
-    return <div className={classNames("form-group", className)}>
-      {label ? <Label>{label}</Label> : null}
-      {children}
-    </div>;
-  }
-}
-
-export const Alignment = {
-  LEFT: "left" as "left",
-  RIGHT: "right" as "right"
-};
-export type Alignment = typeof Alignment[keyof typeof Alignment];
-
-export class Navbar extends React.Component<{ className?: string }, {}> {
-  render() {
-    const { className, children } = this.props;
-    return <nav className={classNames("pt-navbar", className)}>
-      {children}
-    </nav>;
-  }
-}
-
-export class NavbarGroup extends React.Component<{ align: Alignment }, {}> {
-  render() {
-    const { align, children } = this.props;
-    return <div className={classNames('pt-navbar-group', 'pt-align-' + align)}>
-      {children}
-    </div>;
-  }
-}
-
-export class NavbarDivider extends React.Component<{}, {}> {
-  render() {
-    return <span className="pt-navbar-divider"/>;
-  }
-}
-
-export class HTMLSelect extends React.Component<{ key?: string; style?: any; onChange: any; value: any; fill?: boolean }, {}> {
-  render() {
-    const { key, style, onChange, value, fill, children } = this.props;
-    return <div className={classNames("pt-select", { 'pt-fill': fill })} key={key} style={style}>
-      <select onChange={onChange} value={value}>{children}</select>
-    </div>;
-  }
-}
-
-export class TextArea extends React.Component<{ className?: string; onChange?: any; value?: string, readOnly?: boolean, style?: any}, {}> {
-  render() {
-    const { className, value, onChange, readOnly, style } = this.props;
-    return <textarea
-      readOnly={readOnly}
-      className={classNames("pt-input", className)}
-      value={value}
-      onChange={onChange}
-      style={style}
-    />;
-  }
-}
-
-export interface NumericInputProps {
-  value: number | null;
-  onValueChange: any;
-  min?: number;
-  max?: number;
-  stepSize?: number;
-  majorStepSize?: number;
-}
-
-export class NumericInput extends React.Component<NumericInputProps, { stringValue: string }> {
-
-  static defaultProps = {
-    stepSize: 1,
-    majorStepSize: 10
-  };
-
-  constructor(props: NumericInputProps) {
-    super(props);
-    this.state = {
-      stringValue: typeof props.value === 'number' ? String(props.value) : ''
-    };
-  }
-
-  private constrain(n: number): number {
-    const { min, max } = this.props;
-    if (typeof min === 'number') n = Math.max(n, min);
-    if (typeof max === 'number') n = Math.min(n, max);
-    return n;
-  }
-
-  private handleChange = (e: any) => {
-    let stringValue = e.target.value.replace(/[^\d.+-]/g, '');
-    let numValue = parseFloat(stringValue);
-    if (isNaN(numValue)) {
-      this.setState({ stringValue });
-    } else {
-      numValue = this.constrain(numValue);
-      stringValue = String(numValue);
-      this.setState({ stringValue });
-      this.props.onValueChange(numValue);
-    }
-  }
-
-  private handleClick = (e: any, direction: number) => {
-    const { stepSize, majorStepSize } = this.props;
-    const { stringValue } = this.state;
-    const diff = direction * (e.shiftKey ? majorStepSize as number : stepSize as number);
-    const numValue = this.constrain((parseFloat(stringValue) || 0) + diff);
-    this.setState({ stringValue: String(numValue) });
-    this.props.onValueChange(numValue);
-  }
-
-  render() {
-    const { stringValue } = this.state;
-
-    return <ControlGroup>
-      <input className="pt-input" value={stringValue} onChange={this.handleChange}/>
-      <ButtonGroup fixed>
-        <Button iconName="caret-up" onClick={(e: any) => this.handleClick(e, +1)}/>
-        <Button iconName="caret-down" onClick={(e: any) => this.handleClick(e, -1)}/>
-      </ButtonGroup>
-    </ControlGroup>;
-  }
-}
-
-export interface TagInputProps {
-  values: string[];
-  onChange: any;
-  fill?: boolean;
-}
-
-export class TagInput extends React.Component<TagInputProps, { stringValue: string }> {
-  constructor(props: TagInputProps) {
-    super(props);
-    this.state = {
-      stringValue: Array.isArray(props.values) ? props.values.join(', ') : ''
-    };
-  }
-
-  handleChange = (e: any) => {
-    const stringValue = e.target.value;
-    const newValues = stringValue.split(',').map((v: string) => v.trim());
-    const newValuesFiltered = newValues.filter(Boolean);
-    this.setState({
-      stringValue: newValues.length === newValuesFiltered.length ? newValues.join(', ') : stringValue
-    });
-    this.props.onChange(newValuesFiltered);
-  }
-
-  render() {
-    const { fill } = this.props;
-    const { stringValue } = this.state;
-    return <input
-      className={classNames("pt-input", {'pt-fill': fill })}
-      value={stringValue}
-      onChange={this.handleChange}
-    />;
-  }
-}
-
-interface JSONInputProps extends React.Props<any> {
-  onChange: (newJSONValue: any) => void;
-  value: any;
-  updateInputValidity?: (valueValid: boolean) => void;
-  focus?: boolean;
-  width?: string;
-  height?: string;
-}
-
-interface JSONInputState {
-  stringValue: string;
-}
-
-export class JSONInput extends React.Component<JSONInputProps, JSONInputState> {
-  constructor(props: JSONInputProps) {
-    super(props);
-    this.state = {
-      stringValue: ""
-    };
-  }
-
-  componentDidMount(): void {
-    const { value } = this.props;
-    const stringValue = stringifyJSON(value);
-    this.setState({
-      stringValue
-    });
-  }
-
-  componentWillReceiveProps(nextProps: JSONInputProps): void {
-    if (JSON.stringify(nextProps.value) !== JSON.stringify(this.props.value)) {
-      this.setState({
-        stringValue: stringifyJSON(nextProps.value)
-      });
-    }
-  }
-
-  render() {
-    const { onChange, updateInputValidity, focus, width, height } = this.props;
-    const { stringValue } = this.state;
-    return <AceEditor
-      key={"hjson"}
-      mode={"hjson"}
-      theme="solarized_dark"
-      name="ace-editor"
-      onChange={(e: string) => {
-        this.setState({stringValue: e});
-        if (validJson(e) || e === "") onChange(parseStringToJSON(e));
-        if (updateInputValidity) updateInputValidity(validJson(e) || e === '');
-      }}
-      focus={focus}
-      fontSize={12}
-      width={width || '100%'}
-      height={height || "8vh"}
-      showPrintMargin={false}
-      showGutter={false}
-      value={stringValue}
-      editorProps={{
-        $blockScrolling: Infinity
-      }}
-      setOptions={{
-        enableBasicAutocompletion: false,
-        enableLiveAutocompletion: false,
-        showLineNumbers: false,
-        tabSize: 2
-      }}
-    />;
-  }
-}
-
-interface JSONCollapseProps extends React.Props<any> {
-  stringValue: string;
-  buttonText: string;
-}
-
-interface JSONCollapseState {
-  isOpen: boolean;
-}
-
-export class JSONCollapse extends React.Component<JSONCollapseProps, JSONCollapseState> {
-  constructor(props: any) {
-    super(props);
-    this.state = {
-      isOpen: false
-    };
-  }
-
-  render() {
-    const { stringValue, buttonText} = this.props;
-    const { isOpen } = this.state;
-    const prettyValue = JSON.stringify(JSON.parse(stringValue), undefined, 2);
-    return <div className={"json-collapse"}>
-      <Button
-        className={`pt-minimal ${isOpen ? " pt-active" : ""}`}
-        onClick={() => this.setState({isOpen: !isOpen})}
-        text={buttonText}
-      />
-      <div>
-        <Collapse isOpen={isOpen}>
-          <TextArea
-            readOnly
-            value={prettyValue}
-          />
-        </Collapse>
-      </div>
-    </div>;
-  }
-}
diff --git a/web-console/src/components/header-bar.scss b/web-console/src/components/header-bar.scss
index 32a17a7..5723db1 100644
--- a/web-console/src/components/header-bar.scss
+++ b/web-console/src/components/header-bar.scss
@@ -33,12 +33,12 @@
     }
   }
 
-  .config-popover .pt-popover-content,
-  .legacy-popover .pt-popover-content {
+  .config-popover .bp3-popover-content,
+  .legacy-popover .bp3-popover-content {
     width: 240px;
   }
 
-  .help-popover .pt-popover-content {
+  .help-popover .bp3-popover-content {
     width: 180px;
   }
 }
diff --git a/web-console/src/components/header-bar.tsx b/web-console/src/components/header-bar.tsx
index 821f1e3..f0f5853 100644
--- a/web-console/src/components/header-bar.tsx
+++ b/web-console/src/components/header-bar.tsx
@@ -16,11 +16,11 @@
  * limitations under the License.
  */
 
-import { AnchorButton, Button, Classes, Menu, MenuItem, Popover, Position } from "@blueprintjs/core";
+import { Alignment, AnchorButton, Button, Classes, Menu, MenuItem, Navbar, NavbarDivider, NavbarGroup, Popover, Position } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import classNames from 'classnames';
 import * as React from 'react';
 
-import { Alignment, IconNames, Navbar, NavbarDivider, NavbarGroup } from "../components/filler";
 import { AboutDialog } from "../dialogs/about-dialog";
 import { CoordinatorDynamicConfigDialog } from '../dialogs/coordinator-dynamic-config';
 import { OverlordDynamicConfigDialog } from "../dialogs/overlord-dynamic-config";
@@ -110,21 +110,21 @@ export class HeaderBar extends React.Component<HeaderBarProps, HeaderBarState> {
     const { aboutDialogOpen, coordinatorDynamicConfigDialogOpen, overlordDynamicConfigDialogOpen } = this.state;
 
     const legacyMenu = <Menu>
-      <MenuItem iconName={IconNames.GRAPH} text="Legacy coordinator console" href={LEGACY_COORDINATOR_CONSOLE} target="_blank" />
-      <MenuItem iconName={IconNames.MAP} text="Legacy overlord console" href={LEGACY_OVERLORD_CONSOLE} target="_blank" />
+      <MenuItem icon={IconNames.GRAPH} text="Legacy coordinator console" href={LEGACY_COORDINATOR_CONSOLE} target="_blank" />
+      <MenuItem icon={IconNames.MAP} text="Legacy overlord console" href={LEGACY_OVERLORD_CONSOLE} target="_blank" />
     </Menu>;
 
     const helpMenu = <Menu>
-      <MenuItem iconName={IconNames.GRAPH} text="About" onClick={() => this.setState({ aboutDialogOpen: true })} />
-      <MenuItem iconName={IconNames.TH} text="Docs" href={DRUID_DOCS} target="_blank" />
-      <MenuItem iconName={IconNames.USER} text="User group" href={DRUID_USER_GROUP} target="_blank" />
-      <MenuItem iconName={IconNames.GIT_BRANCH} text="GitHub" href={DRUID_GITHUB} target="_blank" />
+      <MenuItem icon={IconNames.GRAPH} text="About" onClick={() => this.setState({ aboutDialogOpen: true })} />
+      <MenuItem icon={IconNames.TH} text="Docs" href={DRUID_DOCS} target="_blank" />
+      <MenuItem icon={IconNames.USER} text="User group" href={DRUID_USER_GROUP} target="_blank" />
+      <MenuItem icon={IconNames.GIT_BRANCH} text="GitHub" href={DRUID_GITHUB} target="_blank" />
     </Menu>;
 
     const configMenu = <Menu>
-      <MenuItem iconName={IconNames.COG} text="Coordinator dynamic config" onClick={() => this.setState({ coordinatorDynamicConfigDialogOpen: true })}/>
-      <MenuItem iconName={IconNames.WRENCH} text="Overlord dynamic config" onClick={() => this.setState({ overlordDynamicConfigDialogOpen: true })}/>
-      <MenuItem iconName={IconNames.PROPERTIES} className={classNames(Classes.MINIMAL, { 'pt-active': active === 'lookups' })} text="Lookups" href="#lookups"/>
+      <MenuItem icon={IconNames.COG} text="Coordinator dynamic config" onClick={() => this.setState({ coordinatorDynamicConfigDialogOpen: true })}/>
+      <MenuItem icon={IconNames.WRENCH} text="Overlord dynamic config" onClick={() => this.setState({ overlordDynamicConfigDialogOpen: true })}/>
+      <MenuItem icon={IconNames.PROPERTIES} active={active === 'lookups'} text="Lookups" href="#lookups"/>
     </Menu>;
 
     return <Navbar className="header-bar">
@@ -133,22 +133,22 @@ export class HeaderBar extends React.Component<HeaderBarProps, HeaderBarState> {
           {this.renderLogo()}
         </a>
         <NavbarDivider />
-        <AnchorButton className={classNames(Classes.MINIMAL, { 'pt-active': active === 'datasources' })} iconName={IconNames.MULTI_SELECT} text="Datasources" href="#datasources" />
-        <AnchorButton className={classNames(Classes.MINIMAL, { 'pt-active': active === 'segments' })} iconName={IconNames.STACKED_CHART} text="Segments" href="#segments" />
-        <AnchorButton className={classNames(Classes.MINIMAL, { 'pt-active': active === 'tasks' })} iconName={IconNames.GANTT_CHART} text="Tasks" href="#tasks" />
-        <AnchorButton className={classNames(Classes.MINIMAL, { 'pt-active': active === 'servers' })} iconName={IconNames.DATABASE} text="Data servers" href="#servers" />
+        <AnchorButton minimal active={active === 'datasources'} icon={IconNames.MULTI_SELECT} text="Datasources" href="#datasources" />
+        <AnchorButton minimal active={active === 'segments'} icon={IconNames.STACKED_CHART} text="Segments" href="#segments" />
+        <AnchorButton minimal active={active === 'tasks'} icon={IconNames.GANTT_CHART} text="Tasks" href="#tasks" />
+        <AnchorButton minimal active={active === 'servers'} icon={IconNames.DATABASE} text="Data servers" href="#servers" />
         <NavbarDivider />
-        <AnchorButton className={classNames(Classes.MINIMAL, { 'pt-active': active === 'sql' })} iconName={IconNames.APPLICATION} text="SQL" href="#sql" />
+        <AnchorButton minimal active={active === 'sql'} icon={IconNames.APPLICATION} text="SQL" href="#sql" />
         <Popover className="config-popover" content={configMenu} position={Position.BOTTOM_LEFT}>
-          <Button className={Classes.MINIMAL} iconName={IconNames.SETTINGS} text="Config"/>
+          <Button className={Classes.MINIMAL} icon={IconNames.SETTINGS} text="Config"/>
         </Popover>
       </NavbarGroup>
       <NavbarGroup align={Alignment.RIGHT}>
         <Popover className="legacy-popover" content={legacyMenu} position={Position.BOTTOM_RIGHT}>
-          <Button className={Classes.MINIMAL} iconName={IconNames.SHARE} text="Legacy" />
+          <Button className={Classes.MINIMAL} icon={IconNames.SHARE} text="Legacy" />
         </Popover>
         <Popover className="help-popover" content={helpMenu} position={Position.BOTTOM_RIGHT}>
-          <Button className={Classes.MINIMAL} iconName={IconNames.HELP} text="Help" />
+          <Button className={Classes.MINIMAL} icon={IconNames.HELP} text="Help" />
         </Popover>
       </NavbarGroup>
       { aboutDialogOpen ? <AboutDialog
diff --git a/web-console/src/components/json-collapse.tsx b/web-console/src/components/json-collapse.tsx
new file mode 100644
index 0000000..7fd2c5f
--- /dev/null
+++ b/web-console/src/components/json-collapse.tsx
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 { Button, Collapse, TextArea } from '@blueprintjs/core';
+import classNames from 'classnames';
+import * as React from 'react';
+
+interface JSONCollapseProps extends React.Props<any> {
+  stringValue: string;
+  buttonText: string;
+}
+
+interface JSONCollapseState {
+  isOpen: boolean;
+}
+
+export class JSONCollapse extends React.Component<JSONCollapseProps, JSONCollapseState> {
+  constructor(props: any) {
+    super(props);
+    this.state = {
+      isOpen: false
+    };
+  }
+
+  render() {
+    const { stringValue, buttonText} = this.props;
+    const { isOpen } = this.state;
+    const prettyValue = JSON.stringify(JSON.parse(stringValue), undefined, 2);
+    return <div className={"json-collapse"}>
+      <Button
+        minimal
+        active={isOpen}
+        onClick={() => this.setState({isOpen: !isOpen})}
+        text={buttonText}
+      />
+      <div>
+        <Collapse isOpen={isOpen}>
+          <TextArea
+            readOnly
+            value={prettyValue}
+          />
+        </Collapse>
+      </div>
+    </div>;
+  }
+}
diff --git a/web-console/src/components/json-input.tsx b/web-console/src/components/json-input.tsx
new file mode 100644
index 0000000..01a7936
--- /dev/null
+++ b/web-console/src/components/json-input.tsx
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 * as React from 'react';
+import AceEditor from "react-ace";
+
+import { parseStringToJSON, stringifyJSON, validJson } from "../utils";
+
+interface JSONInputProps extends React.Props<any> {
+  onChange: (newJSONValue: any) => void;
+  value: any;
+  updateInputValidity?: (valueValid: boolean) => void;
+  focus?: boolean;
+  width?: string;
+  height?: string;
+}
+
+interface JSONInputState {
+  stringValue: string;
+}
+
+export class JSONInput extends React.Component<JSONInputProps, JSONInputState> {
+  constructor(props: JSONInputProps) {
+    super(props);
+    this.state = {
+      stringValue: ""
+    };
+  }
+
+  componentDidMount(): void {
+    const { value } = this.props;
+    const stringValue = stringifyJSON(value);
+    this.setState({
+      stringValue
+    });
+  }
+
+  componentWillReceiveProps(nextProps: JSONInputProps): void {
+    if (JSON.stringify(nextProps.value) !== JSON.stringify(this.props.value)) {
+      this.setState({
+        stringValue: stringifyJSON(nextProps.value)
+      });
+    }
+  }
+
+  render() {
+    const { onChange, updateInputValidity, focus, width, height } = this.props;
+    const { stringValue } = this.state;
+    return <AceEditor
+      key={"hjson"}
+      mode={"hjson"}
+      theme="solarized_dark"
+      name="ace-editor"
+      onChange={(e: string) => {
+        this.setState({stringValue: e});
+        if (validJson(e) || e === "") onChange(parseStringToJSON(e));
+        if (updateInputValidity) updateInputValidity(validJson(e) || e === '');
+      }}
+      focus={focus}
+      fontSize={12}
+      width={width || '100%'}
+      height={height || "8vh"}
+      showPrintMargin={false}
+      showGutter={false}
+      value={stringValue}
+      editorProps={{
+        $blockScrolling: Infinity
+      }}
+      setOptions={{
+        enableBasicAutocompletion: false,
+        enableLiveAutocompletion: false,
+        showLineNumbers: false,
+        tabSize: 2
+      }}
+    />;
+  }
+}
diff --git a/web-console/src/components/rule-editor.tsx b/web-console/src/components/rule-editor.tsx
index f13f046..e7a82fb 100644
--- a/web-console/src/components/rule-editor.tsx
+++ b/web-console/src/components/rule-editor.tsx
@@ -16,12 +16,11 @@
  * limitations under the License.
  */
 
-import { Button, Collapse, InputGroup } from "@blueprintjs/core";
+import { Button, Card, Collapse, ControlGroup, FormGroup, HTMLSelect, InputGroup, NumericInput, TagInput } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as React from 'react';
 
-import { Card, ControlGroup, FormGroup, HTMLSelect, IconNames, NumericInput, TagInput } from "../components/filler";
-
 import './rule-editor.scss';
 
 export interface Rule {
@@ -150,7 +149,7 @@ export class RuleEditor extends React.Component<RuleEditorProps, RuleEditorState
     const ruleTiers = Object.keys(tieredReplicants).sort();
     return ruleTiers.map(tier => {
       return <ControlGroup key={tier}>
-        <Button className="pt-minimal" style={{pointerEvents: 'none'}}>Replicants:</Button>
+        <Button minimal style={{pointerEvents: 'none'}}>Replicants:</Button>
         <NumericInput
           value={tieredReplicants[tier]}
           onValueChange={(v: number) => {
@@ -160,7 +159,7 @@ export class RuleEditor extends React.Component<RuleEditorProps, RuleEditorState
           min={1}
           max={256}
         />
-        <Button className="pt-minimal" style={{pointerEvents: 'none'}}>Tier:</Button>
+        <Button minimal style={{pointerEvents: 'none'}}>Tier:</Button>
         <HTMLSelect
           fill
           value={tier}
@@ -175,7 +174,7 @@ export class RuleEditor extends React.Component<RuleEditorProps, RuleEditorState
         <Button
           disabled={ruleTiers.length === 1}
           onClick={() => this.removeTier(tier)}
-          iconName={IconNames.TRASH}
+          icon={IconNames.TRASH}
         />
       </ControlGroup>;
     });
@@ -186,7 +185,7 @@ export class RuleEditor extends React.Component<RuleEditorProps, RuleEditorState
     if (Object.keys(rule.tieredReplicants || {}).length >= Object.keys(tiers).length) return null;
 
     return <FormGroup className="right">
-      <Button onClick={this.addTier} className="pt-minimal" iconName={IconNames.PLUS}>Add a tier</Button>
+      <Button onClick={this.addTier} minimal icon={IconNames.PLUS}>Add a tier</Button>
     </FormGroup>;
   }
 
@@ -213,13 +212,13 @@ export class RuleEditor extends React.Component<RuleEditorProps, RuleEditorState
 
     return <div className="rule-editor">
       <div className="title">
-        <Button className="left pt-minimal" rightIconName={isOpen ? IconNames.CARET_DOWN : IconNames.CARET_RIGHT} onClick={() => this.setState({isOpen: !isOpen})}>
+        <Button className="left" minimal rightIcon={isOpen ? IconNames.CARET_DOWN : IconNames.CARET_RIGHT} onClick={() => this.setState({isOpen: !isOpen})}>
           {RuleEditor.ruleToString(rule)}
         </Button>
         <div className="spacer"/>
-        {moveUp ? <Button className="pt-minimal" iconName={IconNames.ARROW_UP} onClick={moveUp}/> : null}
-        {moveDown ? <Button className="pt-minimal" iconName={IconNames.ARROW_DOWN} onClick={moveDown}/> : null}
-        <Button className="pt-minimal" iconName={IconNames.TRASH} onClick={onDelete}/>
+        {moveUp ? <Button minimal icon={IconNames.ARROW_UP} onClick={moveUp}/> : null}
+        {moveDown ? <Button minimal icon={IconNames.ARROW_DOWN} onClick={moveDown}/> : null}
+        <Button minimal icon={IconNames.TRASH} onClick={onDelete}/>
       </div>
 
       <Collapse isOpen={isOpen}>
diff --git a/web-console/src/components/sql-control.tsx b/web-console/src/components/sql-control.tsx
index 5a2b745..033944b 100644
--- a/web-console/src/components/sql-control.tsx
+++ b/web-console/src/components/sql-control.tsx
@@ -17,6 +17,7 @@
  */
 
 import { Button, Checkbox, Classes, Intent, Popover, Position } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from "axios";
 import * as ace from 'brace';
 import 'brace/ext/language_tools';
@@ -31,8 +32,6 @@ import * as ReactDOMServer from 'react-dom/server';
 import { SQLFunctionDoc } from "../../lib/sql-function-doc";
 import { AppToaster } from "../singletons/toaster";
 
-import { IconNames } from './filler';
-
 import './sql-control.scss';
 
 const langTools = ace.acequire('ace/ext/language_tools');
@@ -205,11 +204,11 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
         }}
       />
       <div className="buttons">
-        <Button rightIconName={IconNames.CARET_RIGHT} onClick={() => onRun(query)}>
+        <Button rightIcon={IconNames.CARET_RIGHT} onClick={() => onRun(query)}>
           {isRune ? 'Rune' : 'Run'}
         </Button>
         <Popover position={Position.BOTTOM_LEFT} content={autoCompletePopover}>
-          <Button className={`${Classes.MINIMAL} pt-icon-more`}/>
+          <Button minimal icon={IconNames.MORE}/>
         </Popover>
       </div>
     </div>;
diff --git a/web-console/src/components/table-column-selection.scss b/web-console/src/components/table-column-selection.scss
index c9755e6..b1cb80a 100644
--- a/web-console/src/components/table-column-selection.scss
+++ b/web-console/src/components/table-column-selection.scss
@@ -17,10 +17,9 @@
  */
 
 .table-column-selection {
-  &.pt-popover-target{
-    position: absolute;
-    right: 0;
-  }
+  position: absolute;
+  right: 0;
+  margin: 0;
 }
 
 // This will be mounted in a portal
@@ -28,7 +27,7 @@
   .form-group {
     margin-bottom: 0;
 
-    .pt-checkbox:last-child {
+    .bp3-checkbox:last-child {
       margin-bottom: 0;
     }
   }
diff --git a/web-console/src/components/table-column-selection.tsx b/web-console/src/components/table-column-selection.tsx
index da67d6b..f24f551 100644
--- a/web-console/src/components/table-column-selection.tsx
+++ b/web-console/src/components/table-column-selection.tsx
@@ -16,11 +16,10 @@
  * limitations under the License.
  */
 
-import { Button, Checkbox, Menu, Popover, Position } from "@blueprintjs/core";
+import { Button, Checkbox, FormGroup, Menu, Popover, Position } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import * as React from 'react';
 
-import { FormGroup, IconNames } from "./filler";
-
 import "./table-column-selection.scss";
 
 interface TableColumnSelectionProps extends React.Props<any> {
@@ -62,7 +61,7 @@ export class TableColumnSelection extends React.Component<TableColumnSelectionPr
       content={checkboxes}
       position={Position.BOTTOM_RIGHT}
     >
-      <Button rightIconName={IconNames.CARET_DOWN} text={"Columns"} />
+      <Button rightIcon={IconNames.CARET_DOWN} text={"Columns"} />
     </Popover>;
   }
 }
diff --git a/web-console/src/console-application.tsx b/web-console/src/console-application.tsx
index 332783f..4d921e0 100644
--- a/web-console/src/console-application.tsx
+++ b/web-console/src/console-application.tsx
@@ -17,6 +17,7 @@
  */
 
 import { Intent } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as classNames from 'classnames';
 import * as React from 'react';
@@ -61,7 +62,7 @@ export class ConsoleApplication extends React.Component<ConsoleApplicationProps,
 
       // Status works but SQL 405s => the SQL endpoint is disabled
       AppToaster.show({
-        iconName: 'error',
+        icon: IconNames.ERROR,
         intent: Intent.DANGER,
         timeout: 120000,
         /* tslint:disable:jsx-alignment */
diff --git a/web-console/src/dialogs/about-dialog.tsx b/web-console/src/dialogs/about-dialog.tsx
index 7f6ddfd..1459709 100644
--- a/web-console/src/dialogs/about-dialog.tsx
+++ b/web-console/src/dialogs/about-dialog.tsx
@@ -17,9 +17,9 @@
  */
 
 import { AnchorButton, Button, Classes, Dialog, Intent } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import * as React from 'react';
 
-import { IconNames } from "../components/filler";
 import { DRUID_COMMUNITY, DRUID_DEVELOPER_GROUP, DRUID_USER_GROUP, DRUID_WEBSITE } from '../variables';
 
 export interface AboutDialogProps extends React.Props<any> {
@@ -40,7 +40,7 @@ export class AboutDialog extends React.Component<AboutDialogProps, AboutDialogSt
 
     /* tslint:disable:jsx-alignment */
     return <Dialog
-      iconName={IconNames.GRAPH}
+      icon={IconNames.GRAPH}
       onClose={onClose}
       title="Apache Druid"
       isOpen
diff --git a/web-console/src/dialogs/async-action-dialog.tsx b/web-console/src/dialogs/async-action-dialog.tsx
index d943741..9dc0dee 100644
--- a/web-console/src/dialogs/async-action-dialog.tsx
+++ b/web-console/src/dialogs/async-action-dialog.tsx
@@ -18,15 +18,16 @@
 
 import {
   Button,
+  ButtonGroup,
   Classes,
   Dialog,
-  Intent,
-  ProgressBar
+  FormGroup,
+  Icon, Intent, NumericInput, ProgressBar, TagInput
 } from "@blueprintjs/core";
+import { IconName } from "@blueprintjs/icons";
 import classNames from 'classnames';
 import * as React from 'react';
 
-import { ButtonGroup, FormGroup, Icon, NumericInput, TagInput } from '../components/filler';
 import { AppToaster } from '../singletons/toaster';
 
 export interface AsyncAlertDialogProps extends React.Props<any> {
@@ -35,7 +36,7 @@ export interface AsyncAlertDialogProps extends React.Props<any> {
   confirmButtonText: string;
   cancelButtonText?: string;
   className?: string;
-  icon?: string;
+  icon?: IconName;
   intent?: Intent;
   successText: string;
   failText: string;
diff --git a/web-console/src/dialogs/compaction-dialog.scss b/web-console/src/dialogs/compaction-dialog.scss
index ee1cf67..b9a461c 100644
--- a/web-console/src/dialogs/compaction-dialog.scss
+++ b/web-console/src/dialogs/compaction-dialog.scss
@@ -17,7 +17,7 @@
  */
 
 .compaction-dialog {
-  &.pt-dialog {
+  &.bp3-dialog {
     top: 5%;
   }
 
diff --git a/web-console/src/dialogs/coordinator-dynamic-config.scss b/web-console/src/dialogs/coordinator-dynamic-config.scss
index d4bb6d9..8032103 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config.scss
+++ b/web-console/src/dialogs/coordinator-dynamic-config.scss
@@ -17,12 +17,12 @@
  */
 
 .coordinator-dynamic-config {
-  &.pt-dialog {
+  &.bp3-dialog {
     margin-top: 5vh;
     top: 5%;
   }
 
-  .pt-dialog-body {
+  .bp3-dialog-body {
     max-height: 70vh;
 
     .auto-form {
diff --git a/web-console/src/dialogs/coordinator-dynamic-config.tsx b/web-console/src/dialogs/coordinator-dynamic-config.tsx
index b7b2b61..4faeef9 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config.tsx
@@ -17,11 +17,11 @@
  */
 
 import { Intent } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
 import axios from 'axios';
 import * as React from 'react';
 
 import { AutoForm } from '../components/auto-form';
-import { IconNames } from '../components/filler';
 import { AppToaster } from '../singletons/toaster';
 import { getDruidErrorMessage, QueryManager } from '../utils';
 
@@ -74,7 +74,7 @@ export class CoordinatorDynamicConfigDialog extends React.Component<CoordinatorD
       config = configResp.data;
     } catch (e) {
       AppToaster.show({
-        iconName: IconNames.ERROR,
+        icon: IconNames.ERROR,
         intent: Intent.DANGER,
         message: `Could not load coordinator dynamic config: ${getDruidErrorMessage(e)}`
       });
@@ -97,7 +97,7 @@ export class CoordinatorDynamicConfigDialog extends React.Component<CoordinatorD
       });
     } catch (e) {
       AppToaster.show({
-        iconName: IconNames.ERROR,
+        icon: IconNames.ERROR,
         intent: Intent.DANGER,
         message: `Could not save coordinator dynamic config: ${getDruidErrorMessage(e)}`
       });
diff --git a/web-console/src/dialogs/history-dialog.scss b/web-console/src/dialogs/history-dialog.scss
index b16ebd0..247e916 100644
--- a/web-console/src/dialogs/history-dialog.scss
+++ b/web-console/src/dialogs/history-dialog.scss
@@ -17,7 +17,7 @@
  */
 
 .history-dialog {
-  &.pt-dialog {
+  &.bp3-dialog {
     width: 600px;
     top: 5%;
   }
@@ -53,7 +53,7 @@
           margin: 5px 0 5px 0;
         }
 
-        .pt-card {
+        .bp3-card {
           padding-bottom: 10px;
         }
 
diff --git a/web-console/src/dialogs/history-dialog.tsx b/web-console/src/dialogs/history-dialog.tsx
index 73ff6fe..6d97c85 100644
--- a/web-console/src/dialogs/history-dialog.tsx
+++ b/web-console/src/dialogs/history-dialog.tsx
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import { Dialog } from "@blueprintjs/core";
+import { Card, Dialog } from "@blueprintjs/core";
 import * as React from "react";
 
-import { Card, JSONCollapse } from "../components/filler";
+import { JSONCollapse } from '../components/json-collapse';
 
 import "./history-dialog.scss";
 
diff --git a/web-console/src/dialogs/lookup-edit-dialog.scss b/web-console/src/dialogs/lookup-edit-dialog.scss
index 3a26abc..08ae56b 100644
--- a/web-console/src/dialogs/lookup-edit-dialog.scss
+++ b/web-console/src/dialogs/lookup-edit-dialog.scss
@@ -19,7 +19,7 @@
 
 
 .lookup-edit-dialog {
-  &.pt-dialog{
+  &.bp3-dialog{
     top: 10vh;
 
     width: 600px;
diff --git a/web-console/src/dialogs/lookup-edit-dialog.tsx b/web-console/src/dialogs/lookup-edit-dialog.tsx
index e32ec5a..be6dd3a 100644
--- a/web-console/src/dialogs/lookup-edit-dialog.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog.tsx
@@ -16,11 +16,10 @@
  * limitations under the License.
  */
 
-import { Button, Classes, Dialog, InputGroup, Intent } from "@blueprintjs/core";
+import { Button, Classes, Dialog, FormGroup, HTMLSelect, InputGroup, Intent } from "@blueprintjs/core";
 import * as React from "react";
 import AceEditor from "react-ace";
 
-import { FormGroup } from "../components/filler";
 import { validJson } from "../utils";
 
 import "./lookup-edit-dialog.scss";
@@ -69,15 +68,11 @@ export class LookupEditDialog extends React.Component<LookupEditDialogProps, Loo
       </FormGroup>;
     } else {
       return <FormGroup className={"lookup-label"} label={"Tier:"}>
-        <div className="pt-select">
-          <select disabled={isEdit} value={lookupTier} onChange={(e: any) => onChange("lookupEditTier", e.target.value)}>
-            {
-              allLookupTiers.map(tier => {
-                return <option key={tier} value={tier}>{tier}</option>;
-              })
-            }
-          </select>
-        </div>
+        <HTMLSelect disabled={isEdit} value={lookupTier} onChange={(e: any) => onChange("lookupEditTier", e.target.value)}>
+          {allLookupTiers.map(tier => (
+            <option key={tier} value={tier}>{tier}</option>
+          ))}
+        </HTMLSelect>
       </FormGroup>;
     }
   }
@@ -110,7 +105,7 @@ export class LookupEditDialog extends React.Component<LookupEditDialogProps, Loo
           value={lookupVersion}
           onChange={(e: any) => onChange("lookupEditVersion", e.target.value)}
           placeholder={"Enter the lookup version"}
-          rightElement={<Button className={"pt-minimal"} text={"Use ISO as version"} onClick={() => this.addISOVersion()} />}
+          rightElement={<Button minimal text={"Use ISO as version"} onClick={() => this.addISOVersion()} />}
         />
       </FormGroup>
 
diff --git a/web-console/src/dialogs/overlord-dynamic-config.scss b/web-console/src/dialogs/overlord-dynamic-config.scss
index 45a87d0..6e676ad 100644
--- a/web-console/src/dialogs/overlord-dynamic-config.scss
+++ b/web-console/src/dialogs/overlord-dynamic-config.scss
@@ -17,13 +17,13 @@
  */
 
 .overlord-dynamic-config {
-  &.pt-dialog {
+  &.bp3-dialog {
     margin-top: 5vh;
     top: 5%;
     width: 600px;
   }
 
-  .pt-dialog-body {
+  .bp3-dialog-body {
     max-height: 70vh;
 
     .auto-form {
diff --git a/web-console/src/dialogs/overlord-dynamic-config.tsx b/web-console/src/dialogs/overlord-dynamic-config.tsx
index f4be905..683cb59 100644
--- a/web-console/src/dialogs/overlord-dynamic-config.tsx
+++ b/web-console/src/dialogs/overlord-dynamic-config.tsx
@@ -17,11 +17,11 @@
  */
 
 import { Intent } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from "axios";
 import * as React from "react";
 
 import { AutoForm } from "../components/auto-form";
-import { IconNames } from "../components/filler";
 import { AppToaster } from "../singletons/toaster";
 import { getDruidErrorMessage, QueryManager } from "../utils";
 
@@ -76,7 +76,7 @@ export class OverlordDynamicConfigDialog extends React.Component<OverlordDynamic
       config = configResp.data || {};
     } catch (e) {
       AppToaster.show({
-        iconName: IconNames.ERROR,
+        icon: IconNames.ERROR,
         intent: Intent.DANGER,
         message: `Could not load overlord dynamic config: ${getDruidErrorMessage(e)}`
       });
@@ -99,7 +99,7 @@ export class OverlordDynamicConfigDialog extends React.Component<OverlordDynamic
       });
     } catch (e) {
       AppToaster.show({
-        iconName: IconNames.ERROR,
+        icon: IconNames.ERROR,
         intent: Intent.DANGER,
         message: `Could not save overlord dynamic config: ${getDruidErrorMessage(e)}`
       });
diff --git a/web-console/src/dialogs/retention-dialog.scss b/web-console/src/dialogs/retention-dialog.scss
index eab743b..f363c85 100644
--- a/web-console/src/dialogs/retention-dialog.scss
+++ b/web-console/src/dialogs/retention-dialog.scss
@@ -17,7 +17,7 @@
  */
 
 .retention-dialog {
-  &.pt-dialog {
+  &.bp3-dialog {
     top: 5%;
     width: 750px;
   }
diff --git a/web-console/src/dialogs/retention-dialog.tsx b/web-console/src/dialogs/retention-dialog.tsx
index d59e181..08663e9 100644
--- a/web-console/src/dialogs/retention-dialog.tsx
+++ b/web-console/src/dialogs/retention-dialog.tsx
@@ -16,11 +16,11 @@
  * limitations under the License.
  */
 
-import { Button } from "@blueprintjs/core";
+import { Button, FormGroup } from "@blueprintjs/core";
+import { IconNames } from '@blueprintjs/icons';
 import axios from 'axios';
 import * as React from 'react';
 
-import { FormGroup, IconNames } from '../components/filler';
 import { Rule, RuleEditor } from '../components/rule-editor';
 import { QueryManager } from "../utils";
 
@@ -183,7 +183,7 @@ export class RetentionDialog extends React.Component<RetentionDialogProps, Reten
         {(currentRules || []).map(this.renderRule)}
       </FormGroup>
       <FormGroup className="right">
-        <Button iconName={IconNames.PLUS} onClick={this.addRule}>New rule</Button>
+        <Button icon={IconNames.PLUS} onClick={this.addRule}>New rule</Button>
       </FormGroup>
       {
         (!currentRules.length && datasource !== '_default') &&
diff --git a/web-console/src/components/filler.scss b/web-console/src/dialogs/snitch-dialog.scss
similarity index 83%
rename from web-console/src/components/filler.scss
rename to web-console/src/dialogs/snitch-dialog.scss
index b4ee310..7a09bdd 100644
--- a/web-console/src/components/filler.scss
+++ b/web-console/src/dialogs/snitch-dialog.scss
@@ -16,12 +16,15 @@
  * limitations under the License.
  */
 
-.pt-select {
-  &.pt-fill {
-    flex: 1;
+.snitch-dialog {
+  .bp3-dialog-footer-actions {
+    position: relative;
+
+    .left-align-button {
+      position: absolute;
+      left: 0;
+      margin: 0;
+    }
   }
 }
 
-.form-group {
-  margin: 0 0 15px;
-}
diff --git a/web-console/src/dialogs/snitch-dialog.tsx b/web-console/src/dialogs/snitch-dialog.tsx
index 11052e4..5b29b04 100644
--- a/web-console/src/dialogs/snitch-dialog.tsx
+++ b/web-console/src/dialogs/snitch-dialog.tsx
@@ -20,16 +20,19 @@ import {
   Button,
   Classes,
   Dialog,
+  FormGroup,
   IDialogProps,
   InputGroup,
   Intent
 } from "@blueprintjs/core";
+import { IconNames } from '@blueprintjs/icons';
+import classNames = require('classnames');
 import * as React from 'react';
 
-import { FormGroup, IconNames } from '../components/filler';
-
 import { HistoryDialog } from "./history-dialog";
 
+import './snitch-dialog.scss';
+
 export interface SnitchDialogProps extends IDialogProps {
   onSave: (comment: string) => void;
   saveDisabled?: boolean;
@@ -106,7 +109,7 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
       <div className={`dialog-body ${Classes.DIALOG_BODY}`}>
         <FormGroup label={"Why are you making this change?"} className={"comment"}>
           <InputGroup
-            className="pt-large"
+            large
             value={comment}
             placeholder={"Enter description here"}
             onChange={(e: any) => this.changeComment(e.target.value)}
@@ -127,7 +130,7 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
       historyRecords={historyRecords}
     >
       <div className={Classes.DIALOG_FOOTER_ACTIONS}>
-        <Button onClick={this.back} iconName={IconNames.ARROW_LEFT}>Back</Button>
+        <Button onClick={this.back} icon={IconNames.ARROW_LEFT}>Back</Button>
       </div>
     </HistoryDialog>;
   }
@@ -139,17 +142,17 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
     return <div className={Classes.DIALOG_FOOTER_ACTIONS}>
       {showFinalStep || historyRecords === undefined
         ? null
-        : <Button style={{position: "absolute", left: "5px"}} className={"pt-minimal"} text="History" onClick={this.goToHistory}/>
+        : <Button className="left-align-button" minimal text="History" onClick={this.goToHistory}/>
       }
 
       { showFinalStep
-        ? <Button onClick={this.back} iconName={IconNames.ARROW_LEFT}>Back</Button>
+        ? <Button onClick={this.back} icon={IconNames.ARROW_LEFT}>Back</Button>
         : onReset ? <Button onClick={this.reset} intent={"none" as any}>Reset</Button> : null
       }
 
       { showFinalStep
-        ? <Button disabled={saveDisabled} text="Save" onClick={this.save} intent={Intent.PRIMARY as any} rightIconName={IconNames.TICK}/>
-        : <Button disabled={saveDisabled} text="Next" onClick={this.goToFinalStep} intent={Intent.PRIMARY as any} rightIconName={IconNames.ARROW_RIGHT}/>
+        ? <Button disabled={saveDisabled} text="Save" onClick={this.save} intent={Intent.PRIMARY as any} rightIcon={IconNames.TICK}/>
+        : <Button disabled={saveDisabled} text="Next" onClick={this.goToFinalStep} intent={Intent.PRIMARY as any} rightIcon={IconNames.ARROW_RIGHT}/>
       }
     </div>;
   }
@@ -161,7 +164,9 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
     if (showFinalStep) return this.renderFinalStep();
     if (showHistory) return this.renderHistoryDialog();
 
-    return <Dialog isOpen {...this.props}>
+    const propsClone: any = Object.assign({}, this.props);
+    propsClone.className = classNames('snitch-dialog', propsClone.className);
+    return <Dialog isOpen {...propsClone}>
       <div className={Classes.DIALOG_BODY}>
         {children}
       </div>
diff --git a/web-console/src/dialogs/spec-dialog.scss b/web-console/src/dialogs/spec-dialog.scss
index abc1493..2b2e57a 100644
--- a/web-console/src/dialogs/spec-dialog.scss
+++ b/web-console/src/dialogs/spec-dialog.scss
@@ -17,7 +17,7 @@
  */
 
 .spec-dialog {
-  &.pt-dialog {
+  &.bp3-dialog {
     top: 5%;
     width: 90%;
   }
diff --git a/web-console/src/entry.scss b/web-console/src/entry.scss
index d8c3d39..8505642 100644
--- a/web-console/src/entry.scss
+++ b/web-console/src/entry.scss
@@ -17,7 +17,7 @@
  */
 
 @import '../node_modules/normalize.css/normalize';
-@import '../lib/blueprint';
+@import '../node_modules/@blueprintjs/core/lib/css/blueprint';
 @import '../lib/react-table';
 
 html,
@@ -29,7 +29,7 @@ body {
 }
 
 body {
-  &.pt-dark {
+  &.bp3-dark {
     background: rgb(41, 55, 66);
   }
 
diff --git a/web-console/src/utils/general.tsx b/web-console/src/utils/general.tsx
index 5fb696c..fb1a27b 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -16,13 +16,12 @@
  * limitations under the License.
  */
 
-import { Button, InputGroup, Intent } from '@blueprintjs/core';
+import { Button, HTMLSelect, InputGroup, Intent } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
 import * as numeral from "numeral";
 import * as React from 'react';
 import { Filter, FilterRender } from 'react-table';
 
-import { HTMLSelect, IconNames } from "../components/filler";
-
 export function addFilter(filters: Filter[], id: string, value: string): Filter[] {
   const currentFilter = filters.find(f => f.id === id);
   if (currentFilter) {
@@ -43,7 +42,7 @@ export function makeTextFilter(placeholder = ''): FilterRender {
       key={key}
       onChange={(e: any) => onChange(e.target.value)}
       value={filterValue}
-      rightElement={filterValue && <Button iconName={IconNames.CROSS} className="pt-minimal" onClick={() => onChange('')} />}
+      rightElement={filterValue && <Button icon={IconNames.CROSS} minimal onClick={() => onChange('')} />}
       placeholder={placeholder}
     />;
   };
diff --git a/web-console/src/views/datasource-view.tsx b/web-console/src/views/datasource-view.tsx
index 658221d..6283012 100644
--- a/web-console/src/views/datasource-view.tsx
+++ b/web-console/src/views/datasource-view.tsx
@@ -17,11 +17,11 @@
  */
 
 import { Button, Intent, Switch } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as React from 'react';
 import ReactTable, { Filter } from "react-table";
 
-import { IconNames } from "../components/filler";
 import { RuleEditor } from '../components/rule-editor';
 import { TableColumnSelection } from "../components/table-column-selection";
 import { AsyncActionDialog } from '../dialogs/async-action-dialog';
@@ -526,12 +526,12 @@ GROUP BY 1`);
       <div className="control-bar">
         <div className="control-label">Datasources</div>
         <Button
-          iconName={IconNames.REFRESH}
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.datasourceQueryManager.rerunLastQuery()}
         />
         <Button
-          iconName={IconNames.APPLICATION}
+          icon={IconNames.APPLICATION}
           text="Go to SQL"
           onClick={() => goToSql(this.datasourceQueryManager.getLastQuery())}
         />
diff --git a/web-console/src/views/home-view.scss b/web-console/src/views/home-view.scss
index bf35409..9d5a813 100644
--- a/web-console/src/views/home-view.scss
+++ b/web-console/src/views/home-view.scss
@@ -28,7 +28,7 @@
     color: inherit;
   }
 
-  .pt-card {
+  .status-card {
     height: 160px;
   }
 }
diff --git a/web-console/src/views/home-view.tsx b/web-console/src/views/home-view.tsx
index b435bba..3dc0a5c 100644
--- a/web-console/src/views/home-view.tsx
+++ b/web-console/src/views/home-view.tsx
@@ -16,18 +16,19 @@
  * limitations under the License.
  */
 
+import { Card, H5, Icon } from "@blueprintjs/core";
+import { IconName, IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as classNames from 'classnames';
 import * as React from 'react';
 
-import { Card, H5, Icon, IconNames } from "../components/filler";
 import { getHeadProp, pluralIfNeeded, queryDruidSql, QueryManager } from '../utils';
 
 import './home-view.scss';
 
 export interface CardOptions {
   href: string;
-  icon: string;
+  icon: IconName;
   title: string;
   loading?: boolean;
   content: JSX.Element | string;
@@ -256,7 +257,7 @@ GROUP BY 1`);
 
   renderCard(cardOptions: CardOptions): JSX.Element {
     return <a href={cardOptions.href} target={cardOptions.href[0] === '/' ? '_blank' : undefined}>
-      <Card interactive>
+      <Card className="status-card" interactive>
         <H5><Icon color="#bfccd5" icon={cardOptions.icon}/>&nbsp;{cardOptions.title}</H5>
         {cardOptions.loading ? <p>Loading...</p> : (cardOptions.error ? `Error: ${cardOptions.error}` : cardOptions.content)}
       </Card>
diff --git a/web-console/src/views/lookups-view.tsx b/web-console/src/views/lookups-view.tsx
index 8c7b352..fd31e72 100644
--- a/web-console/src/views/lookups-view.tsx
+++ b/web-console/src/views/lookups-view.tsx
@@ -17,6 +17,7 @@
  */
 
 import { Button, Intent } from "@blueprintjs/core";
+import { IconNames } from '@blueprintjs/icons';
 import axios from 'axios';
 import * as classNames from 'classnames';
 import * as React from 'react';
@@ -132,7 +133,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
     } catch (e) {
       AppToaster.show(
         {
-          iconName: 'error',
+          icon: IconNames.ERROR,
           intent: Intent.DANGER,
           message: getDruidErrorMessage(e)
         }
@@ -202,7 +203,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
     } catch (e) {
       AppToaster.show(
         {
-          iconName: 'error',
+          icon: IconNames.ERROR,
           intent: Intent.DANGER,
           message: getDruidErrorMessage(e)
         }
@@ -222,8 +223,8 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
     if (lookupsError) {
       return <div className={"init-div"}>
         <Button
-          iconName="build"
-          text="Initialize Lookup"
+          icon={IconNames.BUILD}
+          text="Initialize lookup"
           onClick={() => this.initializeLookup()}
         />
       </div>;
@@ -309,12 +310,12 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
       <div className="control-bar">
         <div className="control-label">Lookups</div>
         <Button
-          iconName="refresh"
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.lookupsGetQueryManager.rerunLastQuery()}
         />
         <Button
-          iconName="plus"
+          icon={IconNames.PLUS}
           text="Add"
           style={{display: this.state.lookupsError !== null ? 'none' : 'inline'}}
           onClick={() => this.openLookupEditDialog("", "")}
diff --git a/web-console/src/views/segments-view.tsx b/web-console/src/views/segments-view.tsx
index e2cd42e..57d9708 100644
--- a/web-console/src/views/segments-view.tsx
+++ b/web-console/src/views/segments-view.tsx
@@ -17,13 +17,14 @@
  */
 
 import { Button, Intent } from "@blueprintjs/core";
+import { H5 } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as classNames from 'classnames';
 import * as React from 'react';
 import ReactTable from "react-table";
 import { Filter } from "react-table";
 
-import { H5, IconNames } from "../components/filler";
 import { TableColumnSelection } from "../components/table-column-selection";
 import { AppToaster } from "../singletons/toaster";
 import {
@@ -287,12 +288,12 @@ export class SegmentsView extends React.Component<SegmentsViewProps, SegmentsVie
       <div className="control-bar">
         <div className="control-label">Segments</div>
         <Button
-          iconName={IconNames.REFRESH}
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.segmentsQueryManager.rerunLastQuery()}
         />
         <Button
-          iconName={IconNames.APPLICATION}
+          icon={IconNames.APPLICATION}
           text="Go to SQL"
           onClick={() => goToSql(this.segmentsQueryManager.getLastQuery().query)}
         />
diff --git a/web-console/src/views/servers-view.tsx b/web-console/src/views/servers-view.tsx
index ca8b0a0..428aafc 100644
--- a/web-console/src/views/servers-view.tsx
+++ b/web-console/src/views/servers-view.tsx
@@ -17,6 +17,7 @@
  */
 
 import { Button, Switch } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as classNames from 'classnames';
 import { sum } from "d3-array";
@@ -24,7 +25,6 @@ import * as React from 'react';
 import ReactTable from "react-table";
 import { Filter } from "react-table";
 
-import { IconNames } from '../components/filler';
 import { TableColumnSelection } from "../components/table-column-selection";
 import {
   addFilter,
@@ -373,12 +373,12 @@ WHERE "server_type" = 'historical'`);
       <div className="control-bar">
         <div className="control-label">Historicals</div>
         <Button
-          iconName={IconNames.REFRESH}
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.serverQueryManager.rerunLastQuery()}
         />
         <Button
-          iconName={IconNames.APPLICATION}
+          icon={IconNames.APPLICATION}
           text="Go to SQL"
           onClick={() => goToSql(this.serverQueryManager.getLastQuery())}
         />
@@ -400,7 +400,7 @@ WHERE "server_type" = 'historical'`);
       <div className="control-bar">
         <div className="control-label">MiddleManagers</div>
         <Button
-          iconName={IconNames.REFRESH}
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.middleManagerQueryManager.rerunLastQuery()}
         />
diff --git a/web-console/src/views/tasks-view.tsx b/web-console/src/views/tasks-view.tsx
index e904f18..d0c1555 100644
--- a/web-console/src/views/tasks-view.tsx
+++ b/web-console/src/views/tasks-view.tsx
@@ -16,14 +16,14 @@
  * limitations under the License.
  */
 
-import { Alert, Button, Intent } from "@blueprintjs/core";
+import { Alert, Button, ButtonGroup, Intent, Label } from "@blueprintjs/core";
+import { IconNames } from "@blueprintjs/icons";
 import axios from 'axios';
 import * as classNames from 'classnames';
 import * as React from 'react';
 import ReactTable from "react-table";
 import { Filter } from "react-table";
 
-import { ButtonGroup, IconNames, Label } from "../components/filler";
 import { TableColumnSelection } from "../components/table-column-selection";
 import { AsyncActionDialog } from "../dialogs/async-action-dialog";
 import { SpecDialog } from "../dialogs/spec-dialog";
@@ -568,12 +568,12 @@ ORDER BY "rank" DESC, "created_time" DESC`);
       <div className="control-bar">
         <div className="control-label">Supervisors</div>
         <Button
-          iconName={IconNames.REFRESH}
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.supervisorQueryManager.rerunLastQuery()}
         />
         <Button
-          iconName={IconNames.PLUS}
+          icon={IconNames.PLUS}
           text="Submit supervisor"
           onClick={() => this.setState({ supervisorSpecDialogOpen: true })}
         />
@@ -591,23 +591,23 @@ ORDER BY "rank" DESC, "created_time" DESC`);
         <div className="control-label">Tasks</div>
         <Label>Group by</Label>
         <ButtonGroup>
-          <Button className={classNames({ 'pt-active': groupTasksBy === null })} onClick={() => this.setState({ groupTasksBy: null })}>None</Button>
-          <Button className={classNames({ 'pt-active': groupTasksBy === 'type' })} onClick={() => this.setState({ groupTasksBy: 'type' })}>Type</Button>
-          <Button className={classNames({ 'pt-active': groupTasksBy === 'datasource' })} onClick={() => this.setState({ groupTasksBy: 'datasource' })}>Datasource</Button>
-          <Button className={classNames({ 'pt-active': groupTasksBy === 'status' })} onClick={() => this.setState({ groupTasksBy: 'status' })}>Status</Button>
+          <Button active={groupTasksBy === null} onClick={() => this.setState({ groupTasksBy: null })}>None</Button>
+          <Button active={groupTasksBy === 'type'} onClick={() => this.setState({ groupTasksBy: 'type' })}>Type</Button>
+          <Button active={groupTasksBy === 'datasource'} onClick={() => this.setState({ groupTasksBy: 'datasource' })}>Datasource</Button>
+          <Button active={groupTasksBy === 'status'} onClick={() => this.setState({ groupTasksBy: 'status' })}>Status</Button>
         </ButtonGroup>
         <Button
-          iconName={IconNames.REFRESH}
+          icon={IconNames.REFRESH}
           text="Refresh"
           onClick={() => this.taskQueryManager.rerunLastQuery()}
         />
         <Button
-          iconName={IconNames.APPLICATION}
+          icon={IconNames.APPLICATION}
           text="Go to SQL"
           onClick={() => goToSql(this.taskQueryManager.getLastQuery())}
         />
         <Button
-          iconName={IconNames.PLUS}
+          icon={IconNames.PLUS}
           text="Submit task"
           onClick={() => this.setState({ taskSpecDialogOpen: true })}
         />
@@ -629,7 +629,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
         title="Submit task"
       /> : null }
       <Alert
-        iconName={IconNames.ERROR}
+        icon={IconNames.ERROR}
         intent={Intent.PRIMARY}
         isOpen={Boolean(alertErrorMsg)}
         confirmButtonText="OK"
diff --git a/web-console/unified-console.html b/web-console/unified-console.html
index 4c056fc..cd721f9 100644
--- a/web-console/unified-console.html
+++ b/web-console/unified-console.html
@@ -24,8 +24,8 @@
   <meta name="description" content="Apache Druid web console">
   <link rel="shortcut icon" href="/favicon.png">
 </head>
-<body class="pt-dark mouse-mode">
+<body class="bp3-dark mouse-mode">
   <div class="app-container"></div>
-  <script src="public/web-console-0.14.0.js"></script>
+  <script src="public/web-console-0.15.0.js"></script>
 </body>
 </html>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org