Merge "Use yarn and webpack to manage zuul-web javascript"
diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..6df7c0c
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,8 @@
+{
+  "presets": ['env'],
+  "plugins": [[
+    "angularjs-annotate", {
+      "explicitOnly": false
+    }
+  ]]
+}
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..136e54d
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,10 @@
+parser: babel-eslint
+plugins:
+  - standard
+rules:
+  camelcase: off
+  indent:
+    - off
+    - 2
+extends:
+  - ./node_modules/eslint-config-standard/eslintrc.json
diff --git a/.gitignore b/.gitignore
index d7e2fac..82b3898 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,6 @@
 dist/
 cover/
 htmlcov/
+zuul/web/static
+node_modules
+yarn-error.log
diff --git a/.zuul.yaml b/.zuul.yaml
index 8b5ccb9..0ddfa25 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -29,6 +29,18 @@
       - playbooks/zuul-stream/.*
       - requirements.txt
 
+- job:
+    name: zuul-tox-py35
+    parent: tox-py35
+    description: |
+      Runs javascript build before running python 35 unit tests.
+    pre-run: playbooks/tox/pre.yaml
+    run: playbooks/tox/run.yaml
+    post-run: playbooks/tox/post.yaml
+    vars:
+      node_version: 8
+      npm_command: build
+
 - project:
     check:
       jobs:
@@ -39,10 +51,29 @@
             vars:
               sphinx_python: python3
         - tox-pep8
-        - tox-py35:
+        - zuul-tox-py35:
             irrelevant-files:
               - zuul/cmd/migrate.py
               - playbooks/zuul-migrate/.*
+        - build-javascript-content:
+            success-url: 'npm/html/status.html'
+            files:
+              - package.json
+              - webpack.config.js
+              - yarn.lock
+              - web/.*
+            vars:
+              javascript_content_dir: zuul/web/static
+              npm_command: build:dist -- --define ZUUL_API_URL="'https://zuul.openstack.org'"
+        - nodejs-npm-run-lint:
+            vars:
+                node_version: 8
+            success-url: 'npm/reports/bundle.html'
+            files:
+              - package.json
+              - webpack.config.js
+              - yarn.lock
+              - web/.*
         - zuul-stream-functional
         - nodepool-zuul-functional:
             voting: false
@@ -55,12 +86,32 @@
             vars:
               sphinx_python: python3
         - tox-pep8
-        - tox-py35:
+        - zuul-tox-py35:
             irrelevant-files:
               - zuul/cmd/migrate.py
               - playbooks/zuul-migrate/.*
+        - build-javascript-content:
+            success-url: 'npm/html/status.html'
+            files:
+              - package.json
+              - webpack.config.js
+              - yarn.lock
+              - web/.*
+            vars:
+              javascript_content_dir: zuul/web/static
+              npm_command: build:dist -- --define ZUUL_API_URL="'https://zuul.openstack.org'"
+        - nodejs-npm-run-lint:
+            vars:
+                node_version: 8
+            success-url: 'npm/reports/bundle.html'
+            files:
+              - package.json
+              - webpack.config.js
+              - yarn.lock
+              - web/.*
         - zuul-stream-functional
     post:
       jobs:
         - publish-openstack-sphinx-docs-infra-python3
         - publish-openstack-python-branch-tarball
+        - publish-openstack-javascript-content
diff --git a/MANIFEST.in b/MANIFEST.in
index 74fc557..429cf10 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,5 +1,6 @@
 include AUTHORS
 include ChangeLog
+include zuul/web/static/*
 
 exclude .gitignore
 exclude .gitreview
diff --git a/TESTING.rst b/TESTING.rst
index 0786ebf..289af5c 100644
--- a/TESTING.rst
+++ b/TESTING.rst
@@ -11,6 +11,7 @@
 *Install pip*::
 
   [apt-get | yum] install python-pip
+
 More information on pip here: http://www.pip-installer.org/en/latest/
 
 *Use pip to install tox*::
@@ -27,6 +28,22 @@
 
   service zookeeper start
 
+.. note:: Installing and bulding javascript is not required, but tests that
+          depend on the javascript assets having been built will be skipped
+          if you don't.
+
+*Install javascript tools*::
+
+  tools/install-js-tools.sh
+
+*Install javascript dependencies*::
+
+  yarn install
+
+*Build javascript assets*::
+
+  npm run build:dev
+
 Run The Tests
 -------------
 
diff --git a/doc/source/admin/components.rst b/doc/source/admin/components.rst
index b555abc..acf0aad 100644
--- a/doc/source/admin/components.rst
+++ b/doc/source/admin/components.rst
@@ -679,6 +679,11 @@
       Type of server hosting the statistics information. Currently only
       'graphite' is supported by the dashboard.
 
+   .. attr:: static_path
+      :default: zuul/web/static
+
+      Path containing the static web assets.
+
    .. attr:: static_cache_expiry
       :default: 3600
 
diff --git a/doc/source/developer/index.rst b/doc/source/developer/index.rst
index 360dcd5..69e9499 100644
--- a/doc/source/developer/index.rst
+++ b/doc/source/developer/index.rst
@@ -16,3 +16,4 @@
    testing
    docs
    ansible
+   javascript
diff --git a/doc/source/developer/javascript.rst b/doc/source/developer/javascript.rst
new file mode 100644
index 0000000..9eca55e
--- /dev/null
+++ b/doc/source/developer/javascript.rst
@@ -0,0 +1,223 @@
+Zuul Web Javascript
+===================
+
+zuul-web has an html, css and javascript component that is managed
+using Javascript toolchains. It is intended to be served by zuul-web
+directly from zuul/web/static in the simple case, or to be published to
+an alternate static web location, such as an Apache server.
+
+The web applications are managed by `yarn`_ and `webpack`_ which in turn both
+assume a functioning and recent `nodejs`_ installation.
+
+For the impatient who don't want deal with javascript toolchains
+----------------------------------------------------------------
+
+tl;dr - You have to build stuff with javascript tools.
+
+The best thing would be to get familiar with the tools, there are a lot of
+good features available. But, if you don't want to know anything about the
+Javascript toolchains a few helpers have been provided.
+
+If you have npm and docker installed and don't want to install newer nodejs
+or a bunch of javascript libraries, you can run:
+
+.. code-block:: bash
+
+  npm run build:docker
+
+If you have docker but do not have npm or nodejs installed, you can build
+the web app with:
+
+.. code-block:: bash
+
+  docker run -it --rm -v $(PWD):/usr/src/app -w /usr/src/app node:alpine \
+      npm run build:dist-with-depends
+
+Both do the same thing. Both versions will result in the built files being
+put into ``zuul/web/static``.
+
+.. note:: Because the user inside of the Docker container is root, the files
+          that it emits into zuul/web/static will be owned by root.
+
+yarn dependency management
+--------------------------
+
+`yarn`_ manages the javascript dependencies. That means the first step is
+getting `yarn`_ installed.
+
+.. code-block:: bash
+
+  tools/install-js-tools.sh
+
+The ``tools/install-js-tools.sh`` script will add apt or yum repositories and
+install `nodejs`_ and `yarn`_ from them. For RPM-based distros it needs to know
+which repo description file to download, so it calls out to
+``tools/install-js-repos-rpm.sh``.
+
+Once yarn is installed, getting dependencies installed is:
+
+.. code-block:: bash
+
+  yarn install
+
+The ``yarn.lock`` file contains all of the specific versions that were
+installed before. Since this is an application it has been added to the repo.
+
+To add new dependencies:
+
+.. code-block:: bash
+
+  yarn add awesome-package
+
+To remove dependencies:
+
+.. code-block:: bash
+
+  yarn remove terrible-package
+
+Adding or removing packages will add the logical dependency to ``package.json``
+and will record the version of the package and any of its dependencies that
+were installed into ``yarn.lock`` so that other users can simply run
+``yarn install`` and get the same environment.
+
+To update a dependency:
+
+.. code-block:: bash
+
+  yarn add awesome-package
+
+Dependencies are installed into the ``node_modules`` directory. Deleting that
+directory and re-running ``yarn install`` should always be safe.
+
+webpack asset management
+------------------------
+
+`webpack`_ takes care of bundling web assets for deployment, including tasks
+such as minifying and transpiling for older browsers. It takes a
+javascript-first approach, and generates a html file that includes the
+appropriate javascript and CSS to get going.
+
+We need to modify the html generated for each of our pages, so there are
+templates in ``web/templates``.
+
+The main `webpack`_ config file is ``webpack.config.js``. In the Zuul tree that
+file is a stub file that includes either a dev or a prod environment from
+``web/config/webpack.dev.js`` or ``web/config/webpack.prod.js``. Most of the
+important bits are in ``web/config/webpack.common.js``.
+
+Development
+-----------
+
+Building the code can be done with:
+
+.. code-block:: bash
+
+  npm run build
+
+zuul-web has a ``static`` route defined which serves files from
+``zuul/web/static``. ``npm run build`` will put the build output files
+into the ``zuul/web/static`` directory so that zuul-web can serve them.
+
+There is a also a development-oriented version of that same command:
+
+.. code-block:: bash
+
+  npm run build:dev
+
+which will build for the ``dev`` environment. This causes some sample data
+to be bundled and included.
+
+Webpack includes a development server that handles things like reloading and
+hot-updating of code. The following:
+
+.. code-block:: bash
+
+  npm run start
+
+will build the code and launch the dev server on `localhost:8080`. It will
+additionally watch for changes to the files and re-compile/refresh as needed.
+Arbitrary command line options will be passed through after a ``--`` such as:
+
+.. code-block:: bash
+
+  npm run start -- --open-file='static/status.html'
+
+That's kind of annoying though, so additional targets exist for common tasks:
+
+Run status against `basic` built-in demo data.
+
+.. code-block:: bash
+
+  npm run start:status:basic
+
+Run status against `openstack` built-in demo data
+
+.. code-block:: bash
+
+  npm run start:status:openstack
+
+Run status against `tree` built-in demo data.
+
+.. code-block:: bash
+
+  npm run start:status:tree
+
+Run status against live data from OpenStack's Zuul.
+
+.. code-block:: bash
+
+  npm run start:status
+
+Run builds against live data from OpenStack's Zuul.
+
+.. code-block:: bash
+
+  npm run start:builds
+
+Run jobs against live data from OpenStack's Zuul.
+
+.. code-block:: bash
+
+  npm run start:jobs
+
+Run console streamer.
+
+.. note:: There is not currently a good way to pass build_id paramter.
+
+.. code-block:: bash
+
+  npm run start:stream
+
+Additional run commands can be added in `package.json` in the ``scripts``
+section.
+
+Deploying
+---------
+
+The web application is a set of static files and is designed to be served
+by zuul-web from its ``static`` route. In order to make sure this works
+properly, the javascript build needs to be performed so that the javascript
+files are in the ``zuul/web/static`` directory. Because the javascript
+build outputs into the ``zuul/web/static`` directory, as long as
+``npm run build`` has been done before ``pip install .`` or
+``python setup.py sdist``, all the files will be where they need to be.
+
+Debugging minified code
+-----------------------
+
+Both the ``dev`` and ``prod`` ennvironments use the same `devtool`_
+called ``source-map`` which makes debugging errors easier by including mapping
+information from the minified and bundled resources to their approriate
+non-minified source code locations. Javascript errors in the browser as seen
+in the developer console can be clicked on and the appropriate actual source
+code location will be shown.
+
+``source-map`` is considered an appropriate `devtool`_ for production, but has
+the downside that it is slower to update. However, since it includes the most
+complete mapping information and doesn't impact execution performance, so in
+our case we use it for both.
+
+.. _yarn: https://yarnpkg.com/en/
+.. _nodejs: https://nodejs.org/
+.. _webpack: https://webpack.js.org/
+.. _devtool: https://webpack.js.org/configuration/devtool/#devtool
diff --git a/etc/status/README.rst b/etc/status/README.rst
deleted file mode 100644
index 762b49c..0000000
--- a/etc/status/README.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-Zuul Status
-====
-
-Zuul Status is a web portal for a Zuul server.
-
-Set up
-------------
-
-The markup generated by the javascript is fairly generic so it should be easy
-to drop into an existing portal. All it needs is
-``<div id="id="zuul-container"></div>``.
-
-Having said that, the markup is optimised for Twitter Bootstrap, though it in
-no way depends on Boostrap and any element using a bootstrap class has a
-``zuul-`` prefixed class alongside it.
-
-The script depends on jQuery (tested with version 1.8 and 1.9).
-
-The script optimises updates by stopping when the page is not visible.
-This is done by listerning to ``show`` and ``hide`` events emitted by the
-Page Visibility plugin for jQuery. If you don't want to load this plugin you
-can undo undo this optimisation by removing the code at the bottom of
-``index.html``
-
-To automatically fetch the latest versions of jQuery, the Page Visibility
-plugin and Twitter Boostrap, run the ``fetch-dependencies.sh`` script.
-The default ``index.html`` references these.
diff --git a/etc/status/fetch-dependencies.sh b/etc/status/fetch-dependencies.sh
deleted file mode 100755
index ccaf74c..0000000
--- a/etc/status/fetch-dependencies.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-BASE_DIR=$(cd $(dirname $0); pwd)
-DEST_DIR=$BASE_DIR/public_html/lib
-mkdir -p $DEST_DIR
-echo "Destination: $DEST_DIR"
-
-echo "Fetching jquery.min.js..."
-curl -L --silent http://code.jquery.com/jquery.min.js > $DEST_DIR/jquery.min.js
-
-echo "Fetching jquery-visibility.min.js..."
-curl -L --silent https://raw.githubusercontent.com/mathiasbynens/jquery-visibility/master/jquery-visibility.js > $DEST_DIR/jquery-visibility.js
-
-echo "Fetching jquery.graphite.js..."
-curl -L --silent https://github.com/prestontimmons/graphitejs/archive/master.zip > jquery-graphite.zip
-unzip -q -o jquery-graphite.zip -d $DEST_DIR/
-mv $DEST_DIR/graphitejs-master/jquery.graphite.js $DEST_DIR/
-rm -R jquery-graphite.zip $DEST_DIR/graphitejs-master
-
-echo "Fetching bootstrap..."
-curl -L --silent https://github.com/twbs/bootstrap/releases/download/v3.1.1/bootstrap-3.1.1-dist.zip > bootstrap.zip
-unzip -q -o bootstrap.zip -d $DEST_DIR/
-mv $DEST_DIR/bootstrap-3.1.1-dist $DEST_DIR/bootstrap
-rm bootstrap.zip
diff --git a/etc/status/public_html/images/black.png b/etc/status/public_html/images/black.png
deleted file mode 100644
index 252d874..0000000
--- a/etc/status/public_html/images/black.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/images/green.png b/etc/status/public_html/images/green.png
deleted file mode 100644
index a8765f1..0000000
--- a/etc/status/public_html/images/green.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/images/grey.png b/etc/status/public_html/images/grey.png
deleted file mode 100644
index eaee0d7..0000000
--- a/etc/status/public_html/images/grey.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/images/line-angle.png b/etc/status/public_html/images/line-angle.png
deleted file mode 100644
index fa74868..0000000
--- a/etc/status/public_html/images/line-angle.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/images/line-t.png b/etc/status/public_html/images/line-t.png
deleted file mode 100644
index cfd3111..0000000
--- a/etc/status/public_html/images/line-t.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/images/line.png b/etc/status/public_html/images/line.png
deleted file mode 100644
index ace6bab..0000000
--- a/etc/status/public_html/images/line.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/images/red.png b/etc/status/public_html/images/red.png
deleted file mode 100644
index e9956e8..0000000
--- a/etc/status/public_html/images/red.png
+++ /dev/null
Binary files differ
diff --git a/etc/status/public_html/index.html b/etc/status/public_html/index.html
deleted file mode 100644
index cc3d40a..0000000
--- a/etc/status/public_html/index.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-Copyright 2013 OpenStack Foundation
-Copyright 2013 Timo Tijhof
-Copyright 2013 Wikimedia Foundation
-
-Licensed under the Apache License, Version 2.0 (the "License"); you may
-not use this file except in compliance with the License. You may obtain
-a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations
-under the License.
--->
-<!DOCTYPE html>
-<html dir="ltr" lang="en">
-<head>
-    <title>Zuul Status</title>
-    <link rel="stylesheet" href="lib/bootstrap/css/bootstrap.min.css">
-    <link rel="stylesheet" href="styles/zuul.css" />
-</head>
-<body>
-    <div id="zuul_container"></div>
-    <script src="lib/jquery.min.js"></script>
-    <script src="lib/jquery-visibility.js"></script>
-    <script src="lib/jquery.graphite.js"></script>
-    <script src="jquery.zuul.js"></script>
-    <script src="zuul.app.js"></script>
-    <script>
-        // @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7&dn=apache-2.0.txt Apache 2.0
-        zuul_build_dom(jQuery, '#zuul_container');
-        zuul_start(jQuery);
-	// @license-end
-    </script>
-</body>
-</html>
diff --git a/etc/status/public_html/jquery.zuul.js b/etc/status/public_html/jquery.zuul.js
deleted file mode 100644
index ac8a302..0000000
--- a/etc/status/public_html/jquery.zuul.js
+++ /dev/null
@@ -1,945 +0,0 @@
-// jquery plugin for Zuul status page
-//
-// @licstart  The following is the entire license notice for the
-// JavaScript code in this page.
-//
-// Copyright 2012 OpenStack Foundation
-// Copyright 2013 Timo Tijhof
-// Copyright 2013 Wikimedia Foundation
-// Copyright 2014 Rackspace Australia
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-//
-// @licend  The above is the entire license notice
-// for the JavaScript code in this page.
-
-(function ($) {
-    'use strict';
-
-    function set_cookie(name, value) {
-        document.cookie = name + '=' + value + '; path=/';
-    }
-
-    function read_cookie(name, default_value) {
-        var nameEQ = name + '=';
-        var ca = document.cookie.split(';');
-        for(var i=0;i < ca.length;i++) {
-            var c = ca[i];
-            while (c.charAt(0) === ' ') {
-                c = c.substring(1, c.length);
-            }
-            if (c.indexOf(nameEQ) === 0) {
-                return c.substring(nameEQ.length, c.length);
-            }
-        }
-        return default_value;
-    }
-
-    $.zuul = function(options) {
-        options = $.extend({
-            'enabled': true,
-            'graphite_url': '',
-            'source': 'status',
-            'msg_id': '#zuul_msg',
-            'pipelines_id': '#zuul_pipelines',
-            'queue_events_num': '#zuul_queue_events_num',
-            'queue_management_events_num': '#zuul_queue_management_events_num',
-            'queue_results_num': '#zuul_queue_results_num',
-        }, options);
-
-        var collapsed_exceptions = [];
-        var current_filter = read_cookie('zuul_filter_string', '');
-        var change_set_in_url = window.location.href.split('#')[1];
-        if (change_set_in_url) {
-           current_filter = change_set_in_url;
-        }
-        var $jq;
-
-        var xhr,
-            zuul_graph_update_count = 0,
-            zuul_sparkline_urls = {};
-
-        function get_sparkline_url(pipeline_name) {
-            if (options.graphite_url !== '') {
-                if (!(pipeline_name in zuul_sparkline_urls)) {
-                    zuul_sparkline_urls[pipeline_name] = $.fn.graphite
-                        .geturl({
-                        url: options.graphite_url,
-                        from: "-8hours",
-                        width: 100,
-                        height: 26,
-                        margin: 0,
-                        hideLegend: true,
-                        hideAxes: true,
-                        hideGrid: true,
-                        target: [
-                            "color(stats.gauges.zuul.pipeline." + pipeline_name
-                                + ".current_changes, '6b8182')"
-                        ]
-                    });
-                }
-                return zuul_sparkline_urls[pipeline_name];
-            }
-            return false;
-        }
-
-        var format = {
-            job: function(job) {
-                var $job_line = $('<span />');
-
-                if (job.result !== null) {
-                    $job_line.append(
-                        $('<a />')
-                            .addClass('zuul-job-name')
-                            .attr('href', job.report_url)
-                            .text(job.name)
-                    );
-                }
-                else if (job.url !== null) {
-                    $job_line.append(
-                        $('<a />')
-                            .addClass('zuul-job-name')
-                            .attr('href', job.url)
-                            .text(job.name)
-                    );
-                }
-                else {
-                    $job_line.append(
-                        $('<span />')
-                            .addClass('zuul-job-name')
-                            .text(job.name)
-                    );
-                }
-
-                $job_line.append(this.job_status(job));
-
-                if (job.voting === false) {
-                    $job_line.append(
-                        $(' <small />')
-                            .addClass('zuul-non-voting-desc')
-                            .text(' (non-voting)')
-                    );
-                }
-
-                $job_line.append($('<div style="clear: both"></div>'));
-                return $job_line;
-            },
-
-            job_status: function(job) {
-                var result = job.result ? job.result.toLowerCase() : null;
-                if (result === null) {
-                    result = job.url ? 'in progress' : 'queued';
-                }
-
-                if (result === 'in progress') {
-                    return this.job_progress_bar(job.elapsed_time,
-                                                        job.remaining_time);
-                }
-                else {
-                    return this.status_label(result);
-                }
-            },
-
-            status_label: function(result) {
-                var $status = $('<span />');
-                $status.addClass('zuul-job-result label');
-
-                switch (result) {
-                    case 'success':
-                        $status.addClass('label-success');
-                        break;
-                    case 'failure':
-                        $status.addClass('label-danger');
-                        break;
-                    case 'unstable':
-                        $status.addClass('label-warning');
-                        break;
-                    case 'skipped':
-                        $status.addClass('label-info');
-                        break;
-                    // 'in progress' 'queued' 'lost' 'aborted' ...
-                    default:
-                        $status.addClass('label-default');
-                }
-                $status.text(result);
-                return $status;
-            },
-
-            job_progress_bar: function(elapsed_time, remaining_time) {
-                var progress_percent = 100 * (elapsed_time / (elapsed_time +
-                                                              remaining_time));
-                var $bar_inner = $('<div />')
-                    .addClass('progress-bar')
-                    .attr('role', 'progressbar')
-                    .attr('aria-valuenow', 'progressbar')
-                    .attr('aria-valuemin', progress_percent)
-                    .attr('aria-valuemin', '0')
-                    .attr('aria-valuemax', '100')
-                    .css('width', progress_percent + '%');
-
-                var $bar_outter = $('<div />')
-                    .addClass('progress zuul-job-result')
-                    .append($bar_inner);
-
-                return $bar_outter;
-            },
-
-            enqueue_time: function(ms) {
-                // Special format case for enqueue time to add style
-                var hours = 60 * 60 * 1000;
-                var now = Date.now();
-                var delta = now - ms;
-                var status = 'text-success';
-                var text = this.time(delta, true);
-                if (delta > (4 * hours)) {
-                    status = 'text-danger';
-                } else if (delta > (2 * hours)) {
-                    status = 'text-warning';
-                }
-                return '<span class="' + status + '">' + text + '</span>';
-            },
-
-            time: function(ms, words) {
-                if (typeof(words) === 'undefined') {
-                    words = false;
-                }
-                var seconds = (+ms)/1000;
-                var minutes = Math.floor(seconds/60);
-                var hours = Math.floor(minutes/60);
-                seconds = Math.floor(seconds % 60);
-                minutes = Math.floor(minutes % 60);
-                var r = '';
-                if (words) {
-                    if (hours) {
-                        r += hours;
-                        r += ' hr ';
-                    }
-                    r += minutes + ' min';
-                } else {
-                    if (hours < 10) {
-                        r += '0';
-                    }
-                    r += hours + ':';
-                    if (minutes < 10) {
-                        r += '0';
-                    }
-                    r += minutes + ':';
-                    if (seconds < 10) {
-                        r += '0';
-                    }
-                    r += seconds;
-                }
-                return r;
-            },
-
-            change_total_progress_bar: function(change) {
-                var job_percent = Math.floor(100 / change.jobs.length);
-                var $bar_outter = $('<div />')
-                    .addClass('progress zuul-change-total-result');
-
-                $.each(change.jobs, function (i, job) {
-                    var result = job.result ? job.result.toLowerCase() : null;
-                    if (result === null) {
-                        result = job.url ? 'in progress' : 'queued';
-                    }
-
-                    if (result !== 'queued') {
-                        var $bar_inner = $('<div />')
-                            .addClass('progress-bar');
-
-                        switch (result) {
-                            case 'success':
-                                $bar_inner.addClass('progress-bar-success');
-                                break;
-                            case 'lost':
-                            case 'failure':
-                                $bar_inner.addClass('progress-bar-danger');
-                                break;
-                            case 'unstable':
-                                $bar_inner.addClass('progress-bar-warning');
-                                break;
-                            case 'in progress':
-                            case 'queued':
-                                break;
-                        }
-                        $bar_inner.attr('title', job.name)
-                            .css('width', job_percent + '%');
-                        $bar_outter.append($bar_inner);
-                    }
-                });
-                return $bar_outter;
-            },
-
-            change_header: function(change) {
-                var change_id = change.id || 'NA';
-
-                var $change_link = $('<small />');
-                if (change.url !== null) {
-                    var github_id = change_id.match(/^([0-9]+),([0-9a-f]{40})$/);
-                    if (github_id) {
-                        $change_link.append(
-                            $('<a />').attr('href', change.url).append(
-                                $('<abbr />')
-                                    .attr('title', change_id)
-                                    .text('#' + github_id[1])
-                            )
-                        );
-                    } else if (/^[0-9a-f]{40}$/.test(change_id)) {
-                        var change_id_short = change_id.slice(0, 7);
-                        $change_link.append(
-                            $('<a />').attr('href', change.url).append(
-                                $('<abbr />')
-                                    .attr('title', change_id)
-                                    .text(change_id_short)
-                            )
-                        );
-                    }
-                    else {
-                        $change_link.append(
-                            $('<a />').attr('href', change.url).text(change_id)
-                        );
-                    }
-                }
-                else {
-                    if (change_id.length === 40) {
-                        change_id = change_id.substr(0, 7);
-                    }
-                    $change_link.text(change_id);
-                }
-
-                var $change_progress_row_left = $('<div />')
-                    .addClass('col-xs-4')
-                    .append($change_link);
-                var $change_progress_row_right = $('<div />')
-                    .addClass('col-xs-8')
-                    .append(this.change_total_progress_bar(change));
-
-                var $change_progress_row = $('<div />')
-                    .addClass('row')
-                    .append($change_progress_row_left)
-                    .append($change_progress_row_right);
-
-                var $project_span = $('<span />')
-                    .addClass('change_project')
-                    .text(change.project);
-
-                var $left = $('<div />')
-                    .addClass('col-xs-8')
-                    .append($project_span, $change_progress_row);
-
-                var remaining_time = this.time(
-                        change.remaining_time, true);
-                var enqueue_time = this.enqueue_time(
-                        change.enqueue_time);
-                var $remaining_time = $('<small />').addClass('time')
-                    .attr('title', 'Remaining Time').html(remaining_time);
-                var $enqueue_time = $('<small />').addClass('time')
-                    .attr('title', 'Elapsed Time').html(enqueue_time);
-
-                var $right = $('<div />');
-                if (change.live === true) {
-                    $right.addClass('col-xs-4 text-right')
-                        .append($remaining_time, $('<br />'), $enqueue_time);
-                }
-
-                var $header = $('<div />')
-                    .addClass('row')
-                    .append($left, $right);
-                return $header;
-            },
-
-            change_list: function(jobs) {
-                var format = this;
-                var $list = $('<ul />')
-                    .addClass('list-group zuul-patchset-body');
-
-                $.each(jobs, function (i, job) {
-                    var $item = $('<li />')
-                        .addClass('list-group-item')
-                        .addClass('zuul-change-job')
-                        .append(format.job(job));
-                    $list.append($item);
-                });
-
-                return $list;
-            },
-
-            change_panel: function (change) {
-                var $header = $('<div />')
-                    .addClass('panel-heading zuul-patchset-header')
-                    .append(this.change_header(change));
-
-                var panel_id = change.id ? change.id.replace(',', '_')
-                                         : change.project.replace('/', '_') +
-                                           '-' + change.enqueue_time;
-                var $panel = $('<div />')
-                    .attr('id', panel_id)
-                    .addClass('panel panel-default zuul-change')
-                    .append($header)
-                    .append(this.change_list(change.jobs));
-
-                $header.click(this.toggle_patchset);
-                return $panel;
-            },
-
-            change_status_icon: function(change) {
-                var icon_name = 'green.png';
-                var icon_title = 'Succeeding';
-
-                if (change.active !== true) {
-                    // Grey icon
-                    icon_name = 'grey.png';
-                    icon_title = 'Waiting until closer to head of queue to' +
-                        ' start jobs';
-                }
-                else if (change.live !== true) {
-                    // Grey icon
-                    icon_name = 'grey.png';
-                    icon_title = 'Dependent change required for testing';
-                }
-                else if (change.failing_reasons &&
-                         change.failing_reasons.length > 0) {
-                    var reason = change.failing_reasons.join(', ');
-                    icon_title = 'Failing because ' + reason;
-                    if (reason.match(/merge conflict/)) {
-                        // Black icon
-                        icon_name = 'black.png';
-                    }
-                    else {
-                        // Red icon
-                        icon_name = 'red.png';
-                    }
-                }
-
-                var $icon = $('<img />')
-                    .attr('src', 'images/' + icon_name)
-                    .attr('title', icon_title)
-                    .css('margin-top', '-6px');
-
-                return $icon;
-            },
-
-            change_with_status_tree: function(change, change_queue) {
-                var $change_row = $('<tr />');
-
-                for (var i = 0; i < change_queue._tree_columns; i++) {
-                    var $tree_cell  = $('<td />')
-                        .css('height', '100%')
-                        .css('padding', '0 0 10px 0')
-                        .css('margin', '0')
-                        .css('width', '16px')
-                        .css('min-width', '16px')
-                        .css('overflow', 'hidden')
-                        .css('vertical-align', 'top');
-
-                    if (i < change._tree.length && change._tree[i] !== null) {
-                        $tree_cell.css('background-image',
-                                       'url(\'images/line.png\')')
-                            .css('background-repeat', 'repeat-y');
-                    }
-
-                    if (i === change._tree_index) {
-                        $tree_cell.append(
-                            this.change_status_icon(change));
-                    }
-                    if (change._tree_branches.indexOf(i) !== -1) {
-                        var $image = $('<img />')
-                            .css('vertical-align', 'baseline');
-                        if (change._tree_branches.indexOf(i) ===
-                            change._tree_branches.length - 1) {
-                            // Angle line
-                            $image.attr('src', 'images/line-angle.png');
-                        }
-                        else {
-                            // T line
-                            $image.attr('src', 'images/line-t.png');
-                        }
-                        $tree_cell.append($image);
-                    }
-                    $change_row.append($tree_cell);
-                }
-
-                var change_width = 360 - 16*change_queue._tree_columns;
-                var $change_column = $('<td />')
-                    .css('width', change_width + 'px')
-                    .addClass('zuul-change-cell')
-                    .append(this.change_panel(change));
-
-                $change_row.append($change_column);
-
-                var $change_table = $('<table />')
-                    .addClass('zuul-change-box')
-                    .css('-moz-box-sizing', 'content-box')
-                    .css('box-sizing', 'content-box')
-                    .append($change_row);
-
-                return $change_table;
-            },
-
-            pipeline_sparkline: function(pipeline_name) {
-                if (options.graphite_url !== '') {
-                    var $sparkline = $('<img />')
-                        .addClass('pull-right')
-                        .attr('src', get_sparkline_url(pipeline_name));
-                    return $sparkline;
-                }
-                return false;
-            },
-
-            pipeline_header: function(pipeline, count) {
-                // Format the pipeline name, sparkline and description
-                var $header_div = $('<div />')
-                    .addClass('zuul-pipeline-header');
-
-                var $heading = $('<h3 />')
-                    .css('vertical-align', 'middle')
-                    .text(pipeline.name)
-                    .append(
-                        $('<span />')
-                            .addClass('badge pull-right')
-                            .css('vertical-align', 'middle')
-                            .css('margin-top', '0.5em')
-                            .text(count)
-                    )
-                    .append(this.pipeline_sparkline(pipeline.name));
-
-                $header_div.append($heading);
-
-                if (typeof pipeline.description === 'string') {
-                    var descr = $('<small />')
-                    $.each( pipeline.description.split(/\r?\n\r?\n/), function(index, descr_part){
-                        descr.append($('<p />').text(descr_part));
-                    });
-                    $header_div.append(
-                        $('<p />').append(descr)
-                    );
-                }
-                return $header_div;
-            },
-
-            pipeline: function (pipeline, count) {
-                var format = this;
-                var $html = $('<div />')
-                    .addClass('zuul-pipeline col-md-4')
-                    .append(this.pipeline_header(pipeline, count));
-
-                $.each(pipeline.change_queues,
-                       function (queue_i, change_queue) {
-                    $.each(change_queue.heads, function (head_i, changes) {
-                        if (pipeline.change_queues.length > 1 &&
-                            head_i === 0) {
-                            var name = change_queue.name;
-                            var short_name = name;
-                            if (short_name.length > 32) {
-                                short_name = short_name.substr(0, 32) + '...';
-                            }
-                            $html.append(
-                                $('<p />')
-                                    .text('Queue: ')
-                                    .append(
-                                        $('<abbr />')
-                                            .attr('title', name)
-                                            .text(short_name)
-                                    )
-                            );
-                        }
-
-                        $.each(changes, function (change_i, change) {
-                            var $change_box =
-                                format.change_with_status_tree(
-                                    change, change_queue);
-                            $html.append($change_box);
-                            format.display_patchset($change_box);
-                        });
-                    });
-                });
-                return $html;
-            },
-
-            toggle_patchset: function(e) {
-                // Toggle showing/hiding the patchset when the header is
-                // clicked.
-
-                if (e.target.nodeName.toLowerCase() === 'a') {
-                    // Ignore clicks from gerrit patch set link
-                    return;
-                }
-
-                // Grab the patchset panel
-                var $panel = $(e.target).parents('.zuul-change');
-                var $body = $panel.children('.zuul-patchset-body');
-                $body.toggle(200);
-                var collapsed_index = collapsed_exceptions.indexOf(
-                    $panel.attr('id'));
-                if (collapsed_index === -1 ) {
-                    // Currently not an exception, add it to list
-                    collapsed_exceptions.push($panel.attr('id'));
-                }
-                else {
-                    // Currently an except, remove from exceptions
-                    collapsed_exceptions.splice(collapsed_index, 1);
-                }
-            },
-
-            display_patchset: function($change_box, animate) {
-                // Determine if to show or hide the patchset and/or the results
-                // when loaded
-
-                // See if we should hide the body/results
-                var $panel = $change_box.find('.zuul-change');
-                var panel_change = $panel.attr('id');
-                var $body = $panel.children('.zuul-patchset-body');
-                var expand_by_default = $('#expand_by_default')
-                    .prop('checked');
-
-                var collapsed_index = collapsed_exceptions
-                    .indexOf(panel_change);
-
-                if (expand_by_default && collapsed_index === -1 ||
-                    !expand_by_default && collapsed_index !== -1) {
-                    // Expand by default, or is an exception
-                    $body.show(animate);
-                }
-                else {
-                    $body.hide(animate);
-                }
-
-                // Check if we should hide the whole panel
-                var panel_project = $panel.find('.change_project').text()
-                    .toLowerCase();
-
-
-                var panel_pipeline = $change_box
-                    .parents('.zuul-pipeline')
-                    .find('.zuul-pipeline-header > h3')
-                    .html()
-                    .toLowerCase();
-
-                if (current_filter !== '') {
-                    var show_panel = false;
-                    var filter = current_filter.trim().split(/[\s,]+/);
-                    $.each(filter, function(index, f_val) {
-                        if (f_val !== '') {
-                            f_val = f_val.toLowerCase();
-                            if (panel_project.indexOf(f_val) !== -1 ||
-                                panel_pipeline.indexOf(f_val) !== -1 ||
-                                panel_change.indexOf(f_val) !== -1) {
-                                show_panel = true;
-                            }
-                        }
-                    });
-                    if (show_panel === true) {
-                        $change_box.show(animate);
-                    }
-                    else {
-                        $change_box.hide(animate);
-                    }
-                }
-                else {
-                    $change_box.show(animate);
-                }
-            },
-        };
-
-        var app = {
-            schedule: function (app) {
-                app = app || this;
-                if (!options.enabled) {
-                    setTimeout(function() {app.schedule(app);}, 5000);
-                    return;
-                }
-                app.update().always(function () {
-                    setTimeout(function() {app.schedule(app);}, 5000);
-                });
-
-                /* Only update graphs every minute */
-                if (zuul_graph_update_count > 11) {
-                    zuul_graph_update_count = 0;
-                    zuul.update_sparklines();
-                }
-            },
-
-            /** @return {jQuery.Promise} */
-            update: function () {
-                // Cancel the previous update if it hasn't completed yet.
-                if (xhr) {
-                    xhr.abort();
-                }
-
-                this.emit('update-start');
-                var app = this;
-
-                var $msg = $(options.msg_id);
-                xhr = $.getJSON(options.source)
-                    .done(function (data) {
-                        if ('message' in data) {
-                            $msg.removeClass('alert-danger')
-                                .addClass('alert-info')
-                                .text(data.message)
-                                .show();
-                        } else {
-                            $msg.empty()
-                                .hide();
-                        }
-
-                        if ('zuul_version' in data) {
-                            $('#zuul-version-span').text(data.zuul_version);
-                        }
-                        if ('last_reconfigured' in data) {
-                            var last_reconfigured =
-                                new Date(data.last_reconfigured);
-                            $('#last-reconfigured-span').text(
-                                last_reconfigured.toString());
-                        }
-
-                        var $pipelines = $(options.pipelines_id);
-                        $pipelines.html('');
-                        $.each(data.pipelines, function (i, pipeline) {
-                            var count = app.create_tree(pipeline);
-                            $pipelines.append(
-                                format.pipeline(pipeline, count));
-                        });
-
-                        $(options.queue_events_num).text(
-                            data.trigger_event_queue ?
-                                data.trigger_event_queue.length : '0'
-                        );
-                        $(options.queue_management_events_num).text(
-                            data.management_event_queue ?
-                                data.management_event_queue.length : '0'
-                        );
-                        $(options.queue_results_num).text(
-                            data.result_event_queue ?
-                                data.result_event_queue.length : '0'
-                        );
-                    })
-                    .fail(function (jqXHR, statusText, errMsg) {
-                        if (statusText === 'abort') {
-                            return;
-                        }
-                        $msg.text(options.source + ': ' + errMsg)
-                            .addClass('alert-danger')
-                            .removeClass('zuul-msg-wrap-off')
-                            .show();
-                    })
-                    .always(function () {
-                        xhr = undefined;
-                        app.emit('update-end');
-                    });
-
-                return xhr;
-            },
-
-            update_sparklines: function() {
-                $.each(zuul_sparkline_urls, function(name, url) {
-                    var newimg = new Image();
-                    var parts = url.split('#');
-                    newimg.src = parts[0] + '#' + new Date().getTime();
-                    $(newimg).load(function () {
-                        zuul_sparkline_urls[name] = newimg.src;
-                    });
-                });
-            },
-
-            emit: function () {
-                $jq.trigger.apply($jq, arguments);
-                return this;
-            },
-            on: function () {
-                $jq.on.apply($jq, arguments);
-                return this;
-            },
-            one: function () {
-                $jq.one.apply($jq, arguments);
-                return this;
-            },
-
-            control_form: function() {
-                // Build the filter form filling anything from cookies
-
-                var $control_form = $('<form />')
-                    .attr('role', 'form')
-                    .addClass('form-inline')
-                    .submit(this.handle_filter_change);
-
-                $control_form
-                    .append(this.filter_form_group())
-                    .append(this.expand_form_group());
-
-                return $control_form;
-            },
-
-            filter_form_group: function() {
-                // Update the filter form with a clear button if required
-
-                var $label = $('<label />')
-                    .addClass('control-label')
-                    .attr('for', 'filter_string')
-                    .text('Filters')
-                    .css('padding-right', '0.5em');
-
-                var $input = $('<input />')
-                    .attr('type', 'text')
-                    .attr('id', 'filter_string')
-                    .addClass('form-control')
-                    .attr('title',
-                          'project(s), pipeline(s) or review(s) comma ' +
-                          'separated')
-                    .attr('value', current_filter);
-
-                $input.change(this.handle_filter_change);
-
-                var $clear_icon = $('<span />')
-                    .addClass('form-control-feedback')
-                    .addClass('glyphicon glyphicon-remove-circle')
-                    .attr('id', 'filter_form_clear_box')
-                    .attr('title', 'clear filter')
-                    .css('cursor', 'pointer');
-
-                $clear_icon.click(function() {
-                    $('#filter_string').val('').change();
-                });
-
-                if (current_filter === '') {
-                    $clear_icon.hide();
-                }
-
-                var $form_group = $('<div />')
-                    .addClass('form-group has-feedback')
-                    .append($label, $input, $clear_icon);
-                return $form_group;
-            },
-
-            expand_form_group: function() {
-                var expand_by_default = (
-                    read_cookie('zuul_expand_by_default', false) === 'true');
-
-                var $checkbox = $('<input />')
-                    .attr('type', 'checkbox')
-                    .attr('id', 'expand_by_default')
-                    .prop('checked', expand_by_default)
-                    .change(this.handle_expand_by_default);
-
-                var $label = $('<label />')
-                    .css('padding-left', '1em')
-                    .html('Expand by default: ')
-                    .append($checkbox);
-
-                var $form_group = $('<div />')
-                    .addClass('checkbox')
-                    .append($label);
-                return $form_group;
-            },
-
-            handle_filter_change: function() {
-                // Update the filter and save it to a cookie
-                current_filter = $('#filter_string').val();
-                set_cookie('zuul_filter_string', current_filter);
-                if (current_filter === '') {
-                    $('#filter_form_clear_box').hide();
-                }
-                else {
-                    $('#filter_form_clear_box').show();
-                }
-
-                $('.zuul-change-box').each(function(index, obj) {
-                    var $change_box = $(obj);
-                    format.display_patchset($change_box, 200);
-                });
-                return false;
-            },
-
-            handle_expand_by_default: function(e) {
-                // Handle toggling expand by default
-                set_cookie('zuul_expand_by_default', e.target.checked);
-                collapsed_exceptions = [];
-                $('.zuul-change-box').each(function(index, obj) {
-                    var $change_box = $(obj);
-                    format.display_patchset($change_box, 200);
-                });
-            },
-
-            create_tree: function(pipeline) {
-                var count = 0;
-                var pipeline_max_tree_columns = 1;
-                $.each(pipeline.change_queues, function(change_queue_i,
-                                                           change_queue) {
-                    var tree = [];
-                    var max_tree_columns = 1;
-                    var changes = [];
-                    var last_tree_length = 0;
-                    $.each(change_queue.heads, function(head_i, head) {
-                        $.each(head, function(change_i, change) {
-                            changes[change.id] = change;
-                            change._tree_position = change_i;
-                        });
-                    });
-                    $.each(change_queue.heads, function(head_i, head) {
-                        $.each(head, function(change_i, change) {
-                            if (change.live === true) {
-                                count += 1;
-                            }
-                            var idx = tree.indexOf(change.id);
-                            if (idx > -1) {
-                                change._tree_index = idx;
-                                // remove...
-                                tree[idx] = null;
-                                while (tree[tree.length - 1] === null) {
-                                    tree.pop();
-                                }
-                            } else {
-                                change._tree_index = 0;
-                            }
-                            change._tree_branches = [];
-                            change._tree = [];
-                            if (typeof(change.items_behind) === 'undefined') {
-                                change.items_behind = [];
-                            }
-                            change.items_behind.sort(function(a, b) {
-                                return (changes[b]._tree_position -
-                                        changes[a]._tree_position);
-                            });
-                            $.each(change.items_behind, function(i, id) {
-                                tree.push(id);
-                                if (tree.length>last_tree_length &&
-                                    last_tree_length > 0) {
-                                    change._tree_branches.push(
-                                        tree.length - 1);
-                                }
-                            });
-                            if (tree.length > max_tree_columns) {
-                                max_tree_columns = tree.length;
-                            }
-                            if (tree.length > pipeline_max_tree_columns) {
-                                pipeline_max_tree_columns = tree.length;
-                            }
-                            change._tree = tree.slice(0);  // make a copy
-                            last_tree_length = tree.length;
-                        });
-                    });
-                    change_queue._tree_columns = max_tree_columns;
-                });
-                pipeline._tree_columns = pipeline_max_tree_columns;
-                return count;
-            },
-        };
-
-        $jq = $(app);
-        return {
-            options: options,
-            format: format,
-            app: app,
-            jq: $jq
-        };
-    };
-}(jQuery));
diff --git a/etc/status/public_html/zuul.app.js b/etc/status/public_html/zuul.app.js
deleted file mode 100644
index 6e35eb3..0000000
--- a/etc/status/public_html/zuul.app.js
+++ /dev/null
@@ -1,108 +0,0 @@
-// Client script for Zuul status page
-//
-// @licstart  The following is the entire license notice for the
-// JavaScript code in this page.
-//
-// Copyright 2013 OpenStack Foundation
-// Copyright 2013 Timo Tijhof
-// Copyright 2013 Wikimedia Foundation
-// Copyright 2014 Rackspace Australia
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-//
-// @licend  The above is the entire license notice
-// for the JavaScript code in this page.
-
-/*exported zuul_build_dom, zuul_start */
-
-function zuul_build_dom($, container) {
-    // Build a default-looking DOM
-    var default_layout = '<div class="container">'
-        + '<div class="zuul-container" id="zuul-container">'
-        + '<div style="display: none;" class="alert" id="zuul_msg"></div>'
-        + '<button class="btn pull-right zuul-spinner">updating <span class="glyphicon glyphicon-refresh"></span></button>'
-        + '<p>Queue lengths: <span id="zuul_queue_events_num">0</span> events, <span id="zuul_queue_management_events_num">0</span> management events, <span id="zuul_queue_results_num">0</span> results.</p>'
-        + '<div id="zuul_controls"></div>'
-        + '<div id="zuul_pipelines" class="row"></div>'
-        + '<p>Zuul version: <span id="zuul-version-span"></span></p>'
-        + '<p>Last reconfigured: <span id="last-reconfigured-span"></span></p>'
-        + '</div></div>';
-
-    $(function ($) {
-        // DOM ready
-        var $container = $(container);
-        $container.html(default_layout);
-    });
-}
-
-/**
- * @return The $.zuul instance
- */
-function zuul_start($) {
-    // Start the zuul app (expects default dom)
-
-    var $container, $indicator;
-    var demo = location.search.match(/[?&]demo=([^?&]*)/),
-        source_url = location.search.match(/[?&]source_url=([^?&]*)/),
-        source = demo ? './status-' + (demo[1] || 'basic') + '.json-sample' :
-            'status';
-    source = source_url ? source_url[1] : source;
-
-    var zuul = $.zuul({
-        source: source,
-        //graphite_url: 'http://graphite.openstack.org/render/'
-    });
-
-    zuul.jq.on('update-start', function () {
-        $container.addClass('zuul-container-loading');
-        $indicator.addClass('zuul-spinner-on');
-    });
-
-    zuul.jq.on('update-end', function () {
-        $container.removeClass('zuul-container-loading');
-        setTimeout(function () {
-            $indicator.removeClass('zuul-spinner-on');
-        }, 500);
-    });
-
-    zuul.jq.one('update-end', function () {
-        // Do this asynchronous so that if the first update adds a
-        // message, it will not animate while we fade in the content.
-        // Instead it simply appears with the rest of the content.
-        setTimeout(function () {
-            // Fade in the content
-            $container.addClass('zuul-container-ready');
-        });
-    });
-
-    $(function ($) {
-        // DOM ready
-        $container = $('#zuul-container');
-        $indicator = $('#zuul-spinner');
-        $('#zuul_controls').append(zuul.app.control_form());
-
-        zuul.app.schedule();
-
-        $(document).on({
-            'show.visibility': function () {
-                zuul.options.enabled = true;
-                zuul.app.update();
-            },
-            'hide.visibility': function () {
-                zuul.options.enabled = false;
-            }
-        });
-    });
-
-    return zuul;
-}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..f1f1c6d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,60 @@
+{
+  "name": "zuul-web",
+  "version": "1.0.0",
+  "description": "Web Client for Zuul",
+  "main": "index.js",
+  "repository": "https://git.openstack.org/openstack-infra/zuul",
+  "author": "OpenStack Infra",
+  "license": "Apache-2.0",
+  "babel": {
+    "presets": [
+      "env"
+    ]
+  },
+  "dependencies": {
+    "angular": "^1.5.8",
+    "bootstrap": "^3.3.7",
+    "graphitejs": "https://github.com/prestontimmons/graphitejs/archive/master.tar.gz",
+    "jquery": "^1.11.1",
+    "jquery-visibility": "https://github.com/mathiasbynens/jquery-visibility/archive/master.tar.gz"
+  },
+  "scripts": {
+    "build": "npm run build:dist",
+    "build:dev": "webpack --env=dev",
+    "build:dist": "webpack --env=prod",
+    "build:docker": "docker run -it --rm -v $(pwd):/usr/src/app -w /usr/src/app node:alpine npm run build:dist-with-depends",
+    "build:dist-with-depends": "yarn install && npm run build:dist",
+    "format": "eslint --fix web/*.js",
+    "lint": "webpack --env=lint",
+    "start": "webpack-dev-server --env=dev --define ZUUL_API_URL=\"'https://zuul.openstack.org'\" --open-page='status.html'",
+    "start:basic": "webpack-dev-server --env=dev --open-page='status.html?demo=basic'",
+    "start:openstack": "webpack-dev-server --env=dev --open-page='status.html?demo=openstack'",
+    "start:tree": "webpack-dev-server --env=dev --open-page='status.html?demo=tree'"
+  },
+  "devDependencies": {
+    "babel-core": "^6.26.0",
+    "babel-eslint": "^8.0.3",
+    "babel-loader": "^7.1.2",
+    "babel-plugin-angularjs-annotate": "^0.8.2",
+    "babel-preset-env": "^1.6.1",
+    "clean-webpack-plugin": "^0.1.16",
+    "css-loader": "^0.28.4",
+    "eslint": ">=3.19.0",
+    "eslint-config-standard": "^11.0.0-beta.0",
+    "eslint-loader": "^1.9.0",
+    "eslint-plugin-import": "^2.8.0",
+    "eslint-plugin-node": "^6.0.0",
+    "eslint-plugin-promise": "^3.6.0",
+    "eslint-plugin-standard": "^3.0.1",
+    "file-loader": "^0.11.2",
+    "html-webpack-plugin": "^2.29.0",
+    "resolve-url-loader": "^2.1.0",
+    "style-loader": "^0.18.2",
+    "url-loader": "^0.5.9",
+    "webpack": "^3.3.0",
+    "webpack-archive-plugin": "^3.0.0",
+    "webpack-bundle-analyzer": "^2.9.1",
+    "webpack-dev-server": "^2.6.1",
+    "webpack-merge": "^4.1.0"
+  }
+}
diff --git a/playbooks/tox/post.yaml b/playbooks/tox/post.yaml
new file mode 100644
index 0000000..fc32a99
--- /dev/null
+++ b/playbooks/tox/post.yaml
@@ -0,0 +1,3 @@
+- hosts: all
+  roles:
+    - fetch-javascript-output
diff --git a/playbooks/tox/pre.yaml b/playbooks/tox/pre.yaml
new file mode 100644
index 0000000..34206c2
--- /dev/null
+++ b/playbooks/tox/pre.yaml
@@ -0,0 +1,5 @@
+- hosts: all
+  roles:
+    - install-nodejs
+    - install-yarn
+    - install-javascript-packages
diff --git a/playbooks/tox/run.yaml b/playbooks/tox/run.yaml
new file mode 100644
index 0000000..c3bbf63
--- /dev/null
+++ b/playbooks/tox/run.yaml
@@ -0,0 +1,5 @@
+- hosts: all
+  roles:
+    - revoke-sudo
+    - npm
+    - tox
diff --git a/setup.cfg b/setup.cfg
index dea3158..566d24a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -18,6 +18,10 @@
 [pbr]
 warnerrors = True
 
+[global]
+setup-hooks =
+  zuul._setup_hook.setup_hook
+
 [entry_points]
 console_scripts =
     zuul-scheduler = zuul.cmd.scheduler:main
diff --git a/test-requirements.txt b/test-requirements.txt
index 70f8e78..ae03309 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -13,3 +13,4 @@
 PyMySQL
 mypy
 zuul-sphinx
+beautifulsoup4
diff --git a/tests/base.py b/tests/base.py
index 013a6e1..bf1270c 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -15,6 +15,7 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import asyncio
 import configparser
 from contextlib import contextmanager
 import datetime
@@ -39,6 +40,8 @@
 import time
 import uuid
 import urllib
+import socketserver
+import http.server
 
 import git
 import gear
@@ -1755,6 +1758,74 @@
         _tmp_client.close()
 
 
+class WebProxyFixture(fixtures.Fixture):
+    def __init__(self, rules):
+        super(WebProxyFixture, self).__init__()
+        self.rules = rules
+
+    def _setUp(self):
+        rules = self.rules
+
+        class Proxy(http.server.SimpleHTTPRequestHandler):
+            def do_GET(self):
+                path = self.path
+                for (pattern, replace) in rules:
+                    path = re.sub(pattern, replace, path)
+                try:
+                    remote = urllib.request.urlopen(path)
+                except urllib.error.HTTPError as e:
+                    self.send_response(e.code)
+                    self.end_headers()
+                    return
+                self.send_response(int(remote.getcode()))
+                for header in remote.info():
+                    self.send_header(header, remote.info()[header])
+                self.end_headers()
+                self.wfile.write(remote.read())
+
+        self.httpd = socketserver.ThreadingTCPServer(('', 0), Proxy)
+        self.port = self.httpd.socket.getsockname()[1]
+        self.thread = threading.Thread(target=self.httpd.serve_forever)
+        self.thread.start()
+        self.addCleanup(self._cleanup)
+
+    def _cleanup(self):
+        self.httpd.shutdown()
+        self.thread.join()
+
+
+class ZuulWebFixture(fixtures.Fixture):
+    def __init__(self, gearman_server_port):
+        super(ZuulWebFixture, self).__init__()
+        self.gearman_server_port = gearman_server_port
+
+    def _setUp(self):
+        # Start the web server
+        self.web = zuul.web.ZuulWeb(
+            listen_address='127.0.0.1', listen_port=0,
+            gear_server='127.0.0.1', gear_port=self.gearman_server_port)
+        loop = asyncio.new_event_loop()
+        loop.set_debug(True)
+        ws_thread = threading.Thread(target=self.web.run, args=(loop,))
+        ws_thread.start()
+        self.addCleanup(loop.close)
+        self.addCleanup(ws_thread.join)
+        self.addCleanup(self.web.stop)
+
+        self.host = 'localhost'
+        # Wait until web server is started
+        while True:
+            time.sleep(0.1)
+            if self.web.server is None:
+                continue
+            self.port = self.web.server.sockets[0].getsockname()[1]
+            try:
+                with socket.create_connection((self.host, self.port)):
+                    break
+            except ConnectionRefusedError:
+                pass
+
+
 class MySQLSchemaFixture(fixtures.Fixture):
     def setUp(self):
         super(MySQLSchemaFixture, self).setUp()
diff --git a/tests/unit/test_streaming.py b/tests/unit/test_streaming.py
index b999106..cce7d1b 100644
--- a/tests/unit/test_streaming.py
+++ b/tests/unit/test_streaming.py
@@ -249,7 +249,8 @@
         # Start the web server
         web_server = zuul.web.ZuulWeb(
             listen_address='::', listen_port=9000,
-            gear_server='127.0.0.1', gear_port=self.gearman_server.port)
+            gear_server='127.0.0.1', gear_port=self.gearman_server.port,
+            static_path=tempfile.gettempdir())
         loop = asyncio.new_event_loop()
         loop.set_debug(True)
         ws_thread = threading.Thread(target=web_server.run, args=(loop,))
diff --git a/tests/unit/test_web.py b/tests/unit/test_web.py
index 75cf8f3..ddb8828 100644
--- a/tests/unit/test_web.py
+++ b/tests/unit/test_web.py
@@ -45,6 +45,9 @@
     config_ini_data = {}
 
     def setUp(self):
+        self.assertTrue(
+            os.path.exists(zuul.web.STATIC_DIR),
+            "Static web assets are missing, be sure to run 'npm run build'")
         super(BaseTestWeb, self).setUp()
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
diff --git a/tests/unit/test_web_urls.py b/tests/unit/test_web_urls.py
new file mode 100644
index 0000000..3e7f69e
--- /dev/null
+++ b/tests/unit/test_web_urls.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+# Copyright 2017 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import urllib
+
+from bs4 import BeautifulSoup
+
+from tests.base import ZuulTestCase, WebProxyFixture
+from tests.base import ZuulWebFixture
+
+
+class TestWebURLs(object):
+    tenant_config_file = 'config/single-tenant/main.yaml'
+
+    def setUp(self):
+        super(TestWebURLs, self).setUp()
+        self.web = self.useFixture(
+            ZuulWebFixture(self.gearman_server.port))
+
+    def _get(self, port, uri):
+        url = "http://localhost:{}{}".format(port, uri)
+        self.log.debug("GET {}".format(url))
+        req = urllib.request.Request(url)
+        try:
+            f = urllib.request.urlopen(req)
+        except urllib.error.HTTPError as e:
+            raise Exception("Error on URL {}".format(url))
+        return f.read()
+
+    def _crawl(self, url):
+        page = self._get(self.port, url)
+        page = BeautifulSoup(page, 'html.parser')
+        for (tag, attr) in [
+                ('script', 'src'),
+                ('link', 'href'),
+                ('a', 'href'),
+                ('img', 'src'),
+        ]:
+            for item in page.find_all(tag):
+                suburl = item.get(attr)
+                # Skip empty urls. Also skip the navbar relative link for now.
+                # TODO(mordred) Remove when we have the top navbar link sorted.
+                if suburl is None or suburl == "../":
+                    continue
+                link = urllib.parse.urljoin(url, suburl)
+                self._get(self.port, link)
+
+
+class TestDirect(TestWebURLs, ZuulTestCase):
+    # Test directly accessing the zuul-web server with no proxy
+    def setUp(self):
+        super(TestDirect, self).setUp()
+        self.port = self.web.port
+
+    def test_status_page(self):
+        self._crawl('/tenant-one/status.html')
+
+
+class TestWhiteLabel(TestWebURLs, ZuulTestCase):
+    # Test a zuul-web behind a whitelabel proxy (i.e., what
+    # zuul.openstack.org does).
+    def setUp(self):
+        super(TestWhiteLabel, self).setUp()
+        rules = [
+            ('^/(.*)$', 'http://localhost:{}/tenant-one/\\1'.format(
+                self.web.port)),
+        ]
+        self.proxy = self.useFixture(WebProxyFixture(rules))
+        self.port = self.proxy.port
+
+    def test_status_page(self):
+        self._crawl('/status.html')
+
+
+class TestSuburl(TestWebURLs, ZuulTestCase):
+    # Test a zuul-web mounted on a suburl (i.e., what software factory
+    # does).
+    def setUp(self):
+        super(TestSuburl, self).setUp()
+        rules = [
+            ('^/zuul3/(.*)$', 'http://localhost:{}/\\1'.format(
+                self.web.port)),
+        ]
+        self.proxy = self.useFixture(WebProxyFixture(rules))
+        self.port = self.proxy.port
+
+    def test_status_page(self):
+        self._crawl('/zuul3/tenant-one/status.html')
diff --git a/tools/install-js-repos-rpm.sh b/tools/install-js-repos-rpm.sh
new file mode 100755
index 0000000..6832c14
--- /dev/null
+++ b/tools/install-js-repos-rpm.sh
@@ -0,0 +1,256 @@
+#!/bin/bash
+
+# Copyright (c) 2016 NodeSource LLC
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# The above license is inferred from the
+# https://github.com/nodesource/distributions source repository.
+
+# Discussion, issues and change requests at:
+#   https://github.com/nodesource/distributions
+#
+# Script to install the NodeSource Node.js 8.x repo onto an
+# Enterprise Linux or Fedora Core based system.
+#
+# Run as root or insert `sudo -E` before `bash`:
+#
+# This was downloaded from https://rpm.nodesource.com/setup_8.x
+# A few modifications have been made.
+
+print_status() {
+  local outp=$(echo "$1" | sed -r 's/\\n/\\n## /mg')
+  echo
+  echo -e "## ${outp}"
+  echo
+}
+
+bail() {
+  echo 'Error executing command, exiting'
+  exit 1
+}
+
+exec_cmd_nobail() {
+  echo "+ $1"
+  bash -c "$1"
+}
+
+exec_cmd() {
+  exec_cmd_nobail "$1" || bail
+}
+
+print_status "Installing the NodeSource Node.js 8.x repo..."
+
+print_status "Inspecting system..."
+
+if [ ! -x /bin/rpm ]; then
+  print_status "\
+You don't appear to be running an Enterprise Linux based \
+system, please contact NodeSource at \
+https://github.com/nodesource/distributions/issues if you think this \
+is incorrect or would like your distribution to be considered for \
+support.\
+"
+  exit 1
+fi
+
+## Annotated section for auto extraction in test.sh
+#-check-distro-#
+
+## Check distro and arch
+echo "+ rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release || rpm -q --whatprovides sl-release"
+DISTRO_PKG=$(rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release || rpm -q --whatprovides sl-release)
+echo "+ uname -m"
+UNAME_ARCH=$(uname -m)
+
+
+if [ "X${UNAME_ARCH}" == "Xi686" ]; then
+  DIST_ARCH=i386
+elif [ "X${UNAME_ARCH}" == "Xx86_64" ]; then
+  DIST_ARCH=x86_64
+else
+
+  print_status "\
+You don't appear to be running a supported machine architecture: ${UNAME_ARCH}. \
+Please contact NodeSource at \
+https://github.com/nodesource/distributions/issues if you think this is \
+incorrect or would like your architecture to be considered for support. \
+"
+  exit 1
+
+fi
+
+if [[ $DISTRO_PKG =~ ^(redhat|centos|cloudlinux|sl)- ]]; then
+    DIST_TYPE=el
+elif [[ $DISTRO_PKG =~ ^system-release- ]]; then # Amazon Linux
+    DIST_TYPE=el
+elif [[ $DISTRO_PKG =~ ^(fedora|korora)- ]]; then
+    DIST_TYPE=fc
+else
+
+  print_status "\
+You don't appear to be running a supported version of Enterprise Linux. \
+Please contact NodeSource at \
+https://github.com/nodesource/distributions/issues if you think this is \
+incorrect or would like your architecture to be considered for support. \
+Include your 'distribution package' name: ${DISTRO_PKG}. \
+"
+  exit 1
+
+fi
+
+if [[ $DISTRO_PKG =~ ^system-release-201[4-9]\. ]]; then  #NOTE: not really future-proof
+
+  # Amazon Linux, for 2014.* use el7, older versions are unknown, perhaps el6
+  DIST_VERSION=7
+
+else
+
+  ## Using the redhat-release-server-X, centos-release-X, etc. pattern
+  ## extract the major version number of the distro
+  DIST_VERSION=$(echo $DISTRO_PKG | sed -r 's/^[[:alpha:]]+-release(-server|-workstation)?-([0-9]+).*$/\2/')
+
+  if ! [[ $DIST_VERSION =~ ^[0-9][0-9]?$ ]]; then
+
+    print_status "\
+Could not determine your distribution version, you may not be running a \
+supported version of Enterprise Linux. \
+Please contact NodeSource at \
+https://github.com/nodesource/distributions/issues if you think this is \
+incorrect. Include your 'distribution package' name: ${DISTRO_PKG}. \
+"
+    exit 1
+
+  fi
+
+fi
+
+
+## Given the distro, version and arch, construct the url for
+## the appropriate nodesource-release package (it's noarch but
+## we include the arch in the directory tree anyway)
+RELEASE_URL_VERSION_STRING="${DIST_TYPE}${DIST_VERSION}"
+RELEASE_URL="\
+https://rpm.nodesource.com/pub_8.x/\
+${DIST_TYPE}/\
+${DIST_VERSION}/\
+${DIST_ARCH}/\
+nodesource-release-${RELEASE_URL_VERSION_STRING}-1.noarch.rpm"
+
+#-check-distro-#
+
+print_status "Confirming \"${DIST_TYPE}${DIST_VERSION}-${DIST_ARCH}\" is supported..."
+
+## Simple fetch & fast-fail to see if the nodesource-release
+## file exists for this distro/version/arch
+exec_cmd_nobail "curl -sLf -o /dev/null '${RELEASE_URL}'"
+RC=$?
+
+if [[ $RC != 0 ]]; then
+    print_status "\
+Your distribution, identified as \"${DISTRO_PKG}\", \
+is not currently supported, please contact NodeSource at \
+https://github.com/nodesource/distributions/issues \
+if you think this is incorrect or would like your distribution to be considered for support"
+    exit 1
+fi
+
+## EPEL is needed for EL5, we don't install it if it's missing but
+## we can give guidance
+if [ "$DIST_TYPE" == "el" ] && [ "$DIST_VERSION" == "5" ]; then
+
+  print_status "Checking if EPEL is enabled..."
+
+  echo "+ yum repolist enabled 2> /dev/null | grep epel"
+  repolist=$(yum repolist enabled 2> /dev/null | grep epel)
+
+  if [ "X${repolist}" == "X" ]; then
+    print_status "Finding current EPEL release RPM..."
+
+    ## We can scrape the html to find the latest epel-release (likely 5.4)
+    epel_url="http://dl.fedoraproject.org/pub/epel/5/${DIST_ARCH}/"
+    epel_release_view="${epel_url}repoview/epel-release.html"
+    echo "+ curl -s $epel_release_view | grep -oE 'epel-release-[0-9\-]+\.noarch\.rpm'"
+    epel=$(curl -s $epel_release_view | grep -oE 'epel-release-[0-9\-]+\.noarch\.rpm')
+    if [ "X${epel}" = "X" ]; then
+      print_status "Error: Could not find current EPEL release RPM!"
+      exit 1
+    fi
+
+    print_status "\
+The EPEL (Extra Packages for Enterprise Linux) repository is a\n\
+prerequisite for installing Node.js on your operating system. Please\n\
+add it and re-run this setup script.\n\
+\n\
+The EPEL repository RPM is available at:\n\
+  ${epel_url}${epel}\n\
+You can try installing with: \`rpm -ivh <url>\`\
+"
+
+    exit 1
+  fi
+
+fi
+
+print_status "Downloading release setup RPM..."
+
+## Two-step process to install the nodesource-release RPM,
+## Download to a tmp file then install it directly with `rpm`.
+## We don't rely on RPM's ability to fetch from HTTPS directly
+echo "+ mktemp"
+RPM_TMP=$(mktemp || bail)
+
+exec_cmd "curl -sL -o '${RPM_TMP}' '${RELEASE_URL}'"
+
+print_status "Installing release setup RPM..."
+
+## --nosignature because nodesource-release contains the signature!
+exec_cmd "rpm -i --nosignature --force '${RPM_TMP}'"
+
+print_status "Cleaning up..."
+
+exec_cmd "rm -f '${RPM_TMP}'"
+
+print_status "Checking for existing installations..."
+
+## Nasty consequences if you have an existing Node or npm package
+## installed, need to inform if they are there
+echo "+ rpm -qa 'node|npm' | grep -v nodesource"
+EXISTING_NODE=$(rpm -qa 'node|npm|iojs' | grep -v nodesource)
+
+if [ "X${EXISTING_NODE}" != "X" ]; then
+
+  # NOTE(mordred) Removed -y from the yum command below.
+  print_status "\
+Your system appears to already have Node.js installed from an alternative source.\n\
+Run \`\033[1myum remove nodejs npm\033[22m\` (as root) to remove these first.\
+"
+
+fi
+
+# NOTE(mordred) Removed -y from the yum commands below.
+print_status "\
+Run \`\033[1myum install nodejs\033[22m\` (as root) to install Node.js 8.x and npm.\n\
+You may also need development tools to build native addons:\n\
+  \`yum install gcc-c++ make\`\
+"
+
+## Alternative to install dev tools: `yum groupinstall 'Development Tools'
+
+exit 0
diff --git a/tools/install-js-tools.sh b/tools/install-js-tools.sh
new file mode 100755
index 0000000..01d8854
--- /dev/null
+++ b/tools/install-js-tools.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright 2017 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if type apt-get; then
+    # Install https transport - otherwise apt-get HANGS on https urls
+    sudo apt-get update
+    sudo apt-get install apt-transport-https
+    # Install recent NodeJS repo
+    curl -sS https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add -
+    echo "deb https://deb.nodesource.com/node_8.x xenial main" | sudo tee /etc/apt/sources.list.d/nodesource.list
+    # Install yarn repo
+    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+    echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+    sudo apt-get update
+    sudo DEBIAN_FRONTEND=noninteractive \
+        apt-get -q --option "Dpkg::Options::=--force-confold" --assume-yes \
+        install nodejs yarn
+else
+    sudo curl https://dl.yarnpkg.com/rpm/yarn.repo -o /etc/yum.repos.d/yarn.repo
+    sudo $(dirname $0)/install-js-repos-rpm.sh
+    sudo yum -y install nodejs yarn
+fi
diff --git a/etc/status/.gitignore b/web/.gitignore
similarity index 100%
rename from etc/status/.gitignore
rename to web/.gitignore
diff --git a/etc/status/.jshintignore b/web/.jshintignore
similarity index 100%
rename from etc/status/.jshintignore
rename to web/.jshintignore
diff --git a/etc/status/.jshintrc b/web/.jshintrc
similarity index 100%
rename from etc/status/.jshintrc
rename to web/.jshintrc
diff --git a/web/config/webpack.common.js b/web/config/webpack.common.js
new file mode 100644
index 0000000..52ef1f6
--- /dev/null
+++ b/web/config/webpack.common.js
@@ -0,0 +1,137 @@
+const path = require('path');
+const webpack = require('webpack');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+
+module.exports = {
+  entry: {
+    main: './web/main.js',
+    // Tell webpack to extract 3rd party depdenencies which change less
+    // frequently.
+    vendor: [
+      'angular',
+      'bootstrap/dist/css/bootstrap.css',
+      'jquery-visibility/jquery-visibility',
+      'graphitejs/jquery.graphite.js'
+    ]
+  },
+  output: {
+    filename: '[name].js',
+    // path.resolve(__dirname winds up relative to the config dir
+    path: path.resolve(__dirname, '../../zuul/web/static'),
+    publicPath: ''
+  },
+  // Some folks prefer "cheaper" source-map for dev and one that is more
+  // expensive to build for prod. Debugging without the full source-map sucks,
+  // so define it here in common.
+  devtool: 'source-map',
+  plugins: [
+    new webpack.ProvidePlugin({
+        $: 'jquery/dist/jquery',
+        jQuery: 'jquery/dist/jquery',
+    }),
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'vendor',
+    }),
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'manifest',
+    }),
+    new CleanWebpackPlugin(
+        ['zuul/web/static'], { root: path.resolve(__dirname, '../..')}),
+    // Each of the entries below lists a specific 'chunk' which is one of the
+    // entry items from above. We can collapse this to just do one single
+    // output file.
+    new HtmlWebpackPlugin({
+      filename: 'status.html',
+      template: 'web/templates/status.ejs',
+      title: 'Zuul Status'
+    }),
+    new HtmlWebpackPlugin({
+      title: 'Zuul Builds',
+      template: 'web/templates/builds.ejs',
+      filename: 'builds.html'
+    }),
+    new HtmlWebpackPlugin({
+      title: 'Zuul Jobs',
+      template: 'web/templates/jobs.ejs',
+      filename: 'jobs.html'
+    }),
+    new HtmlWebpackPlugin({
+      title: 'Zuul Tenants',
+      template: 'web/templates/tenants.ejs',
+      filename: 'tenants.html'
+    }),
+    new HtmlWebpackPlugin({
+      title: 'Zuul Console Stream',
+      template: 'web/templates/stream.ejs',
+      filename: 'stream.html'
+    })
+  ],
+  module: {
+    rules: [
+      {
+        test: /\.js$/,
+        exclude: /node_modules/,
+        use: [
+          'babel-loader'
+        ]
+      },
+      {
+        test: /.css$/,
+        use: [
+          'style-loader',
+          'css-loader'
+        ]
+      },
+      {
+        test: /\.(png|svg|jpg|gif)$/,
+        use: ['file-loader'],
+      },
+      // The majority of the rules below are all about getting bootstrap copied
+      // appropriately.
+      {
+        test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
+        use: {
+          loader: "url-loader",
+          options: {
+            limit: 10000,
+            mimetype: 'application/font-woff'
+          }
+        }
+      },
+      {
+        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
+        use: {
+          loader: "url-loader",
+          options: {
+            limit: 10000,
+            mimetype: 'application/octet-stream'
+          }
+        }
+      },
+      {
+        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
+        use: ['file-loader'],
+      },
+      {
+        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
+        use: {
+          loader: "url-loader",
+          options: {
+            limit: 10000,
+            mimetype: 'image/svg+xml'
+          }
+        }
+      },
+      {
+        test: /\.html$/,
+        use: ['raw-loader'],
+        exclude: /node_modules/
+      },
+      {
+        test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
+        use: ['file-loader']
+      }
+    ]
+  }
+};
diff --git a/web/config/webpack.dev.js b/web/config/webpack.dev.js
new file mode 100644
index 0000000..8143883
--- /dev/null
+++ b/web/config/webpack.dev.js
@@ -0,0 +1,36 @@
+const path = require('path');
+const webpack = require('webpack');
+const Merge = require('webpack-merge');
+const CommonConfig = require('./webpack.common.js');
+
+module.exports = Merge(CommonConfig, {
+
+  // Enable Hot Module Replacement for devServer
+  devServer: {
+    hot: true,
+    contentBase: path.resolve(__dirname, './zuul/web/static'),
+    publicPath: '/'
+  },
+  module: {
+    rules: [
+      {
+        enforce: 'pre',
+        test: /\.js$/,
+        use: [
+          'babel-loader',
+          'eslint-loader'
+        ],
+        exclude: /node_modules/,
+      }
+    ]
+  },
+  plugins: [
+    new webpack.HotModuleReplacementPlugin(),
+    // We only need to bundle the demo files when we're running locally
+    new webpack.ProvidePlugin({
+        DemoStatusBasic: './status-basic.json',
+        DemoStatusOpenStack: './status-openstack.json',
+        DemoStatusTree: './status-tree.json'
+    }),
+  ]
+})
diff --git a/web/config/webpack.lint.js b/web/config/webpack.lint.js
new file mode 100644
index 0000000..3c490ba
--- /dev/null
+++ b/web/config/webpack.lint.js
@@ -0,0 +1,32 @@
+const path = require('path');
+const webpack = require('webpack');
+const Merge = require('webpack-merge');
+const CommonConfig = require('./webpack.common.js');
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
+
+module.exports = Merge(CommonConfig, {
+
+  module: {
+    rules: [
+      {
+        enforce: 'pre',
+        test: /\.js$/,
+        use: [
+          'babel-loader',
+          'eslint-loader'
+        ],
+        exclude: /node_modules/,
+      }
+    ]
+  },
+  plugins: [
+    new webpack.HotModuleReplacementPlugin(),
+    new BundleAnalyzerPlugin({
+      analyzerMode: 'static',
+      reportFilename: '../../../reports/bundle.html',
+      generateStatsFile: true,
+      openAnalyzer: false,
+      statsFilename: '../../../reports/stats.json',
+    }),
+  ]
+})
diff --git a/web/config/webpack.prod.js b/web/config/webpack.prod.js
new file mode 100644
index 0000000..79f5d51
--- /dev/null
+++ b/web/config/webpack.prod.js
@@ -0,0 +1,49 @@
+const path = require('path');
+const webpack = require('webpack');
+const Merge = require('webpack-merge');
+const CommonConfig = require('./webpack.common.js');
+const ArchivePlugin = require('webpack-archive-plugin');
+
+module.exports = Merge(CommonConfig, {
+  output: {
+    filename: '[name].[chunkhash].js',
+    // path.resolve(__dirname winds up relative to the config dir
+    path: path.resolve(__dirname, '../../zuul/web/static'),
+    publicPath: ''
+  },
+  plugins: [
+    new webpack.LoaderOptionsPlugin({
+      minimize: true,
+      debug: false
+    }),
+    new webpack.DefinePlugin({
+      'process.env': {
+        'NODE_ENV': JSON.stringify('production')
+      }
+    }),
+    // Keeps the vendor bundle from changing needlessly.
+    new webpack.HashedModuleIdsPlugin(),
+    new webpack.optimize.UglifyJsPlugin({
+      warningsFilter: function(filename) {
+        return ! /node_modules/.test(filename);
+      },
+      beautify: false,
+      mangle: {
+        screw_ie8: true,
+        keep_fnames: true
+      },
+      compress: {
+        screw_ie8: true
+      },
+      sourceMap: true,
+      comments: false
+    }),
+    new ArchivePlugin({
+      output: path.resolve(__dirname, '../../zuul-web'),
+      format: [
+        'tar',
+      ],
+      ext: 'tgz'
+    })
+  ]
+})
diff --git a/web/dashboard.js b/web/dashboard.js
new file mode 100644
index 0000000..77884e5
--- /dev/null
+++ b/web/dashboard.js
@@ -0,0 +1,115 @@
+// @licstart  The following is the entire license notice for the
+// JavaScript code in this page.
+//
+// Copyright 2017 Red Hat
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+// @licend  The above is the entire license notice
+// for the JavaScript code in this page.
+
+import 'bootstrap/dist/css/bootstrap.css'
+import angular from 'angular'
+
+import './styles/zuul.css'
+import './jquery.zuul'
+import { getSourceUrl } from './util'
+
+angular.module('zuulTenants', []).controller(
+    'mainController', function ($scope, $http, $location) {
+      $scope.tenants = undefined
+      $scope.tenants_fetch = function () {
+        $http.get(getSourceUrl('tenants', $location))
+            .then(function success (result) {
+              $scope.tenants = result.data
+            })
+      }
+      $scope.tenants_fetch()
+    })
+
+angular.module('zuulJobs', [], function ($locationProvider) {
+  $locationProvider.html5Mode({
+    enabled: true,
+    requireBase: false
+  })
+}).controller(
+    'mainController', function ($scope, $http, $location) {
+      $scope.jobs = undefined
+      $scope.jobs_fetch = function () {
+        $http.get(getSourceUrl('jobs', $location))
+            .then(function success (result) {
+              $scope.jobs = result.data
+            })
+      }
+      $scope.jobs_fetch()
+    })
+
+angular.module('zuulBuilds', [], function ($locationProvider) {
+  $locationProvider.html5Mode({
+    enabled: true,
+    requireBase: false
+  })
+}).controller('mainController', function ($scope, $http, $location) {
+  $scope.rowClass = function (build) {
+    if (build.result === 'SUCCESS') {
+      return 'success'
+    } else {
+      return 'warning'
+    }
+  }
+  let queryArgs = $location.search()
+  let url = $location.url()
+  if (queryArgs['source_url']) {
+    $scope.tenant = undefined
+  } else {
+    let tenantStart = url.lastIndexOf(
+      '/', url.lastIndexOf('/builds.html') - 1) + 1
+    let tenantLength = url.lastIndexOf('/builds.html') - tenantStart
+    $scope.tenant = url.substr(tenantStart, tenantLength)
+  }
+  $scope.builds = undefined
+  if (queryArgs['pipeline']) {
+    $scope.pipeline = queryArgs['pipeline']
+  } else { $scope.pipeline = '' }
+  if (queryArgs['job_name']) {
+    $scope.job_name = queryArgs['job_name']
+  } else { $scope.job_name = '' }
+  if (queryArgs['project']) {
+    $scope.project = queryArgs['project']
+  } else { $scope.project = '' }
+  $scope.builds_fetch = function () {
+    let queryString = ''
+    if ($scope.tenant) { queryString += '&tenant=' + $scope.tenant }
+    if ($scope.pipeline) { queryString += '&pipeline=' + $scope.pipeline }
+    if ($scope.job_name) { queryString += '&job_name=' + $scope.job_name }
+    if ($scope.project) { queryString += '&project=' + $scope.project }
+    if (queryString !== '') { queryString = '?' + queryString.substr(1) }
+    $http.get(getSourceUrl('builds', $location) + queryString)
+            .then(function success (result) {
+              for (let buildPos = 0;
+                     buildPos < result.data.length;
+                     buildPos += 1) {
+                let build = result.data[buildPos]
+                if (build.node_name == null) {
+                  build.node_name = 'master'
+                }
+                /* Fix incorect url for post_failure job */
+                if (build.log_url === build.job_name) {
+                  build.log_url = undefined
+                }
+              }
+              $scope.builds = result.data
+            })
+  }
+  $scope.builds_fetch()
+})
diff --git a/zuul/web/static/images/black.png b/web/images/black.png
similarity index 100%
rename from zuul/web/static/images/black.png
rename to web/images/black.png
Binary files differ
diff --git a/zuul/web/static/images/green.png b/web/images/green.png
similarity index 100%
rename from zuul/web/static/images/green.png
rename to web/images/green.png
Binary files differ
diff --git a/zuul/web/static/images/grey.png b/web/images/grey.png
similarity index 100%
rename from zuul/web/static/images/grey.png
rename to web/images/grey.png
Binary files differ
diff --git a/zuul/web/static/images/line-angle.png b/web/images/line-angle.png
similarity index 100%
rename from zuul/web/static/images/line-angle.png
rename to web/images/line-angle.png
Binary files differ
diff --git a/zuul/web/static/images/line-t.png b/web/images/line-t.png
similarity index 100%
rename from zuul/web/static/images/line-t.png
rename to web/images/line-t.png
Binary files differ
diff --git a/zuul/web/static/images/line.png b/web/images/line.png
similarity index 100%
rename from zuul/web/static/images/line.png
rename to web/images/line.png
Binary files differ
diff --git a/zuul/web/static/images/red.png b/web/images/red.png
similarity index 100%
rename from zuul/web/static/images/red.png
rename to web/images/red.png
Binary files differ
diff --git a/web/jquery.zuul.js b/web/jquery.zuul.js
new file mode 100644
index 0000000..737b018
--- /dev/null
+++ b/web/jquery.zuul.js
@@ -0,0 +1,929 @@
+/* global Image, jQuery */
+// jquery plugin for Zuul status page
+//
+// @licstart  The following is the entire license notice for the
+// JavaScript code in this page.
+//
+// Copyright 2012 OpenStack Foundation
+// Copyright 2013 Timo Tijhof
+// Copyright 2013 Wikimedia Foundation
+// Copyright 2014 Rackspace Australia
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+// @licend  The above is the entire license notice
+// for the JavaScript code in this page.
+
+import RedImage from './images/red.png'
+import GreyImage from './images/grey.png'
+import GreenImage from './images/green.png'
+import BlackImage from './images/black.png'
+import LineImage from './images/line.png'
+import LineAngleImage from './images/line-angle.png'
+import LineTImage from './images/line-t.png';
+
+(function ($) {
+  function setCookie (name, value) {
+    document.cookie = name + '=' + value + '; path=/'
+  }
+
+  function readCookie (name, defaultValue) {
+    let nameEQ = name + '='
+    let ca = document.cookie.split(';')
+    for (let i = 0; i < ca.length; i++) {
+      let c = ca[i]
+      while (c.charAt(0) === ' ') {
+        c = c.substring(1, c.length)
+      }
+      if (c.indexOf(nameEQ) === 0) {
+        return c.substring(nameEQ.length, c.length)
+      }
+    }
+    return defaultValue
+  }
+
+  $.zuul = function (options) {
+    options = $.extend({
+      'enabled': true,
+      'graphite_url': '',
+      'source': 'status',
+      'source_data': null,
+      'msg_id': '#zuul_msg',
+      'pipelines_id': '#zuul_pipelines',
+      'queue_events_num': '#zuul_queue_events_num',
+      'queue_management_events_num': '#zuul_queue_management_events_num',
+      'queue_results_num': '#zuul_queue_results_num'
+    }, options)
+
+    let collapsedExceptions = []
+    let currentFilter = readCookie('zuul_filter_string', '')
+    let changeSetInURL = window.location.href.split('#')[1]
+    if (changeSetInURL) {
+      currentFilter = changeSetInURL
+    }
+    let $jq
+
+    let xhr
+    let zuulGraphUpdateCount = 0
+    let zuulSparklineURLs = {}
+
+    function getSparklineURL (pipelineName) {
+      if (options.graphite_url !== '') {
+        if (!(pipelineName in zuulSparklineURLs)) {
+          zuulSparklineURLs[pipelineName] = $.fn.graphite
+                        .geturl({
+                          url: options.graphite_url,
+                          from: '-8hours',
+                          width: 100,
+                          height: 26,
+                          margin: 0,
+                          hideLegend: true,
+                          hideAxes: true,
+                          hideGrid: true,
+                          target: [
+                            'color(stats.gauges.zuul.pipeline.' + pipelineName +
+                                ".current_changes, '6b8182')"
+                          ]
+                        })
+        }
+        return zuulSparklineURLs[pipelineName]
+      }
+      return false
+    }
+
+    let format = {
+      job: function (job) {
+        let $jobLine = $('<span />')
+
+        if (job.result !== null) {
+          $jobLine.append(
+                        $('<a />')
+                            .addClass('zuul-job-name')
+                            .attr('href', job.report_url)
+                            .text(job.name)
+                    )
+        } else if (job.url !== null) {
+          $jobLine.append(
+                        $('<a />')
+                            .addClass('zuul-job-name')
+                            .attr('href', job.url)
+                            .text(job.name)
+                    )
+        } else {
+          $jobLine.append(
+                        $('<span />')
+                            .addClass('zuul-job-name')
+                            .text(job.name)
+                    )
+        }
+
+        $jobLine.append(this.job_status(job))
+
+        if (job.voting === false) {
+          $jobLine.append(
+                        $(' <small />')
+                            .addClass('zuul-non-voting-desc')
+                            .text(' (non-voting)')
+                    )
+        }
+
+        $jobLine.append($('<div style="clear: both"></div>'))
+        return $jobLine
+      },
+
+      job_status: function (job) {
+        let result = job.result ? job.result.toLowerCase() : null
+        if (result === null) {
+          result = job.url ? 'in progress' : 'queued'
+        }
+
+        if (result === 'in progress') {
+          return this.job_progress_bar(job.elapsed_time,
+                                                        job.remaining_time)
+        } else {
+          return this.status_label(result)
+        }
+      },
+
+      status_label: function (result) {
+        let $status = $('<span />')
+        $status.addClass('zuul-job-result label')
+
+        switch (result) {
+          case 'success':
+            $status.addClass('label-success')
+            break
+          case 'failure':
+            $status.addClass('label-danger')
+            break
+          case 'unstable':
+            $status.addClass('label-warning')
+            break
+          case 'skipped':
+            $status.addClass('label-info')
+            break
+          // 'in progress' 'queued' 'lost' 'aborted' ...
+          default:
+            $status.addClass('label-default')
+        }
+        $status.text(result)
+        return $status
+      },
+
+      job_progress_bar: function (elapsedTime, remainingTime) {
+        let progressPercent = 100 * (elapsedTime / (elapsedTime +
+                                                              remainingTime))
+        let $barInner = $('<div />')
+                    .addClass('progress-bar')
+                    .attr('role', 'progressbar')
+                    .attr('aria-valuenow', 'progressbar')
+                    .attr('aria-valuemin', progressPercent)
+                    .attr('aria-valuemin', '0')
+                    .attr('aria-valuemax', '100')
+                    .css('width', progressPercent + '%')
+
+        let $barOutter = $('<div />')
+                    .addClass('progress zuul-job-result')
+                    .append($barInner)
+
+        return $barOutter
+      },
+
+      enqueueTime: function (ms) {
+        // Special format case for enqueue time to add style
+        let hours = 60 * 60 * 1000
+        let now = Date.now()
+        let delta = now - ms
+        let status = 'text-success'
+        let text = this.time(delta, true)
+        if (delta > (4 * hours)) {
+          status = 'text-danger'
+        } else if (delta > (2 * hours)) {
+          status = 'text-warning'
+        }
+        return '<span class="' + status + '">' + text + '</span>'
+      },
+
+      time: function (ms, words) {
+        if (typeof (words) === 'undefined') {
+          words = false
+        }
+        let seconds = (+ms) / 1000
+        let minutes = Math.floor(seconds / 60)
+        let hours = Math.floor(minutes / 60)
+        seconds = Math.floor(seconds % 60)
+        minutes = Math.floor(minutes % 60)
+        let r = ''
+        if (words) {
+          if (hours) {
+            r += hours
+            r += ' hr '
+          }
+          r += minutes + ' min'
+        } else {
+          if (hours < 10) {
+            r += '0'
+          }
+          r += hours + ':'
+          if (minutes < 10) {
+            r += '0'
+          }
+          r += minutes + ':'
+          if (seconds < 10) {
+            r += '0'
+          }
+          r += seconds
+        }
+        return r
+      },
+
+      changeTotalProgressBar: function (change) {
+        let jobPercent = Math.floor(100 / change.jobs.length)
+        let $barOutter = $('<div />')
+                    .addClass('progress zuul-change-total-result')
+
+        $.each(change.jobs, function (i, job) {
+          let result = job.result ? job.result.toLowerCase() : null
+          if (result === null) {
+            result = job.url ? 'in progress' : 'queued'
+          }
+
+          if (result !== 'queued') {
+            let $barInner = $('<div />')
+                            .addClass('progress-bar')
+
+            switch (result) {
+              case 'success':
+                $barInner.addClass('progress-bar-success')
+                break
+              case 'lost':
+              case 'failure':
+                $barInner.addClass('progress-bar-danger')
+                break
+              case 'unstable':
+                $barInner.addClass('progress-bar-warning')
+                break
+              case 'in progress':
+              case 'queued':
+                break
+            }
+            $barInner.attr('title', job.name)
+                            .css('width', jobPercent + '%')
+            $barOutter.append($barInner)
+          }
+        })
+        return $barOutter
+      },
+
+      changeHeader: function (change) {
+        let changeId = change.id || 'NA'
+
+        let $changeLink = $('<small />')
+        if (change.url !== null) {
+          let githubId = changeId.match(/^([0-9]+),([0-9a-f]{40})$/)
+          if (githubId) {
+            $changeLink.append(
+                            $('<a />').attr('href', change.url).append(
+                                $('<abbr />')
+                                    .attr('title', changeId)
+                                    .text('#' + githubId[1])
+                            )
+                        )
+          } else if (/^[0-9a-f]{40}$/.test(changeId)) {
+            let changeIdShort = changeId.slice(0, 7)
+            $changeLink.append(
+                            $('<a />').attr('href', change.url).append(
+                                $('<abbr />')
+                                    .attr('title', changeId)
+                                    .text(changeIdShort)
+                            )
+                        )
+          } else {
+            $changeLink.append(
+                            $('<a />').attr('href', change.url).text(changeId)
+                        )
+          }
+        } else {
+          if (changeId.length === 40) {
+            changeId = changeId.substr(0, 7)
+          }
+          $changeLink.text(changeId)
+        }
+
+        let $changeProgressRowLeft = $('<div />')
+                    .addClass('col-xs-4')
+                    .append($changeLink)
+        let $changeProgressRowRight = $('<div />')
+                    .addClass('col-xs-8')
+                    .append(this.changeTotalProgressBar(change))
+
+        let $changeProgressRow = $('<div />')
+                    .addClass('row')
+                    .append($changeProgressRowLeft)
+                    .append($changeProgressRowRight)
+
+        let $projectSpan = $('<span />')
+                    .addClass('change_project')
+                    .text(change.project)
+
+        let $left = $('<div />')
+                    .addClass('col-xs-8')
+                    .append($projectSpan, $changeProgressRow)
+
+        let remainingTime = this.time(change.remaining_time, true)
+        let enqueueTime = this.enqueueTime(change.enqueue_time)
+        let $remainingTime = $('<small />').addClass('time')
+                    .attr('title', 'Remaining Time').html(remainingTime)
+        let $enqueueTime = $('<small />').addClass('time')
+                    .attr('title', 'Elapsed Time').html(enqueueTime)
+
+        let $right = $('<div />')
+        if (change.live === true) {
+          $right.addClass('col-xs-4 text-right')
+                        .append($remainingTime, $('<br />'), $enqueueTime)
+        }
+
+        let $header = $('<div />')
+                    .addClass('row')
+                    .append($left, $right)
+        return $header
+      },
+
+      change_list: function (jobs) {
+        let format = this
+        let $list = $('<ul />')
+                    .addClass('list-group zuul-patchset-body')
+
+        $.each(jobs, function (i, job) {
+          let $item = $('<li />')
+                        .addClass('list-group-item')
+                        .addClass('zuul-change-job')
+                        .append(format.job(job))
+          $list.append($item)
+        })
+
+        return $list
+      },
+
+      changePanel: function (change) {
+        let $header = $('<div />')
+                    .addClass('panel-heading zuul-patchset-header')
+                    .append(this.changeHeader(change))
+
+        let panelId = change.id ? change.id.replace(',', '_')
+                                         : change.project.replace('/', '_') +
+                                           '-' + change.enqueue_time
+        let $panel = $('<div />')
+                    .attr('id', panelId)
+                    .addClass('panel panel-default zuul-change')
+                    .append($header)
+                    .append(this.change_list(change.jobs))
+
+        $header.click(this.toggle_patchset)
+        return $panel
+      },
+
+      change_status_icon: function (change) {
+        let iconFile = GreenImage
+        let iconTitle = 'Succeeding'
+
+        if (change.active !== true) {
+          // Grey icon
+          iconFile = GreyImage
+          iconTitle = 'Waiting until closer to head of queue to' +
+                        ' start jobs'
+        } else if (change.live !== true) {
+          // Grey icon
+          iconFile = GreyImage
+          iconTitle = 'Dependent change required for testing'
+        } else if (change.failing_reasons &&
+                         change.failing_reasons.length > 0) {
+          let reason = change.failing_reasons.join(', ')
+          iconTitle = 'Failing because ' + reason
+          if (reason.match(/merge conflict/)) {
+            // Black icon
+            iconFile = BlackImage
+          } else {
+            // Red icon
+            iconFile = RedImage
+          }
+        }
+
+        let $icon = $('<img />')
+                    .attr('src', iconFile)
+                    .attr('title', iconTitle)
+                    .css('margin-top', '-6px')
+
+        return $icon
+      },
+
+      change_with_status_tree: function (change, changeQueue) {
+        let $changeRow = $('<tr />')
+
+        for (let i = 0; i < changeQueue._tree_columns; i++) {
+          let $treeCell = $('<td />')
+                        .css('height', '100%')
+                        .css('padding', '0 0 10px 0')
+                        .css('margin', '0')
+                        .css('width', '16px')
+                        .css('min-width', '16px')
+                        .css('overflow', 'hidden')
+                        .css('vertical-align', 'top')
+
+          if (i < change._tree.length && change._tree[i] !== null) {
+            $treeCell.css('background-image',
+                                       'url(' + LineImage + ')')
+                            .css('background-repeat', 'repeat-y')
+          }
+
+          if (i === change._tree_index) {
+            $treeCell.append(
+                            this.change_status_icon(change))
+          }
+          if (change._tree_branches.indexOf(i) !== -1) {
+            let $image = $('<img />')
+                            .css('vertical-align', 'baseline')
+            if (change._tree_branches.indexOf(i) ===
+                            change._tree_branches.length - 1) {
+              // Angle line
+              $image.attr('src', LineAngleImage)
+            } else {
+              // T line
+              $image.attr('src', LineTImage)
+            }
+            $treeCell.append($image)
+          }
+          $changeRow.append($treeCell)
+        }
+
+        let changeWidth = 360 - 16 * changeQueue._tree_columns
+        let $changeColumn = $('<td />')
+                    .css('width', changeWidth + 'px')
+                    .addClass('zuul-change-cell')
+                    .append(this.changePanel(change))
+
+        $changeRow.append($changeColumn)
+
+        let $changeTable = $('<table />')
+                    .addClass('zuul-change-box')
+                    .css('-moz-box-sizing', 'content-box')
+                    .css('box-sizing', 'content-box')
+                    .append($changeRow)
+
+        return $changeTable
+      },
+
+      pipeline_sparkline: function (pipelineName) {
+        if (options.graphite_url !== '') {
+          let $sparkline = $('<img />')
+                        .addClass('pull-right')
+                        .attr('src', getSparklineURL(pipelineName))
+          return $sparkline
+        }
+        return false
+      },
+
+      pipeline_header: function (pipeline, count) {
+        // Format the pipeline name, sparkline and description
+        let $headerDiv = $('<div />')
+                    .addClass('zuul-pipeline-header')
+
+        let $heading = $('<h3 />')
+                    .css('vertical-align', 'middle')
+                    .text(pipeline.name)
+                    .append(
+                        $('<span />')
+                            .addClass('badge pull-right')
+                            .css('vertical-align', 'middle')
+                            .css('margin-top', '0.5em')
+                            .text(count)
+                    )
+                    .append(this.pipeline_sparkline(pipeline.name))
+
+        $headerDiv.append($heading)
+
+        if (typeof pipeline.description === 'string') {
+          let descr = $('<small />')
+          $.each(pipeline.description.split(/\r?\n\r?\n/),
+                  function (index, descrPart) {
+                    descr.append($('<p />').text(descrPart))
+                  })
+          $headerDiv.append($('<p />').append(descr))
+        }
+        return $headerDiv
+      },
+
+      pipeline: function (pipeline, count) {
+        let format = this
+        let $html = $('<div />')
+                    .addClass('zuul-pipeline col-md-4')
+                    .append(this.pipeline_header(pipeline, count))
+
+        $.each(pipeline.change_queues, function (queueIndex, changeQueue) {
+          $.each(changeQueue.heads, function (headIndex, changes) {
+            if (pipeline.change_queues.length > 1 && headIndex === 0) {
+              let name = changeQueue.name
+              let shortName = name
+              if (shortName.length > 32) {
+                shortName = shortName.substr(0, 32) + '...'
+              }
+              $html.append($('<p />')
+                            .text('Queue: ')
+                            .append(
+                                $('<abbr />')
+                                .attr('title', name)
+                                .text(shortName)
+                                )
+                            )
+            }
+
+            $.each(changes, function (changeIndex, change) {
+              let $changeBox =
+                        format.change_with_status_tree(
+                                change, changeQueue)
+              $html.append($changeBox)
+              format.display_patchset($changeBox)
+            })
+          })
+        })
+        return $html
+      },
+
+      toggle_patchset: function (e) {
+        // Toggle showing/hiding the patchset when the header is clicked.
+        if (e.target.nodeName.toLowerCase() === 'a') {
+                    // Ignore clicks from gerrit patch set link
+          return
+        }
+
+        // Grab the patchset panel
+        let $panel = $(e.target).parents('.zuul-change')
+        let $body = $panel.children('.zuul-patchset-body')
+        $body.toggle(200)
+        let collapsedIndex = collapsedExceptions.indexOf(
+                    $panel.attr('id'))
+        if (collapsedIndex === -1) {
+          // Currently not an exception, add it to list
+          collapsedExceptions.push($panel.attr('id'))
+        } else {
+          // Currently an except, remove from exceptions
+          collapsedExceptions.splice(collapsedIndex, 1)
+        }
+      },
+
+      display_patchset: function ($changeBox, animate) {
+        // Determine if to show or hide the patchset and/or the results
+        // when loaded
+
+        // See if we should hide the body/results
+        let $panel = $changeBox.find('.zuul-change')
+        let panelChange = $panel.attr('id')
+        let $body = $panel.children('.zuul-patchset-body')
+        let expandByDefault = $('#expand_by_default')
+                    .prop('checked')
+
+        let collapsedIndex = collapsedExceptions
+                    .indexOf(panelChange)
+
+        if ((expandByDefault && collapsedIndex === -1) ||
+                    (!expandByDefault && collapsedIndex !== -1)) {
+          // Expand by default, or is an exception
+          $body.show(animate)
+        } else {
+          $body.hide(animate)
+        }
+
+        // Check if we should hide the whole panel
+        let panelProject = $panel.find('.change_project').text()
+                    .toLowerCase()
+
+        let panelPipeline = $changeBox
+                    .parents('.zuul-pipeline')
+                    .find('.zuul-pipeline-header > h3')
+                    .html()
+                    .toLowerCase()
+
+        if (currentFilter !== '') {
+          let showPanel = false
+          let filter = currentFilter.trim().split(/[\s,]+/)
+          $.each(filter, function (index, filterVal) {
+            if (filterVal !== '') {
+              filterVal = filterVal.toLowerCase()
+              if (panelProject.indexOf(filterVal) !== -1 ||
+                      panelPipeline.indexOf(filterVal) !== -1 ||
+                      panelChange.indexOf(filterVal) !== -1) {
+                showPanel = true
+              }
+            }
+          })
+          if (showPanel === true) {
+            $changeBox.show(animate)
+          } else {
+            $changeBox.hide(animate)
+          }
+        } else {
+          $changeBox.show(animate)
+        }
+      }
+    }
+
+    let app = {
+      schedule: function (app) {
+        app = app || this
+        if (!options.enabled) {
+          setTimeout(function () { app.schedule(app) }, 5000)
+          return
+        }
+        app.update().always(function () {
+          setTimeout(function () { app.schedule(app) }, 5000)
+        })
+
+        // Only update graphs every minute
+        if (zuulGraphUpdateCount > 11) {
+          zuulGraphUpdateCount = 0
+          $.zuul.update_sparklines()
+        }
+      },
+      injest: function (data, $msg) {
+        if ('message' in data) {
+          $msg.removeClass('alert-danger')
+                        .addClass('alert-info')
+                        .text(data.message)
+                        .show()
+        } else {
+          $msg.empty()
+                        .hide()
+        }
+
+        if ('zuul_version' in data) {
+          $('#zuul-version-span').text(data.zuul_version)
+        }
+        if ('last_reconfigured' in data) {
+          let lastReconfigured =
+                        new Date(data.last_reconfigured)
+          $('#last-reconfigured-span').text(
+                        lastReconfigured.toString())
+        }
+
+        let $pipelines = $(options.pipelines_id)
+        $pipelines.html('')
+        $.each(data.pipelines, function (i, pipeline) {
+          let count = app.create_tree(pipeline)
+          $pipelines.append(
+                        format.pipeline(pipeline, count))
+        })
+
+        $(options.queue_events_num).text(
+                    data.trigger_event_queue
+                        ? data.trigger_event_queue.length : '0'
+                )
+        $(options.queue_results_num).text(
+                    data.result_event_queue
+                        ? data.result_event_queue.length : '0'
+                )
+      },
+      /** @return {jQuery.Promise} */
+      update: function () {
+        // Cancel the previous update if it hasn't completed yet.
+        if (xhr) {
+          xhr.abort()
+        }
+
+        this.emit('update-start')
+        let app = this
+
+        let $msg = $(options.msg_id)
+        if (options.source_data !== null) {
+          app.injest(options.source_data, $msg)
+          return
+        }
+        xhr = $.getJSON(options.source)
+                    .done(function (data) {
+                      app.injest(data, $msg)
+                    })
+                    .fail(function (jqXHR, statusText, errMsg) {
+                      if (statusText === 'abort') {
+                        return
+                      }
+                      $msg.text(options.source + ': ' + errMsg)
+                            .addClass('alert-danger')
+                            .removeClass('zuul-msg-wrap-off')
+                            .show()
+                    })
+                    .always(function () {
+                      xhr = undefined
+                      app.emit('update-end')
+                    })
+
+        return xhr
+      },
+
+      update_sparklines: function () {
+        $.each(zuulSparklineURLs, function (name, url) {
+          let newimg = new Image()
+          let parts = url.split('#')
+          newimg.src = parts[0] + '#' + new Date().getTime()
+          $(newimg).load(function () {
+            zuulSparklineURLs[name] = newimg.src
+          })
+        })
+      },
+
+      emit: function () {
+        $jq.trigger.apply($jq, arguments)
+        return this
+      },
+      on: function () {
+        $jq.on.apply($jq, arguments)
+        return this
+      },
+      one: function () {
+        $jq.one.apply($jq, arguments)
+        return this
+      },
+
+      controlForm: function () {
+        // Build the filter form filling anything from cookies
+
+        let $controlForm = $('<form />')
+                    .attr('role', 'form')
+                    .addClass('form-inline')
+                    .submit(this.handleFilterChange)
+
+        $controlForm
+                    .append(this.filterFormGroup())
+                    .append(this.expandFormGroup())
+
+        return $controlForm
+      },
+
+      filterFormGroup: function () {
+        // Update the filter form with a clear button if required
+
+        let $label = $('<label />')
+                    .addClass('control-label')
+                    .attr('for', 'filter_string')
+                    .text('Filters')
+                    .css('padding-right', '0.5em')
+
+        let $input = $('<input />')
+                    .attr('type', 'text')
+                    .attr('id', 'filter_string')
+                    .addClass('form-control')
+                    .attr('title',
+                          'project(s), pipeline(s) or review(s) comma ' +
+                          'separated')
+                    .attr('value', currentFilter)
+
+        $input.change(this.handleFilterChange)
+
+        let $clearIcon = $('<span />')
+                    .addClass('form-control-feedback')
+                    .addClass('glyphicon glyphicon-remove-circle')
+                    .attr('id', 'filter_form_clear_box')
+                    .attr('title', 'clear filter')
+                    .css('cursor', 'pointer')
+
+        $clearIcon.click(function () {
+          $('#filter_string').val('').change()
+        })
+
+        if (currentFilter === '') {
+          $clearIcon.hide()
+        }
+
+        let $formGroup = $('<div />')
+                    .addClass('form-group has-feedback')
+                    .append($label, $input, $clearIcon)
+        return $formGroup
+      },
+
+      expandFormGroup: function () {
+        let expandByDefault = (
+                    readCookie('zuul_expand_by_default', false) === 'true')
+
+        let $checkbox = $('<input />')
+                    .attr('type', 'checkbox')
+                    .attr('id', 'expand_by_default')
+                    .prop('checked', expandByDefault)
+                    .change(this.handleExpandByDefault)
+
+        let $label = $('<label />')
+                    .css('padding-left', '1em')
+                    .html('Expand by default: ')
+                    .append($checkbox)
+
+        let $formGroup = $('<div />')
+                    .addClass('checkbox')
+                    .append($label)
+        return $formGroup
+      },
+
+      handleFilterChange: function () {
+        // Update the filter and save it to a cookie
+        currentFilter = $('#filter_string').val()
+        setCookie('zuul_filter_string', currentFilter)
+        if (currentFilter === '') {
+          $('#filter_form_clear_box').hide()
+        } else {
+          $('#filter_form_clear_box').show()
+        }
+
+        $('.zuul-change-box').each(function (index, obj) {
+          let $changeBox = $(obj)
+          format.display_patchset($changeBox, 200)
+        })
+        return false
+      },
+
+      handleExpandByDefault: function (e) {
+        // Handle toggling expand by default
+        setCookie('zuul_expand_by_default', e.target.checked)
+        collapsedExceptions = []
+        $('.zuul-change-box').each(function (index, obj) {
+          let $changeBox = $(obj)
+          format.display_patchset($changeBox, 200)
+        })
+      },
+
+      create_tree: function (pipeline) {
+        let count = 0
+        let pipelineMaxTreeColumns = 1
+        $.each(pipeline.change_queues,
+                function (changeQueueIndex, changeQueue) {
+                  let tree = []
+                  let maxTreeColumns = 1
+                  let changes = []
+                  let lastTreeLength = 0
+                  $.each(changeQueue.heads, function (headIndex, head) {
+                    $.each(head, function (changeIndex, change) {
+                      changes[change.id] = change
+                      change._tree_position = changeIndex
+                    })
+                  })
+                  $.each(changeQueue.heads, function (headIndex, head) {
+                    $.each(head, function (changeIndex, change) {
+                      if (change.live === true) {
+                        count += 1
+                      }
+                      let idx = tree.indexOf(change.id)
+                      if (idx > -1) {
+                        change._tree_index = idx
+                        // remove...
+                        tree[idx] = null
+                        while (tree[tree.length - 1] === null) {
+                          tree.pop()
+                        }
+                      } else {
+                        change._tree_index = 0
+                      }
+                      change._tree_branches = []
+                      change._tree = []
+                      if (typeof (change.items_behind) === 'undefined') {
+                        change.items_behind = []
+                      }
+                      change.items_behind.sort(function (a, b) {
+                        return (changes[b]._tree_position - changes[a]._tree_position)
+                      })
+                      $.each(change.items_behind, function (i, id) {
+                        tree.push(id)
+                        if (tree.length > lastTreeLength && lastTreeLength > 0) {
+                          change._tree_branches.push(tree.length - 1)
+                        }
+                      })
+                      if (tree.length > maxTreeColumns) {
+                        maxTreeColumns = tree.length
+                      }
+                      if (tree.length > pipelineMaxTreeColumns) {
+                        pipelineMaxTreeColumns = tree.length
+                      }
+                      change._tree = tree.slice(0) // make a copy
+                      lastTreeLength = tree.length
+                    })
+                  })
+                  changeQueue._tree_columns = maxTreeColumns
+                })
+        pipeline._tree_columns = pipelineMaxTreeColumns
+        return count
+      }
+    }
+
+    $jq = $(app)
+    return {
+      options: options,
+      format: format,
+      app: app,
+      jq: $jq
+    }
+  }
+}(jQuery))
diff --git a/web/main.js b/web/main.js
new file mode 100644
index 0000000..3eea2f7
--- /dev/null
+++ b/web/main.js
@@ -0,0 +1,25 @@
+// Main library entrypoint
+//
+// @licstart  The following is the entire license notice for the
+// JavaScript code in this page.
+//
+// Copyright 2018 Red Hat, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+// @licend  The above is the entire license notice
+// for the JavaScript code in this page.
+
+import './status'
+import './stream'
+import './dashboard'
diff --git a/etc/status/public_html/status-basic.json-sample b/web/status-basic.json
similarity index 100%
rename from etc/status/public_html/status-basic.json-sample
rename to web/status-basic.json
diff --git a/etc/status/public_html/status-openstack.json-sample b/web/status-openstack.json
similarity index 100%
rename from etc/status/public_html/status-openstack.json-sample
rename to web/status-openstack.json
diff --git a/etc/status/public_html/status-tree.json-sample b/web/status-tree.json
similarity index 100%
rename from etc/status/public_html/status-tree.json-sample
rename to web/status-tree.json
diff --git a/web/status.js b/web/status.js
new file mode 100644
index 0000000..81658e6
--- /dev/null
+++ b/web/status.js
@@ -0,0 +1,126 @@
+/* global jQuery, URL, DemoStatusBasic, DemoStatusOpenStack, DemoStatusTree, BuiltinConfig */
+// Client script for Zuul status page
+//
+// @licstart  The following is the entire license notice for the
+// JavaScript code in this page.
+//
+// Copyright 2013 OpenStack Foundation
+// Copyright 2013 Timo Tijhof
+// Copyright 2013 Wikimedia Foundation
+// Copyright 2014 Rackspace Australia
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+// @licend  The above is the entire license notice
+// for the JavaScript code in this page.
+
+import 'bootstrap/dist/css/bootstrap.css'
+import 'jquery-visibility/jquery-visibility'
+import 'graphitejs/jquery.graphite.js'
+import angular from 'angular'
+
+import './styles/zuul.css'
+import './jquery.zuul'
+import { getSourceUrl } from './util'
+
+/**
+ * @return The $.zuul instance
+ */
+function zuulStart ($) {
+  // Start the zuul app (expects default dom)
+
+  let $container, $indicator
+
+  let url = new URL(window.location)
+  let params = {
+    // graphite_url: 'http://graphite.openstack.org/render/'
+  }
+
+  if (typeof BuiltinConfig !== 'undefined') {
+    params['source'] = BuiltinConfig.api_endpoint + '/' + 'status'
+  } else if (url.searchParams.has('source_url')) {
+    params['source'] = url.searchParams.get('source_url') + '/' + 'status'
+  } else if (url.searchParams.has('demo')) {
+    let demo = url.searchParams.get('demo') || 'basic'
+    if (demo === 'basic') {
+      params['source_data'] = DemoStatusBasic
+    } else if (demo === 'openstack') {
+      params['source_data'] = DemoStatusOpenStack
+    } else if (demo === 'tree') {
+      params['source_data'] = DemoStatusTree
+    }
+  } else {
+    params['source'] = getSourceUrl('status')
+  }
+
+  let zuul = $.zuul(params)
+
+  zuul.jq.on('update-start', function () {
+    $container.addClass('zuul-container-loading')
+    $indicator.addClass('zuul-spinner-on')
+  })
+
+  zuul.jq.on('update-end', function () {
+    $container.removeClass('zuul-container-loading')
+    setTimeout(function () {
+      $indicator.removeClass('zuul-spinner-on')
+    }, 500)
+  })
+
+  zuul.jq.one('update-end', function () {
+    // Do this asynchronous so that if the first update adds a
+    // message, it will not animate while we fade in the content.
+    // Instead it simply appears with the rest of the content.
+    setTimeout(function () {
+      // Fade in the content
+      $container.addClass('zuul-container-ready')
+    })
+  })
+
+  $(function ($) {
+    // DOM ready
+    $container = $('#zuul-container')
+    $indicator = $('#zuul-spinner')
+    $('#zuul_controls').append(zuul.app.controlForm())
+
+    zuul.app.schedule()
+
+    $(document).on({
+      'show.visibility': function () {
+        zuul.options.enabled = true
+        zuul.app.update()
+      },
+      'hide.visibility': function () {
+        zuul.options.enabled = false
+      }
+    })
+  })
+
+  return zuul
+}
+
+if (module.hot) {
+  // This doesn't fully work with our jquery plugin because $.zuul is already
+  // instantiated. Leaving it here to show where a hook can happen if we can
+  // figure out a way to live update it. When it's not there, an update to
+  // jquery.zuul.js triggers a page reload.
+  // module.hot.accept('./jquery.zuul', function() {
+  //   console.log('Accepting the updated module!');
+  // })
+}
+
+angular.module('zuulStatus', []).controller(
+  'mainController', function ($scope, $http) {
+    zuulStart(jQuery)
+  }
+)
diff --git a/web/stream.js b/web/stream.js
new file mode 100644
index 0000000..824948d
--- /dev/null
+++ b/web/stream.js
@@ -0,0 +1,99 @@
+/* global URL, WebSocket, BuiltinConfig */
+// Client script for Zuul Log Streaming
+//
+// @licstart  The following is the entire license notice for the
+// JavaScript code in this page.
+//
+// Copyright 2017 BMW Car IT GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+// @licend  The above is the entire license notice for the JavaScript code in
+// this page.
+
+import angular from 'angular'
+import './styles/stream.css'
+
+function escapeLog (text) {
+  const pattern = /[<>&"']/g
+
+  return text.replace(pattern, function (match) {
+    return '&#' + match.charCodeAt(0) + ';'
+  })
+}
+
+function zuulStartStream () {
+  let pageUpdateInMS = 250
+  let receiveBuffer = ''
+
+  setInterval(function () {
+    console.log('autoScroll')
+    if (receiveBuffer !== '') {
+      document.getElementById('zuulstreamcontent').innerHTML += receiveBuffer
+      receiveBuffer = ''
+      if (document.getElementById('autoscroll').checked) {
+        window.scrollTo(0, document.body.scrollHeight)
+      }
+    }
+  }, pageUpdateInMS)
+
+  let url = new URL(window.location)
+
+  let params = {
+    uuid: url.searchParams.get('uuid')
+  }
+  document.getElementById('pagetitle').innerHTML = params['uuid']
+  if (url.searchParams.has('logfile')) {
+    params['logfile'] = url.searchParams.get('logfile')
+    let logfileSuffix = `(${params['logfile']})`
+    document.getElementById('pagetitle').innerHTML += logfileSuffix
+  }
+  if (typeof BuiltinConfig !== 'undefined') {
+    params['websocket_url'] = BuiltinConfig.websocket_url
+  } else if (url.searchParams.has('websocket_url')) {
+    params['websocket_url'] = url.searchParams.get('websocket_url')
+  } else {
+    // Websocket doesn't accept relative urls so construct an
+    // absolute one.
+    let protocol = ''
+    if (url['protocol'] === 'https:') {
+      protocol = 'wss://'
+    } else {
+      protocol = 'ws://'
+    }
+    let path = url['pathname'].replace(/stream.html.*$/g, '') + 'console-stream'
+    params['websocket_url'] = protocol + url['host'] + path
+  }
+  let ws = new WebSocket(params['websocket_url'])
+
+  ws.onmessage = function (event) {
+    console.log('onmessage')
+    receiveBuffer = receiveBuffer + escapeLog(event.data)
+  }
+
+  ws.onopen = function (event) {
+    console.log('onopen')
+    ws.send(JSON.stringify(params))
+  }
+
+  ws.onclose = function (event) {
+    console.log('onclose')
+    receiveBuffer = receiveBuffer + '\n--- END OF STREAM ---\n'
+  }
+}
+
+angular.module('zuulStream', []).controller(
+  'mainController', function ($scope, $http) {
+    window.onload = zuulStartStream()
+  }
+)
diff --git a/web/styles/stream.css b/web/styles/stream.css
new file mode 100644
index 0000000..28bf02b
--- /dev/null
+++ b/web/styles/stream.css
@@ -0,0 +1,18 @@
+body#zuulstream {
+  font-family: monospace;
+  background-color: black;
+  color: lightgrey;
+}
+
+#zuulstreamoverlay {
+    position: fixed;
+    top: 5px;
+    right: 5px;
+    background-color: darkgrey;
+    color: black;
+}
+
+pre#zuulstreamcontent {
+    white-space: pre;
+    margin: 0px 10px;
+}
diff --git a/etc/status/public_html/styles/zuul.css b/web/styles/zuul.css
similarity index 99%
rename from etc/status/public_html/styles/zuul.css
rename to web/styles/zuul.css
index 44fd737..3eecc35 100644
--- a/etc/status/public_html/styles/zuul.css
+++ b/web/styles/zuul.css
@@ -55,4 +55,4 @@
 .zuul-patchset-header {
     font-size: small;
     padding: 8px 12px;
-}
\ No newline at end of file
+}
diff --git a/zuul/web/static/builds.html b/web/templates/builds.ejs
similarity index 86%
rename from zuul/web/static/builds.html
rename to web/templates/builds.ejs
index ace1e0a..25461ac 100644
--- a/zuul/web/static/builds.html
+++ b/web/templates/builds.ejs
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
 Copyright 2017 Red Hat
 
@@ -13,15 +14,10 @@
 License for the specific language governing permissions and limitations
 under the License.
 -->
-<!DOCTYPE html>
 <html>
 <head>
-    <title>Zuul Builds</title>
-    <link rel="stylesheet" href="../static/bootstrap/css/bootstrap.min.css">
-    <link rel="stylesheet" href="../static/styles/zuul.css" />
-    <script src="../static/js/jquery.min.js"></script>
-    <script src="../static/js/angular.min.js"></script>
-    <script src="../static/javascripts/zuul.angular.js"></script>
+  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
+  <title id='pagetitle'><%= htmlWebpackPlugin.options.title %></title>
 </head>
 <body ng-app="zuulBuilds" ng-controller="mainController"><div class="container-fluid">
   <nav class="navbar navbar-default">
diff --git a/zuul/web/static/jobs.html b/web/templates/jobs.ejs
similarity index 80%
rename from zuul/web/static/jobs.html
rename to web/templates/jobs.ejs
index b27d882..97f2bee 100644
--- a/zuul/web/static/jobs.html
+++ b/web/templates/jobs.ejs
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
 Copyright 2017 Red Hat
 
@@ -13,15 +14,10 @@
 License for the specific language governing permissions and limitations
 under the License.
 -->
-<!DOCTYPE html>
 <html>
 <head>
-    <title>Zuul Builds</title>
-    <link rel="stylesheet" href="../static/bootstrap/css/bootstrap.min.css">
-    <link rel="stylesheet" href="../static/styles/zuul.css" />
-    <script src="../static/js/jquery.min.js"></script>
-    <script src="../static/js/angular.min.js"></script>
-    <script src="../static/javascripts/zuul.angular.js"></script>
+  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
+  <title id='pagetitle'><%= htmlWebpackPlugin.options.title %></title>
 </head>
 <body ng-app="zuulJobs" ng-controller="mainController"><div class="container-fluid">
   <nav class="navbar navbar-default">
diff --git a/web/templates/status.ejs b/web/templates/status.ejs
new file mode 100644
index 0000000..230c074
--- /dev/null
+++ b/web/templates/status.ejs
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 Red Hat
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+-->
+<html>
+<head>
+  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
+  <title id='pagetitle'><%= htmlWebpackPlugin.options.title %></title>
+</head>
+<body ng-app="zuulStatus" ng-controller="mainController">
+  <nav class="navbar navbar-default">
+      <div class="container-fluid">
+          <div class="navbar-header">
+              <a class="navbar-brand" href="../" target="_self">Zuul Dashboard</a>
+          </div>
+          <ul class="nav navbar-nav">
+              <li class="active"><a href="status.html" target="_self">Status</a></li>
+              <li><a href="jobs.html" target="_self">Jobs</a></li>
+              <li><a href="builds.html" target="_self">Builds</a></li>
+          </ul>
+      </div>
+  </nav>
+   <div class="container">
+       <div class="zuul-container" id="zuul-container">
+           <div style="display: none;" class="alert" id="zuul_msg"></div>
+           <button class="btn pull-right zuul-spinner">
+               updating <span class="glyphicon glyphicon-refresh"></span>
+           </button>
+           <p>Queue lengths:
+           <span id="zuul_queue_events_num">0</span> events,
+           <span id="zuul_queue_management_events_num">0</span> management events,
+           <span id="zuul_queue_results_num">0</span> results.
+           </p>
+           <div id="zuul_controls"></div>
+           <div id="zuul_pipelines" class="row"></div>
+           <p>Zuul version: <span id="zuul-version-span"></span></p>
+           <p>Last reconfigured: <span id="last-reconfigured-span"></span></p>
+       </div>
+   </div>
+</body></html>
diff --git a/web/templates/stream.ejs b/web/templates/stream.ejs
new file mode 100644
index 0000000..b1ec38c
--- /dev/null
+++ b/web/templates/stream.ejs
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
+    <title id='pagetitle'><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body ng-app="zuulStream" ng-controller="mainController" id="zuulstream">
+    <div id="zuulstreamoverlay">
+      <form>
+        <input type="checkbox" id="autoscroll" checked> autoscroll
+      </form>
+    </div>
+
+    <pre id="zuulstreamcontent"></pre>
+  </div></body>
+</html>
diff --git a/zuul/web/static/index.html b/web/templates/tenants.ejs
similarity index 78%
rename from zuul/web/static/index.html
rename to web/templates/tenants.ejs
index d20a1ea..55ed076 100644
--- a/zuul/web/static/index.html
+++ b/web/templates/tenants.ejs
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
 Copyright 2017 Red Hat
 
@@ -13,15 +14,10 @@
 License for the specific language governing permissions and limitations
 under the License.
 -->
-<!DOCTYPE html>
 <html>
 <head>
-    <title>Zuul Tenants</title>
-    <link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css">
-    <link rel="stylesheet" href="static/styles/zuul.css" />
-    <script src="static/js/jquery.min.js"></script>
-    <script src="static/js/angular.min.js"></script>
-    <script src="static/javascripts/zuul.angular.js"></script>
+  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
+  <title id='pagetitle'><%= htmlWebpackPlugin.options.title %></title>
 </head>
 <body ng-app="zuulTenants" ng-controller="mainController"><div class="container-fluid">
   <nav class="navbar navbar-default">
@@ -30,7 +26,7 @@
       <a class="navbar-brand">Zuul Dashboard</a>
     </div>
     <ul class="nav navbar-nav">
-      <li class="active"><a href="tenants.html">Tenants</a></li>
+      <li class="active"><a href=".">Tenants</a></li>
     </ul>
   </div>
   </nav>
diff --git a/web/util.js b/web/util.js
new file mode 100644
index 0000000..32ea669
--- /dev/null
+++ b/web/util.js
@@ -0,0 +1,30 @@
+/* global ZUUL_API_URL */
+// @licstart  The following is the entire license notice for the
+// JavaScript code in this page.
+//
+// Copyright 2017 Red Hat
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+// @licend  The above is the entire license notice
+// for the JavaScript code in this page.
+
+// TODO(mordred) This should be encapsulated in an Angular Service singleton
+// that fetches the other things from the info endpoint.
+export function getSourceUrl (filename, $location) {
+  if (typeof ZUUL_API_URL !== 'undefined') {
+    return ZUUL_API_URL + '/' + filename
+  } else {
+    return filename
+  }
+}
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..27c3d58
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,3 @@
+module.exports = function(env) {
+  return require(`./web/config/webpack.${env}.js`)
+}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..2f92695
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,6019 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@7.0.0-beta.36":
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.36.tgz#2349d7ec04b3a06945ae173280ef8579b63728e4"
+  dependencies:
+    chalk "^2.0.0"
+    esutils "^2.0.2"
+    js-tokens "^3.0.0"
+
+"@babel/helper-function-name@7.0.0-beta.36":
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.36.tgz#366e3bc35147721b69009f803907c4d53212e88d"
+  dependencies:
+    "@babel/helper-get-function-arity" "7.0.0-beta.36"
+    "@babel/template" "7.0.0-beta.36"
+    "@babel/types" "7.0.0-beta.36"
+
+"@babel/helper-get-function-arity@7.0.0-beta.36":
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.36.tgz#f5383bac9a96b274828b10d98900e84ee43e32b8"
+  dependencies:
+    "@babel/types" "7.0.0-beta.36"
+
+"@babel/template@7.0.0-beta.36":
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.36.tgz#02e903de5d68bd7899bce3c5b5447e59529abb00"
+  dependencies:
+    "@babel/code-frame" "7.0.0-beta.36"
+    "@babel/types" "7.0.0-beta.36"
+    babylon "7.0.0-beta.36"
+    lodash "^4.2.0"
+
+"@babel/traverse@7.0.0-beta.36":
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.36.tgz#1dc6f8750e89b6b979de5fe44aa993b1a2192261"
+  dependencies:
+    "@babel/code-frame" "7.0.0-beta.36"
+    "@babel/helper-function-name" "7.0.0-beta.36"
+    "@babel/types" "7.0.0-beta.36"
+    babylon "7.0.0-beta.36"
+    debug "^3.0.1"
+    globals "^11.1.0"
+    invariant "^2.2.0"
+    lodash "^4.2.0"
+
+"@babel/types@7.0.0-beta.36":
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.36.tgz#64f2004353de42adb72f9ebb4665fc35b5499d23"
+  dependencies:
+    esutils "^2.0.2"
+    lodash "^4.2.0"
+    to-fast-properties "^2.0.0"
+
+abbrev@1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+
+accepts@~1.3.4:
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
+  dependencies:
+    mime-types "~2.1.16"
+    negotiator "0.6.1"
+
+acorn-dynamic-import@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
+  dependencies:
+    acorn "^4.0.3"
+
+acorn-jsx@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+  dependencies:
+    acorn "^3.0.4"
+
+acorn@^3.0.4:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
+acorn@^4.0.3:
+  version "4.0.13"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+
+acorn@^5.0.0, acorn@^5.3.0, acorn@^5.4.0:
+  version "5.4.1"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102"
+
+adjust-sourcemap-loader@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.1.0.tgz#412d92404eb61e4113635012cba53a33d008e0e2"
+  dependencies:
+    assert "^1.3.0"
+    camelcase "^1.2.1"
+    loader-utils "^1.0.2"
+    lodash.assign "^4.0.1"
+    lodash.defaults "^3.1.2"
+    object-path "^0.9.2"
+    regex-parser "^2.2.1"
+
+ajv-keywords@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
+
+ajv-keywords@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be"
+
+ajv@^4.9.1:
+  version "4.11.8"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+  dependencies:
+    co "^4.6.0"
+    json-stable-stringify "^1.0.1"
+
+ajv@^5.0.0, ajv@^5.2.3, ajv@^5.3.0:
+  version "5.5.2"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
+  dependencies:
+    co "^4.6.0"
+    fast-deep-equal "^1.0.0"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.3.0"
+
+ajv@^6.1.0:
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.1.1.tgz#978d597fbc2b7d0e5a5c3ddeb149a682f2abfa0e"
+  dependencies:
+    fast-deep-equal "^1.0.0"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.3.0"
+
+align-text@^0.1.1, align-text@^0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+  dependencies:
+    kind-of "^3.0.2"
+    longest "^1.0.1"
+    repeat-string "^1.5.2"
+
+alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
+
+amdefine@>=0.0.4:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+
+angular@^1.5.8:
+  version "1.6.9"
+  resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.9.tgz#bc812932e18909038412d594a5990f4bb66c0619"
+
+ansi-escapes@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
+
+ansi-html@0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
+
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-regex@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+ansi-styles@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
+  dependencies:
+    color-convert "^1.9.0"
+
+anymatch@^1.3.0:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
+  dependencies:
+    micromatch "^2.1.5"
+    normalize-path "^2.0.0"
+
+anymatch@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
+  dependencies:
+    micromatch "^3.1.4"
+    normalize-path "^2.1.1"
+
+aproba@^1.0.3:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+
+archiver-utils@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174"
+  dependencies:
+    glob "^7.0.0"
+    graceful-fs "^4.1.0"
+    lazystream "^1.0.0"
+    lodash "^4.8.0"
+    normalize-path "^2.0.0"
+    readable-stream "^2.0.0"
+
+archiver@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22"
+  dependencies:
+    archiver-utils "^1.3.0"
+    async "^2.0.0"
+    buffer-crc32 "^0.2.1"
+    glob "^7.0.0"
+    lodash "^4.8.0"
+    readable-stream "^2.0.0"
+    tar-stream "^1.5.0"
+    walkdir "^0.0.11"
+    zip-stream "^1.1.0"
+
+are-we-there-yet@~1.1.2:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
+  dependencies:
+    delegates "^1.0.0"
+    readable-stream "^2.0.6"
+
+argparse@^1.0.7:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+  dependencies:
+    sprintf-js "~1.0.2"
+
+arr-diff@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+  dependencies:
+    arr-flatten "^1.0.1"
+
+arr-diff@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
+
+arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+
+arr-union@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
+
+array-find-index@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+
+array-flatten@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+
+array-flatten@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.1.tgz#426bb9da84090c1838d812c8150af20a8331e296"
+
+array-includes@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d"
+  dependencies:
+    define-properties "^1.1.2"
+    es-abstract "^1.7.0"
+
+array-union@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+  dependencies:
+    array-uniq "^1.0.1"
+
+array-uniq@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+array-unique@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+
+array-unique@^0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
+
+arrify@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asn1.js@^4.0.0:
+  version "4.10.1"
+  resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
+  dependencies:
+    bn.js "^4.0.0"
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+
+asn1@~0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert-plus@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
+
+assert@^1.1.1, assert@^1.3.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+  dependencies:
+    util "0.10.3"
+
+assign-symbols@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
+
+async-each@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
+
+async-limiter@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
+
+async@^1.5.2:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@^2.0.0, async@^2.1.2:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
+  dependencies:
+    lodash "^4.14.0"
+
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+atob@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d"
+
+atob@~1.1.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773"
+
+autoprefixer@^6.3.1:
+  version "6.7.7"
+  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
+  dependencies:
+    browserslist "^1.7.6"
+    caniuse-db "^1.0.30000634"
+    normalize-range "^0.1.2"
+    num2fraction "^1.2.2"
+    postcss "^5.2.16"
+    postcss-value-parser "^3.2.3"
+
+aws-sign2@~0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
+
+aws4@^1.2.1:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
+
+babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+  dependencies:
+    chalk "^1.1.3"
+    esutils "^2.0.2"
+    js-tokens "^3.0.2"
+
+babel-core@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-generator "^6.26.0"
+    babel-helpers "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-register "^6.26.0"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    convert-source-map "^1.5.0"
+    debug "^2.6.8"
+    json5 "^0.5.1"
+    lodash "^4.17.4"
+    minimatch "^3.0.4"
+    path-is-absolute "^1.0.1"
+    private "^0.1.7"
+    slash "^1.0.0"
+    source-map "^0.5.6"
+
+babel-eslint@^8.0.3:
+  version "8.2.1"
+  resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.1.tgz#136888f3c109edc65376c23ebf494f36a3e03951"
+  dependencies:
+    "@babel/code-frame" "7.0.0-beta.36"
+    "@babel/traverse" "7.0.0-beta.36"
+    "@babel/types" "7.0.0-beta.36"
+    babylon "7.0.0-beta.36"
+    eslint-scope "~3.7.1"
+    eslint-visitor-keys "^1.0.0"
+
+babel-generator@^6.26.0:
+  version "6.26.1"
+  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
+  dependencies:
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    detect-indent "^4.0.0"
+    jsesc "^1.3.0"
+    lodash "^4.17.4"
+    source-map "^0.5.7"
+    trim-right "^1.0.1"
+
+babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
+  dependencies:
+    babel-helper-explode-assignable-expression "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-call-delegate@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
+  dependencies:
+    babel-helper-hoist-variables "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-define-map@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
+babel-helper-explode-assignable-expression@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-function-name@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
+  dependencies:
+    babel-helper-get-function-arity "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-get-function-arity@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-hoist-variables@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-optimise-call-expression@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-regex@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
+babel-helper-remap-async-to-generator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-replace-supers@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
+  dependencies:
+    babel-helper-optimise-call-expression "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helpers@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-loader@^7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.2.tgz#f6cbe122710f1aa2af4d881c6d5b54358ca24126"
+  dependencies:
+    find-cache-dir "^1.0.0"
+    loader-utils "^1.0.2"
+    mkdirp "^0.5.1"
+
+babel-messages@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-angularjs-annotate@^0.8.2:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-angularjs-annotate/-/babel-plugin-angularjs-annotate-0.8.2.tgz#7f9a37fbb7511668e836cb91a2e43e98e12f9ed9"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-types "^6.26.0"
+    simple-is "~0.2.0"
+
+babel-plugin-check-es2015-constants@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-syntax-async-functions@^6.8.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
+
+babel-plugin-syntax-exponentiation-operator@^6.8.0:
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
+
+babel-plugin-syntax-trailing-function-commas@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
+
+babel-plugin-transform-async-to-generator@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
+  dependencies:
+    babel-helper-remap-async-to-generator "^6.24.1"
+    babel-plugin-syntax-async-functions "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-arrow-functions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoping@^6.23.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
+babel-plugin-transform-es2015-classes@^6.23.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
+  dependencies:
+    babel-helper-define-map "^6.24.1"
+    babel-helper-function-name "^6.24.1"
+    babel-helper-optimise-call-expression "^6.24.1"
+    babel-helper-replace-supers "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-computed-properties@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-destructuring@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-duplicate-keys@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-for-of@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-function-name@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-literals@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
+  dependencies:
+    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
+  dependencies:
+    babel-plugin-transform-strict-mode "^6.24.1"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-types "^6.26.0"
+
+babel-plugin-transform-es2015-modules-systemjs@^6.23.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
+  dependencies:
+    babel-helper-hoist-variables "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-modules-umd@^6.23.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
+  dependencies:
+    babel-plugin-transform-es2015-modules-amd "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-object-super@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
+  dependencies:
+    babel-helper-replace-supers "^6.24.1"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-parameters@^6.23.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
+  dependencies:
+    babel-helper-call-delegate "^6.24.1"
+    babel-helper-get-function-arity "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-shorthand-properties@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-spread@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-sticky-regex@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
+  dependencies:
+    babel-helper-regex "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-template-literals@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-unicode-regex@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
+  dependencies:
+    babel-helper-regex "^6.24.1"
+    babel-runtime "^6.22.0"
+    regexpu-core "^2.0.0"
+
+babel-plugin-transform-exponentiation-operator@^6.22.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
+  dependencies:
+    babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
+    babel-plugin-syntax-exponentiation-operator "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-regenerator@^6.22.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
+  dependencies:
+    regenerator-transform "^0.10.0"
+
+babel-plugin-transform-strict-mode@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-preset-env@^1.6.1:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48"
+  dependencies:
+    babel-plugin-check-es2015-constants "^6.22.0"
+    babel-plugin-syntax-trailing-function-commas "^6.22.0"
+    babel-plugin-transform-async-to-generator "^6.22.0"
+    babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+    babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+    babel-plugin-transform-es2015-block-scoping "^6.23.0"
+    babel-plugin-transform-es2015-classes "^6.23.0"
+    babel-plugin-transform-es2015-computed-properties "^6.22.0"
+    babel-plugin-transform-es2015-destructuring "^6.23.0"
+    babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
+    babel-plugin-transform-es2015-for-of "^6.23.0"
+    babel-plugin-transform-es2015-function-name "^6.22.0"
+    babel-plugin-transform-es2015-literals "^6.22.0"
+    babel-plugin-transform-es2015-modules-amd "^6.22.0"
+    babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
+    babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
+    babel-plugin-transform-es2015-modules-umd "^6.23.0"
+    babel-plugin-transform-es2015-object-super "^6.22.0"
+    babel-plugin-transform-es2015-parameters "^6.23.0"
+    babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
+    babel-plugin-transform-es2015-spread "^6.22.0"
+    babel-plugin-transform-es2015-sticky-regex "^6.22.0"
+    babel-plugin-transform-es2015-template-literals "^6.22.0"
+    babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
+    babel-plugin-transform-es2015-unicode-regex "^6.22.0"
+    babel-plugin-transform-exponentiation-operator "^6.22.0"
+    babel-plugin-transform-regenerator "^6.22.0"
+    browserslist "^2.1.2"
+    invariant "^2.2.2"
+    semver "^5.3.0"
+
+babel-register@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
+  dependencies:
+    babel-core "^6.26.0"
+    babel-runtime "^6.26.0"
+    core-js "^2.5.0"
+    home-or-tmp "^2.0.0"
+    lodash "^4.17.4"
+    mkdirp "^0.5.1"
+    source-map-support "^0.4.15"
+
+babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
+babel-template@^6.24.1, babel-template@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    lodash "^4.17.4"
+
+babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    debug "^2.6.8"
+    globals "^9.18.0"
+    invariant "^2.2.2"
+    lodash "^4.17.4"
+
+babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+  dependencies:
+    babel-runtime "^6.26.0"
+    esutils "^2.0.2"
+    lodash "^4.17.4"
+    to-fast-properties "^1.0.3"
+
+babylon@7.0.0-beta.36:
+  version "7.0.0-beta.36"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.36.tgz#3a3683ba6a9a1e02b0aa507c8e63435e39305b9e"
+
+babylon@^6.18.0:
+  version "6.18.0"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+
+balanced-match@^0.4.2:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
+balanced-match@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
+base64-js@^1.0.2:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801"
+
+base@^0.11.1:
+  version "0.11.2"
+  resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
+  dependencies:
+    cache-base "^1.0.1"
+    class-utils "^0.3.5"
+    component-emitter "^1.2.1"
+    define-property "^1.0.0"
+    isobject "^3.0.1"
+    mixin-deep "^1.2.0"
+    pascalcase "^0.1.1"
+
+batch@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+
+bcrypt-pbkdf@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
+  dependencies:
+    tweetnacl "^0.14.3"
+
+bfj-node4@^5.2.0:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/bfj-node4/-/bfj-node4-5.2.1.tgz#3a6aa2730cf6911ba2afb836c2f88f015d718f3f"
+  dependencies:
+    bluebird "^3.5.1"
+    check-types "^7.3.0"
+    tryer "^1.0.0"
+
+big.js@^3.1.3:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
+
+binary-extensions@^1.0.0:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
+
+bl@^1.0.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
+  dependencies:
+    readable-stream "^2.0.5"
+
+block-stream@*:
+  version "0.0.9"
+  resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+  dependencies:
+    inherits "~2.0.0"
+
+bluebird@^3.4.7, bluebird@^3.5.1:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
+
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
+  version "4.11.8"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
+
+body-parser@1.18.2:
+  version "1.18.2"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
+  dependencies:
+    bytes "3.0.0"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "~1.1.1"
+    http-errors "~1.6.2"
+    iconv-lite "0.4.19"
+    on-finished "~2.3.0"
+    qs "6.5.1"
+    raw-body "2.3.2"
+    type-is "~1.6.15"
+
+bonjour@^3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
+  dependencies:
+    array-flatten "^2.1.0"
+    deep-equal "^1.0.1"
+    dns-equal "^1.0.0"
+    dns-txt "^2.0.2"
+    multicast-dns "^6.0.1"
+    multicast-dns-service-types "^1.1.0"
+
+boolbase@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
+boom@2.x.x:
+  version "2.10.1"
+  resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
+  dependencies:
+    hoek "2.x.x"
+
+bootstrap@^3.3.7:
+  version "3.3.7"
+  resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.3.7.tgz#5a389394549f23330875a3b150656574f8a9eb71"
+
+brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
+braces@^1.8.2:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+  dependencies:
+    expand-range "^1.8.1"
+    preserve "^0.2.0"
+    repeat-element "^1.1.2"
+
+braces@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e"
+  dependencies:
+    arr-flatten "^1.1.0"
+    array-unique "^0.3.2"
+    define-property "^1.0.0"
+    extend-shallow "^2.0.1"
+    fill-range "^4.0.0"
+    isobject "^3.0.1"
+    repeat-element "^1.1.2"
+    snapdragon "^0.8.1"
+    snapdragon-node "^2.0.1"
+    split-string "^3.0.2"
+    to-regex "^3.0.1"
+
+brorand@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+
+browserify-aes@^1.0.0, browserify-aes@^1.0.4:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f"
+  dependencies:
+    buffer-xor "^1.0.3"
+    cipher-base "^1.0.0"
+    create-hash "^1.1.0"
+    evp_bytestokey "^1.0.3"
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+browserify-cipher@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a"
+  dependencies:
+    browserify-aes "^1.0.4"
+    browserify-des "^1.0.0"
+    evp_bytestokey "^1.0.0"
+
+browserify-des@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd"
+  dependencies:
+    cipher-base "^1.0.1"
+    des.js "^1.0.0"
+    inherits "^2.0.1"
+
+browserify-rsa@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
+  dependencies:
+    bn.js "^4.1.0"
+    randombytes "^2.0.1"
+
+browserify-sign@^4.0.0:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298"
+  dependencies:
+    bn.js "^4.1.1"
+    browserify-rsa "^4.0.0"
+    create-hash "^1.1.0"
+    create-hmac "^1.1.2"
+    elliptic "^6.0.0"
+    inherits "^2.0.1"
+    parse-asn1 "^5.0.0"
+
+browserify-zlib@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
+  dependencies:
+    pako "~1.0.5"
+
+browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
+  version "1.7.7"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9"
+  dependencies:
+    caniuse-db "^1.0.30000639"
+    electron-to-chromium "^1.2.7"
+
+browserslist@^2.1.2:
+  version "2.11.3"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2"
+  dependencies:
+    caniuse-lite "^1.0.30000792"
+    electron-to-chromium "^1.3.30"
+
+buffer-crc32@^0.2.1:
+  version "0.2.13"
+  resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+
+buffer-indexof@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
+
+buffer-xor@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+
+buffer@^4.3.0:
+  version "4.9.1"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
+  dependencies:
+    base64-js "^1.0.2"
+    ieee754 "^1.1.4"
+    isarray "^1.0.0"
+
+builtin-modules@^1.0.0, builtin-modules@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+builtin-status-codes@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+
+bytes@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+
+cache-base@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
+  dependencies:
+    collection-visit "^1.0.0"
+    component-emitter "^1.2.1"
+    get-value "^2.0.6"
+    has-value "^1.0.0"
+    isobject "^3.0.1"
+    set-value "^2.0.0"
+    to-object-path "^0.3.0"
+    union-value "^1.0.0"
+    unset-value "^1.0.0"
+
+caller-path@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
+  dependencies:
+    callsites "^0.2.0"
+
+callsites@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
+
+camel-case@3.0.x:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
+  dependencies:
+    no-case "^2.2.0"
+    upper-case "^1.1.1"
+
+camelcase-keys@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+  dependencies:
+    camelcase "^2.0.0"
+    map-obj "^1.0.0"
+
+camelcase@^1.0.2, camelcase@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+
+camelcase@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+
+camelcase@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+
+camelcase@^4.0.0, camelcase@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+
+caniuse-api@^1.5.2:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
+  dependencies:
+    browserslist "^1.3.6"
+    caniuse-db "^1.0.30000529"
+    lodash.memoize "^4.1.2"
+    lodash.uniq "^4.5.0"
+
+caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
+  version "1.0.30000808"
+  resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000808.tgz#30dfd83009d5704f02dffb37725068ed12a366bb"
+
+caniuse-lite@^1.0.30000792:
+  version "1.0.30000808"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000808.tgz#7d759b5518529ea08b6705a19e70dbf401628ffc"
+
+caseless@~0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+
+center-align@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+  dependencies:
+    align-text "^0.1.3"
+    lazy-cache "^1.0.3"
+
+chalk@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
+chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
+  dependencies:
+    ansi-styles "^3.2.0"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.2.0"
+
+chardet@^0.4.0:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+
+check-types@^7.3.0:
+  version "7.3.0"
+  resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d"
+
+chokidar@^1.7.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
+  dependencies:
+    anymatch "^1.3.0"
+    async-each "^1.0.0"
+    glob-parent "^2.0.0"
+    inherits "^2.0.1"
+    is-binary-path "^1.0.0"
+    is-glob "^2.0.0"
+    path-is-absolute "^1.0.0"
+    readdirp "^2.0.0"
+  optionalDependencies:
+    fsevents "^1.0.0"
+
+chokidar@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7"
+  dependencies:
+    anymatch "^2.0.0"
+    async-each "^1.0.0"
+    braces "^2.3.0"
+    glob-parent "^3.1.0"
+    inherits "^2.0.1"
+    is-binary-path "^1.0.0"
+    is-glob "^4.0.0"
+    normalize-path "^2.1.1"
+    path-is-absolute "^1.0.0"
+    readdirp "^2.0.0"
+    upath "^1.0.0"
+  optionalDependencies:
+    fsevents "^1.0.0"
+
+cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+circular-json@^0.3.1:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
+
+clap@^1.0.9:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51"
+  dependencies:
+    chalk "^1.1.3"
+
+class-utils@^0.3.5:
+  version "0.3.6"
+  resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
+  dependencies:
+    arr-union "^3.1.0"
+    define-property "^0.2.5"
+    isobject "^3.0.0"
+    static-extend "^0.1.1"
+
+clean-css@4.1.x:
+  version "4.1.9"
+  resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.9.tgz#35cee8ae7687a49b98034f70de00c4edd3826301"
+  dependencies:
+    source-map "0.5.x"
+
+clean-webpack-plugin@^0.1.16:
+  version "0.1.18"
+  resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-0.1.18.tgz#2e2173897c76646031bff047c14b9c22c80d8c4a"
+  dependencies:
+    rimraf "^2.6.1"
+
+cli-cursor@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+  dependencies:
+    restore-cursor "^2.0.0"
+
+cli-width@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
+
+cliui@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+  dependencies:
+    center-align "^0.1.1"
+    right-align "^0.1.1"
+    wordwrap "0.0.2"
+
+cliui@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wrap-ansi "^2.0.0"
+
+clone@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f"
+
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+coa@~1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd"
+  dependencies:
+    q "^1.1.2"
+
+code-point-at@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+collection-visit@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
+  dependencies:
+    map-visit "^1.0.0"
+    object-visit "^1.0.0"
+
+color-convert@^1.3.0, color-convert@^1.9.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
+  dependencies:
+    color-name "^1.1.1"
+
+color-name@^1.0.0, color-name@^1.1.1:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+
+color-string@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991"
+  dependencies:
+    color-name "^1.0.0"
+
+color@^0.11.0:
+  version "0.11.4"
+  resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
+  dependencies:
+    clone "^1.0.2"
+    color-convert "^1.3.0"
+    color-string "^0.3.0"
+
+colormin@^1.0.5:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133"
+  dependencies:
+    color "^0.11.0"
+    css-color-names "0.0.4"
+    has "^1.0.1"
+
+colors@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
+
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
+  dependencies:
+    delayed-stream "~1.0.0"
+
+commander@2.14.x, commander@^2.13.0, commander@~2.14.1:
+  version "2.14.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
+
+commondir@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+
+component-emitter@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
+
+compress-commons@^1.2.0:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f"
+  dependencies:
+    buffer-crc32 "^0.2.1"
+    crc32-stream "^2.0.0"
+    normalize-path "^2.0.0"
+    readable-stream "^2.0.0"
+
+compressible@~2.0.11:
+  version "2.0.12"
+  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66"
+  dependencies:
+    mime-db ">= 1.30.0 < 2"
+
+compression@^1.5.2:
+  version "1.7.1"
+  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db"
+  dependencies:
+    accepts "~1.3.4"
+    bytes "3.0.0"
+    compressible "~2.0.11"
+    debug "2.6.9"
+    on-headers "~1.0.1"
+    safe-buffer "5.1.1"
+    vary "~1.1.2"
+
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+concat-stream@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
+  dependencies:
+    inherits "^2.0.3"
+    readable-stream "^2.2.2"
+    typedarray "^0.0.6"
+
+connect-history-api-fallback@^1.3.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a"
+
+console-browserify@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
+  dependencies:
+    date-now "^0.1.4"
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+
+constants-browserify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+
+contains-path@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
+
+content-disposition@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+
+content-type@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+
+convert-source-map@^0.3.3:
+  version "0.3.5"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
+
+convert-source-map@^1.1.1, convert-source-map@^1.5.0:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
+
+cookie-signature@1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+
+cookie@0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+
+copy-descriptor@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
+
+core-js@^2.4.0, core-js@^2.5.0:
+  version "2.5.3"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
+
+core-util-is@1.0.2, core-util-is@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+crc32-stream@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4"
+  dependencies:
+    crc "^3.4.4"
+    readable-stream "^2.0.0"
+
+crc@^3.4.4:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/crc/-/crc-3.5.0.tgz#98b8ba7d489665ba3979f59b21381374101a1964"
+
+create-ecdh@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
+  dependencies:
+    bn.js "^4.1.0"
+    elliptic "^6.0.0"
+
+create-hash@^1.1.0, create-hash@^1.1.2:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
+  dependencies:
+    cipher-base "^1.0.1"
+    inherits "^2.0.1"
+    ripemd160 "^2.0.0"
+    sha.js "^2.4.0"
+
+create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06"
+  dependencies:
+    cipher-base "^1.0.3"
+    create-hash "^1.1.0"
+    inherits "^2.0.1"
+    ripemd160 "^2.0.0"
+    safe-buffer "^5.0.1"
+    sha.js "^2.4.8"
+
+cross-spawn@^5.0.1, cross-spawn@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
+  dependencies:
+    lru-cache "^4.0.1"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
+cryptiles@2.x.x:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
+  dependencies:
+    boom "2.x.x"
+
+crypto-browserify@^3.11.0:
+  version "3.12.0"
+  resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
+  dependencies:
+    browserify-cipher "^1.0.0"
+    browserify-sign "^4.0.0"
+    create-ecdh "^4.0.0"
+    create-hash "^1.1.0"
+    create-hmac "^1.1.0"
+    diffie-hellman "^5.0.0"
+    inherits "^2.0.1"
+    pbkdf2 "^3.0.3"
+    public-encrypt "^4.0.0"
+    randombytes "^2.0.0"
+    randomfill "^1.0.3"
+
+css-color-names@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
+
+css-loader@^0.28.4:
+  version "0.28.9"
+  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.9.tgz#68064b85f4e271d7ce4c48a58300928e535d1c95"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    css-selector-tokenizer "^0.7.0"
+    cssnano "^3.10.0"
+    icss-utils "^2.1.0"
+    loader-utils "^1.0.2"
+    lodash.camelcase "^4.3.0"
+    object-assign "^4.1.1"
+    postcss "^5.0.6"
+    postcss-modules-extract-imports "^1.2.0"
+    postcss-modules-local-by-default "^1.2.0"
+    postcss-modules-scope "^1.1.0"
+    postcss-modules-values "^1.3.0"
+    postcss-value-parser "^3.3.0"
+    source-list-map "^2.0.0"
+
+css-select@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+  dependencies:
+    boolbase "~1.0.0"
+    css-what "2.1"
+    domutils "1.5.1"
+    nth-check "~1.0.1"
+
+css-selector-tokenizer@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86"
+  dependencies:
+    cssesc "^0.1.0"
+    fastparse "^1.1.1"
+    regexpu-core "^1.0.0"
+
+css-what@2.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
+
+css@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc"
+  dependencies:
+    inherits "^2.0.1"
+    source-map "^0.1.38"
+    source-map-resolve "^0.3.0"
+    urix "^0.1.0"
+
+cssesc@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
+
+cssnano@^3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
+  dependencies:
+    autoprefixer "^6.3.1"
+    decamelize "^1.1.2"
+    defined "^1.0.0"
+    has "^1.0.1"
+    object-assign "^4.0.1"
+    postcss "^5.0.14"
+    postcss-calc "^5.2.0"
+    postcss-colormin "^2.1.8"
+    postcss-convert-values "^2.3.4"
+    postcss-discard-comments "^2.0.4"
+    postcss-discard-duplicates "^2.0.1"
+    postcss-discard-empty "^2.0.1"
+    postcss-discard-overridden "^0.1.1"
+    postcss-discard-unused "^2.2.1"
+    postcss-filter-plugins "^2.0.0"
+    postcss-merge-idents "^2.1.5"
+    postcss-merge-longhand "^2.0.1"
+    postcss-merge-rules "^2.0.3"
+    postcss-minify-font-values "^1.0.2"
+    postcss-minify-gradients "^1.0.1"
+    postcss-minify-params "^1.0.4"
+    postcss-minify-selectors "^2.0.4"
+    postcss-normalize-charset "^1.1.0"
+    postcss-normalize-url "^3.0.7"
+    postcss-ordered-values "^2.1.0"
+    postcss-reduce-idents "^2.2.2"
+    postcss-reduce-initial "^1.0.0"
+    postcss-reduce-transforms "^1.0.3"
+    postcss-svgo "^2.1.1"
+    postcss-unique-selectors "^2.0.2"
+    postcss-value-parser "^3.2.3"
+    postcss-zindex "^2.0.1"
+
+csso@~2.3.1:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85"
+  dependencies:
+    clap "^1.0.9"
+    source-map "^0.5.3"
+
+currently-unhandled@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+  dependencies:
+    array-find-index "^1.0.1"
+
+d@1:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
+  dependencies:
+    es5-ext "^0.10.9"
+
+dashdash@^1.12.0:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+  dependencies:
+    assert-plus "^1.0.0"
+
+date-now@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
+
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  dependencies:
+    ms "2.0.0"
+
+debug@^3.0.1, debug@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  dependencies:
+    ms "2.0.0"
+
+decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+decode-uri-component@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+
+deep-equal@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
+
+deep-extend@~0.4.0:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
+
+deep-is@~0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+define-properties@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
+  dependencies:
+    foreach "^2.0.5"
+    object-keys "^1.0.8"
+
+define-property@^0.2.5:
+  version "0.2.5"
+  resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
+  dependencies:
+    is-descriptor "^0.1.0"
+
+define-property@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
+  dependencies:
+    is-descriptor "^1.0.0"
+
+defined@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
+
+del@^2.0.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+  dependencies:
+    globby "^5.0.0"
+    is-path-cwd "^1.0.0"
+    is-path-in-cwd "^1.0.0"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    rimraf "^2.2.8"
+
+del@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
+  dependencies:
+    globby "^6.1.0"
+    is-path-cwd "^1.0.0"
+    is-path-in-cwd "^1.0.0"
+    p-map "^1.1.1"
+    pify "^3.0.0"
+    rimraf "^2.2.8"
+
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+delegates@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+
+depd@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
+depd@~1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+
+des.js@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
+  dependencies:
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+
+destroy@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+
+detect-indent@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+  dependencies:
+    repeating "^2.0.0"
+
+detect-libc@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+
+detect-node@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
+
+diffie-hellman@^5.0.0:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
+  dependencies:
+    bn.js "^4.1.0"
+    miller-rabin "^4.0.0"
+    randombytes "^2.0.0"
+
+dns-equal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
+
+dns-packet@^1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a"
+  dependencies:
+    ip "^1.1.0"
+    safe-buffer "^5.0.1"
+
+dns-txt@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6"
+  dependencies:
+    buffer-indexof "^1.0.0"
+
+doctrine@1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
+  dependencies:
+    esutils "^2.0.2"
+    isarray "^1.0.0"
+
+doctrine@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+  dependencies:
+    esutils "^2.0.2"
+
+dom-converter@~0.1:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.1.4.tgz#a45ef5727b890c9bffe6d7c876e7b19cb0e17f3b"
+  dependencies:
+    utila "~0.3"
+
+dom-serializer@0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+  dependencies:
+    domelementtype "~1.1.1"
+    entities "~1.1.1"
+
+domain-browser@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
+
+domelementtype@1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+
+domelementtype@~1.1.1:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@2.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.1.0.tgz#d2646f5e57f6c3bab11cf6cb05d3c0acf7412594"
+  dependencies:
+    domelementtype "1"
+
+domutils@1.1:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485"
+  dependencies:
+    domelementtype "1"
+
+domutils@1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+  dependencies:
+    dom-serializer "0"
+    domelementtype "1"
+
+duplexer@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
+
+ecc-jsbn@~0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
+  dependencies:
+    jsbn "~0.1.0"
+
+ee-first@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+
+ejs@^2.5.7:
+  version "2.5.7"
+  resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
+
+electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30:
+  version "1.3.33"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.33.tgz#bf00703d62a7c65238136578c352d6c5c042a545"
+
+elliptic@^6.0.0:
+  version "6.4.0"
+  resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
+  dependencies:
+    bn.js "^4.4.0"
+    brorand "^1.0.1"
+    hash.js "^1.0.0"
+    hmac-drbg "^1.0.0"
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+    minimalistic-crypto-utils "^1.0.0"
+
+emojis-list@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+
+encodeurl@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+
+end-of-stream@^1.0.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
+  dependencies:
+    once "^1.4.0"
+
+enhanced-resolve@^3.4.0:
+  version "3.4.1"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e"
+  dependencies:
+    graceful-fs "^4.1.2"
+    memory-fs "^0.4.0"
+    object-assign "^4.0.1"
+    tapable "^0.2.7"
+
+entities@~1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+
+errno@^0.1.3:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
+  dependencies:
+    prr "~1.0.1"
+
+error-ex@^1.2.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
+  dependencies:
+    is-arrayish "^0.2.1"
+
+es-abstract@^1.7.0:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
+  dependencies:
+    es-to-primitive "^1.1.1"
+    function-bind "^1.1.1"
+    has "^1.0.1"
+    is-callable "^1.1.3"
+    is-regex "^1.0.4"
+
+es-to-primitive@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
+  dependencies:
+    is-callable "^1.1.1"
+    is-date-object "^1.0.1"
+    is-symbol "^1.0.1"
+
+es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
+  version "0.10.39"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.39.tgz#fca21b67559277ca4ac1a1ed7048b107b6f76d87"
+  dependencies:
+    es6-iterator "~2.0.3"
+    es6-symbol "~3.1.1"
+
+es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+  dependencies:
+    d "1"
+    es5-ext "^0.10.35"
+    es6-symbol "^3.1.1"
+
+es6-map@^0.1.3:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+    es6-iterator "~2.0.1"
+    es6-set "~0.1.5"
+    es6-symbol "~3.1.1"
+    event-emitter "~0.3.5"
+
+es6-set@~0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+    es6-iterator "~2.0.1"
+    es6-symbol "3.1.1"
+    event-emitter "~0.3.5"
+
+es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
+es6-weak-map@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
+  dependencies:
+    d "1"
+    es5-ext "^0.10.14"
+    es6-iterator "^2.0.1"
+    es6-symbol "^3.1.1"
+
+escape-html@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escope@^3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
+  dependencies:
+    es6-map "^0.1.3"
+    es6-weak-map "^2.0.1"
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-config-standard@^11.0.0-beta.0:
+  version "11.0.0-beta.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0-beta.0.tgz#f8afe69803d95c685a4b8392b8793188eb03cbb3"
+
+eslint-import-resolver-node@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
+  dependencies:
+    debug "^2.6.9"
+    resolve "^1.5.0"
+
+eslint-loader@^1.9.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-1.9.0.tgz#7e1be9feddca328d3dcfaef1ad49d5beffe83a13"
+  dependencies:
+    loader-fs-cache "^1.0.0"
+    loader-utils "^1.0.2"
+    object-assign "^4.0.1"
+    object-hash "^1.1.4"
+    rimraf "^2.6.1"
+
+eslint-module-utils@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
+  dependencies:
+    debug "^2.6.8"
+    pkg-dir "^1.0.0"
+
+eslint-plugin-import@^2.8.0:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894"
+  dependencies:
+    builtin-modules "^1.1.1"
+    contains-path "^0.1.0"
+    debug "^2.6.8"
+    doctrine "1.5.0"
+    eslint-import-resolver-node "^0.3.1"
+    eslint-module-utils "^2.1.1"
+    has "^1.0.1"
+    lodash.cond "^4.3.0"
+    minimatch "^3.0.3"
+    read-pkg-up "^2.0.0"
+
+eslint-plugin-node@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.0.tgz#5ad5ee6b5346aec6cc9cde0b8619caed2c6d8f25"
+  dependencies:
+    ignore "^3.3.6"
+    minimatch "^3.0.4"
+    resolve "^1.3.3"
+    semver "^5.4.1"
+
+eslint-plugin-promise@^3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75"
+
+eslint-plugin-standard@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2"
+
+eslint-scope@^3.7.1, eslint-scope@~3.7.1:
+  version "3.7.1"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
+  dependencies:
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-visitor-keys@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+
+eslint@>=3.19.0:
+  version "4.18.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.0.tgz#ebd0ba795af6dc59aa5cee17938160af5950e051"
+  dependencies:
+    ajv "^5.3.0"
+    babel-code-frame "^6.22.0"
+    chalk "^2.1.0"
+    concat-stream "^1.6.0"
+    cross-spawn "^5.1.0"
+    debug "^3.1.0"
+    doctrine "^2.1.0"
+    eslint-scope "^3.7.1"
+    eslint-visitor-keys "^1.0.0"
+    espree "^3.5.2"
+    esquery "^1.0.0"
+    esutils "^2.0.2"
+    file-entry-cache "^2.0.0"
+    functional-red-black-tree "^1.0.1"
+    glob "^7.1.2"
+    globals "^11.0.1"
+    ignore "^3.3.3"
+    imurmurhash "^0.1.4"
+    inquirer "^3.0.6"
+    is-resolvable "^1.0.0"
+    js-yaml "^3.9.1"
+    json-stable-stringify-without-jsonify "^1.0.1"
+    levn "^0.3.0"
+    lodash "^4.17.4"
+    minimatch "^3.0.2"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    path-is-inside "^1.0.2"
+    pluralize "^7.0.0"
+    progress "^2.0.0"
+    require-uncached "^1.0.3"
+    semver "^5.3.0"
+    strip-ansi "^4.0.0"
+    strip-json-comments "~2.0.1"
+    table "^4.0.1"
+    text-table "~0.2.0"
+
+espree@^3.5.2:
+  version "3.5.3"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.3.tgz#931e0af64e7fbbed26b050a29daad1fc64799fa6"
+  dependencies:
+    acorn "^5.4.0"
+    acorn-jsx "^3.0.0"
+
+esprima@^2.6.0:
+  version "2.7.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+
+esprima@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
+
+esquery@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+  dependencies:
+    estraverse "^4.0.0"
+
+esrecurse@^4.1.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
+  dependencies:
+    estraverse "^4.1.0"
+    object-assign "^4.0.1"
+
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
+esutils@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+etag@~1.8.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+
+event-emitter@~0.3.5:
+  version "0.3.5"
+  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
+eventemitter3@1.x.x:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
+
+events@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+
+eventsource@0.1.6:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-0.1.6.tgz#0acede849ed7dd1ccc32c811bb11b944d4f29232"
+  dependencies:
+    original ">=0.0.5"
+
+evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+  dependencies:
+    md5.js "^1.3.4"
+    safe-buffer "^5.1.1"
+
+execa@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
+  dependencies:
+    cross-spawn "^5.0.1"
+    get-stream "^3.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+expand-brackets@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+  dependencies:
+    is-posix-bracket "^0.1.0"
+
+expand-brackets@^2.1.4:
+  version "2.1.4"
+  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
+  dependencies:
+    debug "^2.3.3"
+    define-property "^0.2.5"
+    extend-shallow "^2.0.1"
+    posix-character-classes "^0.1.0"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+expand-range@^1.8.1:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+  dependencies:
+    fill-range "^2.1.0"
+
+express@^4.16.2:
+  version "4.16.2"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c"
+  dependencies:
+    accepts "~1.3.4"
+    array-flatten "1.1.1"
+    body-parser "1.18.2"
+    content-disposition "0.5.2"
+    content-type "~1.0.4"
+    cookie "0.3.1"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "~1.1.1"
+    encodeurl "~1.0.1"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "1.1.0"
+    fresh "0.5.2"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.2"
+    qs "6.5.1"
+    range-parser "~1.2.0"
+    safe-buffer "5.1.1"
+    send "0.16.1"
+    serve-static "1.13.1"
+    setprototypeof "1.1.0"
+    statuses "~1.3.1"
+    type-is "~1.6.15"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
+
+extend-shallow@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
+  dependencies:
+    is-extendable "^0.1.0"
+
+extend-shallow@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
+  dependencies:
+    assign-symbols "^1.0.0"
+    is-extendable "^1.0.1"
+
+extend@~3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+
+external-editor@^2.0.4:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48"
+  dependencies:
+    chardet "^0.4.0"
+    iconv-lite "^0.4.17"
+    tmp "^0.0.33"
+
+extglob@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+  dependencies:
+    is-extglob "^1.0.0"
+
+extglob@^2.0.2:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
+  dependencies:
+    array-unique "^0.3.2"
+    define-property "^1.0.0"
+    expand-brackets "^2.1.4"
+    extend-shallow "^2.0.1"
+    fragment-cache "^0.2.1"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+extsprintf@1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+
+extsprintf@^1.2.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
+
+fast-deep-equal@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
+
+fast-json-stable-stringify@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+
+fast-levenshtein@~2.0.4:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+fastparse@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
+
+faye-websocket@^0.10.0:
+  version "0.10.0"
+  resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
+  dependencies:
+    websocket-driver ">=0.5.1"
+
+faye-websocket@~0.11.0:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38"
+  dependencies:
+    websocket-driver ">=0.5.1"
+
+figures@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+  dependencies:
+    escape-string-regexp "^1.0.5"
+
+file-entry-cache@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
+  dependencies:
+    flat-cache "^1.2.1"
+    object-assign "^4.0.1"
+
+file-loader@^0.11.2:
+  version "0.11.2"
+  resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.11.2.tgz#4ff1df28af38719a6098093b88c82c71d1794a34"
+  dependencies:
+    loader-utils "^1.0.2"
+
+filename-regex@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
+
+filesize@^3.5.11:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa"
+
+fill-range@^2.1.0:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
+  dependencies:
+    is-number "^2.1.0"
+    isobject "^2.0.0"
+    randomatic "^1.1.3"
+    repeat-element "^1.1.2"
+    repeat-string "^1.5.2"
+
+fill-range@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
+  dependencies:
+    extend-shallow "^2.0.1"
+    is-number "^3.0.0"
+    repeat-string "^1.6.1"
+    to-regex-range "^2.1.0"
+
+finalhandler@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.1"
+    escape-html "~1.0.3"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    statuses "~1.3.1"
+    unpipe "~1.0.0"
+
+find-cache-dir@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9"
+  dependencies:
+    commondir "^1.0.1"
+    mkdirp "^0.5.1"
+    pkg-dir "^1.0.0"
+
+find-cache-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
+  dependencies:
+    commondir "^1.0.1"
+    make-dir "^1.0.0"
+    pkg-dir "^2.0.0"
+
+find-up@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  dependencies:
+    path-exists "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+find-up@^2.0.0, find-up@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+  dependencies:
+    locate-path "^2.0.0"
+
+flat-cache@^1.2.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
+  dependencies:
+    circular-json "^0.3.1"
+    del "^2.0.2"
+    graceful-fs "^4.1.2"
+    write "^0.2.1"
+
+flatten@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
+
+for-in@^1.0.1, for-in@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+
+for-own@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
+  dependencies:
+    for-in "^1.0.1"
+
+foreach@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
+
+forever-agent@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+form-data@~2.1.1:
+  version "2.1.4"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.5"
+    mime-types "^2.1.12"
+
+forwarded@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+
+fragment-cache@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
+  dependencies:
+    map-cache "^0.2.2"
+
+fresh@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+fsevents@^1.0.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8"
+  dependencies:
+    nan "^2.3.0"
+    node-pre-gyp "^0.6.39"
+
+fstream-ignore@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
+  dependencies:
+    fstream "^1.0.0"
+    inherits "2"
+    minimatch "^3.0.0"
+
+fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
+  dependencies:
+    graceful-fs "^4.1.2"
+    inherits "~2.0.0"
+    mkdirp ">=0.5 0"
+    rimraf "2"
+
+function-bind@^1.0.2, function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+
+functional-red-black-tree@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+
+gauge@~2.7.3:
+  version "2.7.4"
+  resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+  dependencies:
+    aproba "^1.0.3"
+    console-control-strings "^1.0.0"
+    has-unicode "^2.0.0"
+    object-assign "^4.1.0"
+    signal-exit "^3.0.0"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wide-align "^1.1.0"
+
+get-caller-file@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
+
+get-stdin@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+
+get-stream@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+
+get-value@^2.0.3, get-value@^2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
+
+getpass@^0.1.1:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+  dependencies:
+    assert-plus "^1.0.0"
+
+glob-base@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+  dependencies:
+    glob-parent "^2.0.0"
+    is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+  dependencies:
+    is-glob "^2.0.0"
+
+glob-parent@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
+  dependencies:
+    is-glob "^3.1.0"
+    path-dirname "^1.0.0"
+
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+globals@^11.0.1, globals@^11.1.0:
+  version "11.3.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0"
+
+globals@^9.18.0:
+  version "9.18.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+
+globby@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+  dependencies:
+    array-union "^1.0.1"
+    arrify "^1.0.0"
+    glob "^7.0.3"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+globby@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
+  dependencies:
+    array-union "^1.0.1"
+    glob "^7.0.3"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+graceful-fs@^4.1.0, graceful-fs@^4.1.2:
+  version "4.1.11"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+"graphitejs@https://github.com/prestontimmons/graphitejs/archive/master.tar.gz":
+  version "0.0.0"
+  resolved "https://github.com/prestontimmons/graphitejs/archive/master.tar.gz#f2dfd1dff1c2813a9e1ac6e99240d785dceab3c2"
+
+gzip-size@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-4.1.0.tgz#8ae096257eabe7d69c45be2b67c448124ffb517c"
+  dependencies:
+    duplexer "^0.1.1"
+    pify "^3.0.0"
+
+handle-thing@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
+
+har-schema@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
+  dependencies:
+    ajv "^4.9.1"
+    har-schema "^1.0.5"
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+has-flag@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
+
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+
+has-unicode@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+
+has-value@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
+  dependencies:
+    get-value "^2.0.3"
+    has-values "^0.1.4"
+    isobject "^2.0.0"
+
+has-value@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
+  dependencies:
+    get-value "^2.0.6"
+    has-values "^1.0.0"
+    isobject "^3.0.0"
+
+has-values@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
+
+has-values@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
+  dependencies:
+    is-number "^3.0.0"
+    kind-of "^4.0.0"
+
+has@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
+  dependencies:
+    function-bind "^1.0.2"
+
+hash-base@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
+  dependencies:
+    inherits "^2.0.1"
+
+hash-base@^3.0.0:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+hash.js@^1.0.0, hash.js@^1.0.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846"
+  dependencies:
+    inherits "^2.0.3"
+    minimalistic-assert "^1.0.0"
+
+hawk@3.1.3, hawk@~3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
+  dependencies:
+    boom "2.x.x"
+    cryptiles "2.x.x"
+    hoek "2.x.x"
+    sntp "1.x.x"
+
+he@1.1.x:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
+
+hmac-drbg@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+  dependencies:
+    hash.js "^1.0.3"
+    minimalistic-assert "^1.0.0"
+    minimalistic-crypto-utils "^1.0.1"
+
+hoek@2.x.x:
+  version "2.16.3"
+  resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+
+home-or-tmp@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
+  dependencies:
+    os-homedir "^1.0.0"
+    os-tmpdir "^1.0.1"
+
+hosted-git-info@^2.1.4:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
+
+hpack.js@^2.1.6:
+  version "2.1.6"
+  resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+  dependencies:
+    inherits "^2.0.1"
+    obuf "^1.0.0"
+    readable-stream "^2.0.1"
+    wbuf "^1.1.0"
+
+html-comment-regex@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
+
+html-entities@^1.2.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
+
+html-minifier@^3.2.3:
+  version "3.5.9"
+  resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.9.tgz#74424014b872598d4bb0e20ac420926ec61024b6"
+  dependencies:
+    camel-case "3.0.x"
+    clean-css "4.1.x"
+    commander "2.14.x"
+    he "1.1.x"
+    ncname "1.0.x"
+    param-case "2.1.x"
+    relateurl "0.2.x"
+    uglify-js "3.3.x"
+
+html-webpack-plugin@^2.29.0:
+  version "2.30.1"
+  resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz#7f9c421b7ea91ec460f56527d78df484ee7537d5"
+  dependencies:
+    bluebird "^3.4.7"
+    html-minifier "^3.2.3"
+    loader-utils "^0.2.16"
+    lodash "^4.17.3"
+    pretty-error "^2.0.2"
+    toposort "^1.0.0"
+
+htmlparser2@~3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe"
+  dependencies:
+    domelementtype "1"
+    domhandler "2.1"
+    domutils "1.1"
+    readable-stream "1.0"
+
+http-deceiver@^1.2.7:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+
+http-errors@1.6.2, http-errors@~1.6.2:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+  dependencies:
+    depd "1.1.1"
+    inherits "2.0.3"
+    setprototypeof "1.0.3"
+    statuses ">= 1.3.1 < 2"
+
+http-parser-js@>=0.4.0:
+  version "0.4.10"
+  resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
+
+http-proxy-middleware@~0.17.4:
+  version "0.17.4"
+  resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833"
+  dependencies:
+    http-proxy "^1.16.2"
+    is-glob "^3.1.0"
+    lodash "^4.17.2"
+    micromatch "^2.3.11"
+
+http-proxy@^1.16.2:
+  version "1.16.2"
+  resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742"
+  dependencies:
+    eventemitter3 "1.x.x"
+    requires-port "1.x.x"
+
+http-signature@~1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+  dependencies:
+    assert-plus "^0.2.0"
+    jsprim "^1.2.2"
+    sshpk "^1.7.0"
+
+https-browserify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
+
+iconv-lite@0.4.19, iconv-lite@^0.4.17:
+  version "0.4.19"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+
+icss-replace-symbols@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
+
+icss-utils@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962"
+  dependencies:
+    postcss "^6.0.1"
+
+ieee754@^1.1.4:
+  version "1.1.8"
+  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
+
+ignore@^3.3.3, ignore@^3.3.6:
+  version "3.3.7"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
+
+import-local@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
+  dependencies:
+    pkg-dir "^2.0.0"
+    resolve-cwd "^2.0.0"
+
+imurmurhash@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+
+indent-string@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+  dependencies:
+    repeating "^2.0.0"
+
+indexes-of@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
+
+indexof@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inherits@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+
+ini@~1.3.0:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+
+inquirer@^3.0.6:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
+  dependencies:
+    ansi-escapes "^3.0.0"
+    chalk "^2.0.0"
+    cli-cursor "^2.1.0"
+    cli-width "^2.0.0"
+    external-editor "^2.0.4"
+    figures "^2.0.0"
+    lodash "^4.3.0"
+    mute-stream "0.0.7"
+    run-async "^2.2.0"
+    rx-lite "^4.0.8"
+    rx-lite-aggregates "^4.0.8"
+    string-width "^2.1.0"
+    strip-ansi "^4.0.0"
+    through "^2.3.6"
+
+internal-ip@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-1.2.0.tgz#ae9fbf93b984878785d50a8de1b356956058cf5c"
+  dependencies:
+    meow "^3.3.0"
+
+interpret@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
+
+invariant@^2.2.0, invariant@^2.2.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+  dependencies:
+    loose-envify "^1.0.0"
+
+invert-kv@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+
+ip@^1.1.0, ip@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+
+ipaddr.js@1.5.2:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0"
+
+is-absolute-url@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
+
+is-accessor-descriptor@^0.1.6:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
+  dependencies:
+    kind-of "^3.0.2"
+
+is-accessor-descriptor@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
+  dependencies:
+    kind-of "^6.0.0"
+
+is-arrayish@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-binary-path@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+  dependencies:
+    binary-extensions "^1.0.0"
+
+is-buffer@^1.1.5:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+
+is-builtin-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+  dependencies:
+    builtin-modules "^1.0.0"
+
+is-callable@^1.1.1, is-callable@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
+
+is-data-descriptor@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
+  dependencies:
+    kind-of "^3.0.2"
+
+is-data-descriptor@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
+  dependencies:
+    kind-of "^6.0.0"
+
+is-date-object@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+
+is-descriptor@^0.1.0:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
+  dependencies:
+    is-accessor-descriptor "^0.1.6"
+    is-data-descriptor "^0.1.4"
+    kind-of "^5.0.0"
+
+is-descriptor@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
+  dependencies:
+    is-accessor-descriptor "^1.0.0"
+    is-data-descriptor "^1.0.0"
+    kind-of "^6.0.2"
+
+is-dotfile@^1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
+
+is-equal-shallow@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+  dependencies:
+    is-primitive "^2.0.0"
+
+is-extendable@^0.1.0, is-extendable@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+
+is-extendable@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
+  dependencies:
+    is-plain-object "^2.0.4"
+
+is-extglob@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+
+is-extglob@^2.1.0, is-extglob@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+
+is-finite@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+  dependencies:
+    is-extglob "^1.0.0"
+
+is-glob@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
+  dependencies:
+    is-extglob "^2.1.0"
+
+is-glob@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0"
+  dependencies:
+    is-extglob "^2.1.1"
+
+is-number@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+  dependencies:
+    kind-of "^3.0.2"
+
+is-number@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+  dependencies:
+    kind-of "^3.0.2"
+
+is-odd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088"
+  dependencies:
+    is-number "^3.0.0"
+
+is-path-cwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+
+is-path-in-cwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
+  dependencies:
+    is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+  dependencies:
+    path-is-inside "^1.0.1"
+
+is-plain-obj@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+
+is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+  dependencies:
+    isobject "^3.0.1"
+
+is-posix-bracket@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+
+is-primitive@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+
+is-promise@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
+is-regex@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+  dependencies:
+    has "^1.0.1"
+
+is-resolvable@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
+
+is-stream@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+is-svg@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9"
+  dependencies:
+    html-comment-regex "^1.1.0"
+
+is-symbol@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
+
+is-typedarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+is-wsl@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+
+isarray@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
+isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isexe@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+isobject@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+  dependencies:
+    isarray "1.0.0"
+
+isobject@^3.0.0, isobject@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+
+isstream@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+"jquery-visibility@https://github.com/mathiasbynens/jquery-visibility/archive/master.tar.gz":
+  version "1.0.12"
+  resolved "https://github.com/mathiasbynens/jquery-visibility/archive/master.tar.gz#c1d9800180fbdcf018488f70376ea818bfceaa41"
+  dependencies:
+    jquery "*"
+
+jquery@*:
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
+
+jquery@^1.11.1:
+  version "1.12.4"
+  resolved "https://registry.yarnpkg.com/jquery/-/jquery-1.12.4.tgz#01e1dfba290fe73deba77ceeacb0f9ba2fec9e0c"
+
+js-base64@^2.1.9:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582"
+
+js-tokens@^3.0.0, js-tokens@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-yaml@^3.9.1:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
+js-yaml@~3.7.0:
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^2.6.0"
+
+jsbn@~0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+
+jsesc@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+
+jsesc@~0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+
+json-loader@^0.5.4:
+  version "0.5.7"
+  resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
+
+json-schema-traverse@^0.3.0:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
+
+json-schema@0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify-without-jsonify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+
+json-stable-stringify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+  dependencies:
+    jsonify "~0.0.0"
+
+json-stringify-safe@~5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+json3@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
+
+json5@^0.5.0, json5@^0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+
+jsonify@~0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsprim@^1.2.2:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
+  dependencies:
+    assert-plus "1.0.0"
+    extsprintf "1.3.0"
+    json-schema "0.2.3"
+    verror "1.10.0"
+
+killable@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
+
+kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+  dependencies:
+    is-buffer "^1.1.5"
+
+kind-of@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+  dependencies:
+    is-buffer "^1.1.5"
+
+kind-of@^5.0.0, kind-of@^5.0.2:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
+
+kind-of@^6.0.0, kind-of@^6.0.2:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
+
+lazy-cache@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+
+lazy-cache@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264"
+  dependencies:
+    set-getter "^0.1.0"
+
+lazystream@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
+  dependencies:
+    readable-stream "^2.0.5"
+
+lcid@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+  dependencies:
+    invert-kv "^1.0.0"
+
+levn@^0.3.0, levn@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+  dependencies:
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+
+load-json-file@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    strip-bom "^2.0.0"
+
+load-json-file@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    strip-bom "^3.0.0"
+
+loader-fs-cache@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz#56e0bf08bd9708b26a765b68509840c8dec9fdbc"
+  dependencies:
+    find-cache-dir "^0.1.1"
+    mkdirp "0.5.1"
+
+loader-runner@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
+
+loader-utils@^0.2.16:
+  version "0.2.17"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
+loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+
+locate-path@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+  dependencies:
+    p-locate "^2.0.0"
+    path-exists "^3.0.0"
+
+lodash._baseassign@^3.0.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
+  dependencies:
+    lodash._basecopy "^3.0.0"
+    lodash.keys "^3.0.0"
+
+lodash._basecopy@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
+
+lodash._bindcallback@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
+
+lodash._createassigner@^3.0.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11"
+  dependencies:
+    lodash._bindcallback "^3.0.0"
+    lodash._isiterateecall "^3.0.0"
+    lodash.restparam "^3.0.0"
+
+lodash._getnative@^3.0.0:
+  version "3.9.1"
+  resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
+
+lodash._isiterateecall@^3.0.0:
+  version "3.0.9"
+  resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
+
+lodash.assign@^3.0.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa"
+  dependencies:
+    lodash._baseassign "^3.0.0"
+    lodash._createassigner "^3.0.0"
+    lodash.keys "^3.0.0"
+
+lodash.assign@^4.0.1:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
+
+lodash.camelcase@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+
+lodash.cond@^4.3.0:
+  version "4.5.2"
+  resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5"
+
+lodash.defaults@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c"
+  dependencies:
+    lodash.assign "^3.0.0"
+    lodash.restparam "^3.0.0"
+
+lodash.defaults@^4.0.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+
+lodash.endswith@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09"
+
+lodash.isarguments@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
+
+lodash.isarray@^3.0.0:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
+
+lodash.isfunction@^3.0.8:
+  version "3.0.9"
+  resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051"
+
+lodash.isstring@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+
+lodash.keys@^3.0.0:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
+  dependencies:
+    lodash._getnative "^3.0.0"
+    lodash.isarguments "^3.0.0"
+    lodash.isarray "^3.0.0"
+
+lodash.memoize@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+
+lodash.restparam@^3.0.0:
+  version "3.6.1"
+  resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
+
+lodash.startswith@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/lodash.startswith/-/lodash.startswith-4.2.1.tgz#c598c4adce188a27e53145731cdc6c0e7177600c"
+
+lodash.uniq@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+
+lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.0:
+  version "4.17.5"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
+
+loglevel@^1.4.1:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
+
+longest@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+
+loose-envify@^1.0.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
+  dependencies:
+    js-tokens "^3.0.0"
+
+loud-rejection@^1.0.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+  dependencies:
+    currently-unhandled "^0.4.1"
+    signal-exit "^3.0.0"
+
+lower-case@^1.1.1:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
+
+lru-cache@^4.0.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
+  dependencies:
+    pseudomap "^1.0.2"
+    yallist "^2.1.2"
+
+macaddress@^0.2.8:
+  version "0.2.8"
+  resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
+
+make-dir@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51"
+  dependencies:
+    pify "^3.0.0"
+
+map-cache@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+
+map-visit@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
+  dependencies:
+    object-visit "^1.0.0"
+
+math-expression-evaluator@^1.2.14:
+  version "1.2.17"
+  resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac"
+
+md5.js@^1.3.4:
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+
+media-typer@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+
+mem@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
+  dependencies:
+    mimic-fn "^1.0.0"
+
+memory-fs@^0.4.0, memory-fs@~0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+meow@^3.3.0:
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+  dependencies:
+    camelcase-keys "^2.0.0"
+    decamelize "^1.1.2"
+    loud-rejection "^1.0.0"
+    map-obj "^1.0.1"
+    minimist "^1.1.3"
+    normalize-package-data "^2.3.4"
+    object-assign "^4.0.1"
+    read-pkg-up "^1.0.1"
+    redent "^1.0.0"
+    trim-newlines "^1.0.0"
+
+merge-descriptors@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+
+methods@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+
+micromatch@^2.1.5, micromatch@^2.3.11:
+  version "2.3.11"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+  dependencies:
+    arr-diff "^2.0.0"
+    array-unique "^0.2.1"
+    braces "^1.8.2"
+    expand-brackets "^0.1.4"
+    extglob "^0.3.1"
+    filename-regex "^2.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.1"
+    kind-of "^3.0.2"
+    normalize-path "^2.0.1"
+    object.omit "^2.0.0"
+    parse-glob "^3.0.4"
+    regex-cache "^0.4.2"
+
+micromatch@^3.1.4:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.5.tgz#d05e168c206472dfbca985bfef4f57797b4cd4ba"
+  dependencies:
+    arr-diff "^4.0.0"
+    array-unique "^0.3.2"
+    braces "^2.3.0"
+    define-property "^1.0.0"
+    extend-shallow "^2.0.1"
+    extglob "^2.0.2"
+    fragment-cache "^0.2.1"
+    kind-of "^6.0.0"
+    nanomatch "^1.2.5"
+    object.pick "^1.3.0"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+miller-rabin@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
+  dependencies:
+    bn.js "^4.0.0"
+    brorand "^1.0.1"
+
+"mime-db@>= 1.30.0 < 2", mime-db@~1.33.0:
+  version "1.33.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
+
+mime-types@^2.1.12, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7:
+  version "2.1.18"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
+  dependencies:
+    mime-db "~1.33.0"
+
+mime@1.3.x:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0"
+
+mime@1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+
+mime@^1.5.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+
+mimic-fn@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+
+minimalistic-assert@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
+
+minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+
+minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  dependencies:
+    brace-expansion "^1.1.7"
+
+minimist@0.0.8:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^1.1.3, minimist@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+mixin-deep@^1.2.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
+  dependencies:
+    for-in "^1.0.2"
+    is-extendable "^1.0.1"
+
+mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  dependencies:
+    minimist "0.0.8"
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+multicast-dns-service-types@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
+
+multicast-dns@^6.0.1:
+  version "6.2.3"
+  resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229"
+  dependencies:
+    dns-packet "^1.3.1"
+    thunky "^1.0.2"
+
+mute-stream@0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+
+nan@^2.3.0:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a"
+
+nanomatch@^1.2.5:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.7.tgz#53cd4aa109ff68b7f869591fdc9d10daeeea3e79"
+  dependencies:
+    arr-diff "^4.0.0"
+    array-unique "^0.3.2"
+    define-property "^1.0.0"
+    extend-shallow "^2.0.1"
+    fragment-cache "^0.2.1"
+    is-odd "^1.0.0"
+    kind-of "^5.0.2"
+    object.pick "^1.3.0"
+    regex-not "^1.0.0"
+    snapdragon "^0.8.1"
+    to-regex "^3.0.1"
+
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
+ncname@1.0.x:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/ncname/-/ncname-1.0.0.tgz#5b57ad18b1ca092864ef62b0b1ed8194f383b71c"
+  dependencies:
+    xml-char-classes "^1.0.0"
+
+negotiator@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+
+no-case@^2.2.0:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
+  dependencies:
+    lower-case "^1.1.1"
+
+node-forge@0.7.1:
+  version "0.7.1"
+  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.1.tgz#9da611ea08982f4b94206b3beb4cc9665f20c300"
+
+node-libs-browser@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df"
+  dependencies:
+    assert "^1.1.1"
+    browserify-zlib "^0.2.0"
+    buffer "^4.3.0"
+    console-browserify "^1.1.0"
+    constants-browserify "^1.0.0"
+    crypto-browserify "^3.11.0"
+    domain-browser "^1.1.1"
+    events "^1.0.0"
+    https-browserify "^1.0.0"
+    os-browserify "^0.3.0"
+    path-browserify "0.0.0"
+    process "^0.11.10"
+    punycode "^1.2.4"
+    querystring-es3 "^0.2.0"
+    readable-stream "^2.3.3"
+    stream-browserify "^2.0.1"
+    stream-http "^2.7.2"
+    string_decoder "^1.0.0"
+    timers-browserify "^2.0.4"
+    tty-browserify "0.0.0"
+    url "^0.11.0"
+    util "^0.10.3"
+    vm-browserify "0.0.4"
+
+node-pre-gyp@^0.6.39:
+  version "0.6.39"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649"
+  dependencies:
+    detect-libc "^1.0.2"
+    hawk "3.1.3"
+    mkdirp "^0.5.1"
+    nopt "^4.0.1"
+    npmlog "^4.0.2"
+    rc "^1.1.7"
+    request "2.81.0"
+    rimraf "^2.6.1"
+    semver "^5.3.0"
+    tar "^2.2.1"
+    tar-pack "^3.4.0"
+
+nopt@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+  dependencies:
+    abbrev "1"
+    osenv "^0.1.4"
+
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+  dependencies:
+    hosted-git-info "^2.1.4"
+    is-builtin-module "^1.0.0"
+    semver "2 || 3 || 4 || 5"
+    validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+  dependencies:
+    remove-trailing-separator "^1.0.1"
+
+normalize-range@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+
+normalize-url@^1.4.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
+  dependencies:
+    object-assign "^4.0.1"
+    prepend-http "^1.0.0"
+    query-string "^4.1.0"
+    sort-keys "^1.0.0"
+
+npm-run-path@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+  dependencies:
+    path-key "^2.0.0"
+
+npmlog@^4.0.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+  dependencies:
+    are-we-there-yet "~1.1.2"
+    console-control-strings "~1.1.0"
+    gauge "~2.7.3"
+    set-blocking "~2.0.0"
+
+nth-check@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
+  dependencies:
+    boolbase "~1.0.0"
+
+num2fraction@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+oauth-sign@~0.8.1:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+
+object-copy@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
+  dependencies:
+    copy-descriptor "^0.1.0"
+    define-property "^0.2.5"
+    kind-of "^3.0.3"
+
+object-hash@^1.1.4:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.2.0.tgz#e96af0e96981996a1d47f88ead8f74f1ebc4422b"
+
+object-keys@^1.0.8:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
+
+object-path@^0.9.2:
+  version "0.9.2"
+  resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.9.2.tgz#0fd9a74fc5fad1ae3968b586bda5c632bd6c05a5"
+
+object-visit@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
+  dependencies:
+    isobject "^3.0.0"
+
+object.omit@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+  dependencies:
+    for-own "^0.1.4"
+    is-extendable "^0.1.1"
+
+object.pick@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
+  dependencies:
+    isobject "^3.0.1"
+
+obuf@^1.0.0, obuf@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e"
+
+on-finished@~2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+  dependencies:
+    ee-first "1.1.1"
+
+on-headers@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
+
+once@^1.3.0, once@^1.3.3, once@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  dependencies:
+    wrappy "1"
+
+onetime@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+  dependencies:
+    mimic-fn "^1.0.0"
+
+opener@^1.4.3:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
+
+opn@^5.1.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225"
+  dependencies:
+    is-wsl "^1.1.0"
+
+optionator@^0.8.2:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~2.0.4"
+    levn "~0.3.0"
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+    wordwrap "~1.0.0"
+
+original@>=0.0.5:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b"
+  dependencies:
+    url-parse "1.0.x"
+
+os-browserify@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
+
+os-homedir@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
+os-locale@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+  dependencies:
+    lcid "^1.0.0"
+
+os-locale@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
+  dependencies:
+    execa "^0.7.0"
+    lcid "^1.0.0"
+    mem "^1.1.0"
+
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+osenv@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+  dependencies:
+    os-homedir "^1.0.0"
+    os-tmpdir "^1.0.0"
+
+p-finally@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+
+p-limit@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
+  dependencies:
+    p-try "^1.0.0"
+
+p-locate@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+  dependencies:
+    p-limit "^1.1.0"
+
+p-map@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
+
+p-try@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+
+pako@~1.0.5:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
+
+param-case@2.1.x:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
+  dependencies:
+    no-case "^2.2.0"
+
+parse-asn1@^5.0.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
+  dependencies:
+    asn1.js "^4.0.0"
+    browserify-aes "^1.0.0"
+    create-hash "^1.1.0"
+    evp_bytestokey "^1.0.0"
+    pbkdf2 "^3.0.3"
+
+parse-glob@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+  dependencies:
+    glob-base "^0.3.0"
+    is-dotfile "^1.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.0"
+
+parse-json@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  dependencies:
+    error-ex "^1.2.0"
+
+parseurl@~1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+
+pascalcase@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
+
+path-browserify@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
+
+path-dirname@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
+
+path-exists@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  dependencies:
+    pinkie-promise "^2.0.0"
+
+path-exists@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+
+path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-is-inside@^1.0.1, path-is-inside@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+
+path-key@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+
+path-parse@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+
+path-to-regexp@0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+
+path-type@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  dependencies:
+    graceful-fs "^4.1.2"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+path-type@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
+  dependencies:
+    pify "^2.0.0"
+
+pbkdf2@^3.0.3:
+  version "3.0.14"
+  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
+  dependencies:
+    create-hash "^1.1.2"
+    create-hmac "^1.1.4"
+    ripemd160 "^2.0.1"
+    safe-buffer "^5.0.1"
+    sha.js "^2.4.8"
+
+performance-now@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
+pify@^2.0.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pify@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+pkg-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
+  dependencies:
+    find-up "^1.0.0"
+
+pkg-dir@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
+  dependencies:
+    find-up "^2.1.0"
+
+pluralize@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
+
+portfinder@^1.0.9:
+  version "1.0.13"
+  resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
+  dependencies:
+    async "^1.5.2"
+    debug "^2.2.0"
+    mkdirp "0.5.x"
+
+posix-character-classes@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
+
+postcss-calc@^5.2.0:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e"
+  dependencies:
+    postcss "^5.0.2"
+    postcss-message-helpers "^2.0.0"
+    reduce-css-calc "^1.2.6"
+
+postcss-colormin@^2.1.8:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b"
+  dependencies:
+    colormin "^1.0.5"
+    postcss "^5.0.13"
+    postcss-value-parser "^3.2.3"
+
+postcss-convert-values@^2.3.4:
+  version "2.6.1"
+  resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d"
+  dependencies:
+    postcss "^5.0.11"
+    postcss-value-parser "^3.1.2"
+
+postcss-discard-comments@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d"
+  dependencies:
+    postcss "^5.0.14"
+
+postcss-discard-duplicates@^2.0.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-discard-empty@^2.0.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5"
+  dependencies:
+    postcss "^5.0.14"
+
+postcss-discard-overridden@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58"
+  dependencies:
+    postcss "^5.0.16"
+
+postcss-discard-unused@^2.2.1:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433"
+  dependencies:
+    postcss "^5.0.14"
+    uniqs "^2.0.0"
+
+postcss-filter-plugins@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c"
+  dependencies:
+    postcss "^5.0.4"
+    uniqid "^4.0.0"
+
+postcss-merge-idents@^2.1.5:
+  version "2.1.7"
+  resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270"
+  dependencies:
+    has "^1.0.1"
+    postcss "^5.0.10"
+    postcss-value-parser "^3.1.1"
+
+postcss-merge-longhand@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-merge-rules@^2.0.3:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721"
+  dependencies:
+    browserslist "^1.5.2"
+    caniuse-api "^1.5.2"
+    postcss "^5.0.4"
+    postcss-selector-parser "^2.2.2"
+    vendors "^1.0.0"
+
+postcss-message-helpers@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e"
+
+postcss-minify-font-values@^1.0.2:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69"
+  dependencies:
+    object-assign "^4.0.1"
+    postcss "^5.0.4"
+    postcss-value-parser "^3.0.2"
+
+postcss-minify-gradients@^1.0.1:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1"
+  dependencies:
+    postcss "^5.0.12"
+    postcss-value-parser "^3.3.0"
+
+postcss-minify-params@^1.0.4:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3"
+  dependencies:
+    alphanum-sort "^1.0.1"
+    postcss "^5.0.2"
+    postcss-value-parser "^3.0.2"
+    uniqs "^2.0.0"
+
+postcss-minify-selectors@^2.0.4:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf"
+  dependencies:
+    alphanum-sort "^1.0.2"
+    has "^1.0.1"
+    postcss "^5.0.14"
+    postcss-selector-parser "^2.0.0"
+
+postcss-modules-extract-imports@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85"
+  dependencies:
+    postcss "^6.0.1"
+
+postcss-modules-local-by-default@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
+  dependencies:
+    css-selector-tokenizer "^0.7.0"
+    postcss "^6.0.1"
+
+postcss-modules-scope@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
+  dependencies:
+    css-selector-tokenizer "^0.7.0"
+    postcss "^6.0.1"
+
+postcss-modules-values@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
+  dependencies:
+    icss-replace-symbols "^1.1.0"
+    postcss "^6.0.1"
+
+postcss-normalize-charset@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1"
+  dependencies:
+    postcss "^5.0.5"
+
+postcss-normalize-url@^3.0.7:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222"
+  dependencies:
+    is-absolute-url "^2.0.0"
+    normalize-url "^1.4.0"
+    postcss "^5.0.14"
+    postcss-value-parser "^3.2.3"
+
+postcss-ordered-values@^2.1.0:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d"
+  dependencies:
+    postcss "^5.0.4"
+    postcss-value-parser "^3.0.1"
+
+postcss-reduce-idents@^2.2.2:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3"
+  dependencies:
+    postcss "^5.0.4"
+    postcss-value-parser "^3.0.2"
+
+postcss-reduce-initial@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-reduce-transforms@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1"
+  dependencies:
+    has "^1.0.1"
+    postcss "^5.0.8"
+    postcss-value-parser "^3.0.1"
+
+postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90"
+  dependencies:
+    flatten "^1.0.2"
+    indexes-of "^1.0.1"
+    uniq "^1.0.1"
+
+postcss-svgo@^2.1.1:
+  version "2.1.6"
+  resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d"
+  dependencies:
+    is-svg "^2.0.0"
+    postcss "^5.0.14"
+    postcss-value-parser "^3.2.3"
+    svgo "^0.7.0"
+
+postcss-unique-selectors@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d"
+  dependencies:
+    alphanum-sort "^1.0.1"
+    postcss "^5.0.4"
+    uniqs "^2.0.0"
+
+postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
+
+postcss-zindex@^2.0.1:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22"
+  dependencies:
+    has "^1.0.1"
+    postcss "^5.0.4"
+    uniqs "^2.0.0"
+
+postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16:
+  version "5.2.18"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
+  dependencies:
+    chalk "^1.1.3"
+    js-base64 "^2.1.9"
+    source-map "^0.5.6"
+    supports-color "^3.2.3"
+
+postcss@^6.0.1:
+  version "6.0.18"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.18.tgz#370f5f44d47f3a205f0eb2f6262bbf202df2a80e"
+  dependencies:
+    chalk "^2.3.1"
+    source-map "^0.6.1"
+    supports-color "^5.2.0"
+
+prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+prepend-http@^1.0.0:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
+
+preserve@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+
+pretty-error@^2.0.2:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"
+  dependencies:
+    renderkid "^2.0.1"
+    utila "~0.4"
+
+private@^0.1.6, private@^0.1.7:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
+
+process-nextick-args@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+
+process@^0.11.10:
+  version "0.11.10"
+  resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+
+progress@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
+
+proxy-addr@~2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
+  dependencies:
+    forwarded "~0.1.2"
+    ipaddr.js "1.5.2"
+
+prr@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+
+pseudomap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+
+public-encrypt@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6"
+  dependencies:
+    bn.js "^4.1.0"
+    browserify-rsa "^4.0.0"
+    create-hash "^1.1.0"
+    parse-asn1 "^5.0.0"
+    randombytes "^2.0.1"
+
+punycode@1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+
+punycode@^1.2.4, punycode@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+q@^1.1.2:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+
+qs@6.5.1:
+  version "6.5.1"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+
+qs@~6.4.0:
+  version "6.4.0"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+
+query-string@^4.1.0:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
+  dependencies:
+    object-assign "^4.1.0"
+    strict-uri-encode "^1.0.0"
+
+querystring-es3@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+
+querystring@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+
+querystringify@0.0.x:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c"
+
+querystringify@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb"
+
+randomatic@^1.1.3:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
+  dependencies:
+    is-number "^3.0.0"
+    kind-of "^4.0.0"
+
+randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80"
+  dependencies:
+    safe-buffer "^5.1.0"
+
+randomfill@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
+  dependencies:
+    randombytes "^2.0.5"
+    safe-buffer "^5.1.0"
+
+range-parser@^1.0.3, range-parser@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+
+raw-body@2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
+  dependencies:
+    bytes "3.0.0"
+    http-errors "1.6.2"
+    iconv-lite "0.4.19"
+    unpipe "1.0.0"
+
+rc@^1.1.7:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd"
+  dependencies:
+    deep-extend "~0.4.0"
+    ini "~1.3.0"
+    minimist "^1.2.0"
+    strip-json-comments "~2.0.1"
+
+read-pkg-up@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  dependencies:
+    find-up "^1.0.0"
+    read-pkg "^1.0.0"
+
+read-pkg-up@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
+  dependencies:
+    find-up "^2.0.0"
+    read-pkg "^2.0.0"
+
+read-pkg@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  dependencies:
+    load-json-file "^1.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^1.0.0"
+
+read-pkg@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
+  dependencies:
+    load-json-file "^2.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^2.0.0"
+
+readable-stream@1.0:
+  version "1.0.34"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "0.0.1"
+    string_decoder "~0.10.x"
+
+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.3:
+  version "2.3.4"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.0.3"
+    util-deprecate "~1.0.1"
+
+readdirp@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
+  dependencies:
+    graceful-fs "^4.1.2"
+    minimatch "^3.0.2"
+    readable-stream "^2.0.2"
+    set-immediate-shim "^1.0.1"
+
+redent@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+  dependencies:
+    indent-string "^2.1.0"
+    strip-indent "^1.0.1"
+
+reduce-css-calc@^1.2.6:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
+  dependencies:
+    balanced-match "^0.4.2"
+    math-expression-evaluator "^1.2.14"
+    reduce-function-call "^1.0.1"
+
+reduce-function-call@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99"
+  dependencies:
+    balanced-match "^0.4.2"
+
+regenerate@^1.2.1:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f"
+
+regenerator-runtime@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+
+regenerator-transform@^0.10.0:
+  version "0.10.1"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
+  dependencies:
+    babel-runtime "^6.18.0"
+    babel-types "^6.19.0"
+    private "^0.1.6"
+
+regex-cache@^0.4.2:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
+  dependencies:
+    is-equal-shallow "^0.1.3"
+
+regex-not@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9"
+  dependencies:
+    extend-shallow "^2.0.1"
+
+regex-parser@^2.2.1:
+  version "2.2.9"
+  resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.9.tgz#a372f45a248b62976a568037c1b6e60a60599192"
+
+regexpu-core@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
+  dependencies:
+    regenerate "^1.2.1"
+    regjsgen "^0.2.0"
+    regjsparser "^0.1.4"
+
+regexpu-core@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
+  dependencies:
+    regenerate "^1.2.1"
+    regjsgen "^0.2.0"
+    regjsparser "^0.1.4"
+
+regjsgen@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
+
+regjsparser@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
+  dependencies:
+    jsesc "~0.5.0"
+
+relateurl@0.2.x:
+  version "0.2.7"
+  resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
+
+remove-trailing-separator@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+
+renderkid@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.1.tgz#898cabfc8bede4b7b91135a3ffd323e58c0db319"
+  dependencies:
+    css-select "^1.1.0"
+    dom-converter "~0.1"
+    htmlparser2 "~3.3.0"
+    strip-ansi "^3.0.0"
+    utila "~0.3"
+
+repeat-element@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
+
+repeat-string@^1.5.2, repeat-string@^1.6.1:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+
+repeating@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+  dependencies:
+    is-finite "^1.0.0"
+
+request@2.81.0:
+  version "2.81.0"
+  resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
+  dependencies:
+    aws-sign2 "~0.6.0"
+    aws4 "^1.2.1"
+    caseless "~0.12.0"
+    combined-stream "~1.0.5"
+    extend "~3.0.0"
+    forever-agent "~0.6.1"
+    form-data "~2.1.1"
+    har-validator "~4.2.1"
+    hawk "~3.1.3"
+    http-signature "~1.1.0"
+    is-typedarray "~1.0.0"
+    isstream "~0.1.2"
+    json-stringify-safe "~5.0.1"
+    mime-types "~2.1.7"
+    oauth-sign "~0.8.1"
+    performance-now "^0.2.0"
+    qs "~6.4.0"
+    safe-buffer "^5.0.1"
+    stringstream "~0.0.4"
+    tough-cookie "~2.3.0"
+    tunnel-agent "^0.6.0"
+    uuid "^3.0.0"
+
+require-directory@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+
+require-main-filename@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+
+require-uncached@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
+  dependencies:
+    caller-path "^0.1.0"
+    resolve-from "^1.0.0"
+
+requires-port@1.0.x, requires-port@1.x.x, requires-port@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+
+resolve-cwd@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
+  dependencies:
+    resolve-from "^3.0.0"
+
+resolve-from@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+
+resolve-from@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
+
+resolve-url-loader@^2.1.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.2.1.tgz#13a1396fb773edf959550e400e688f5ed32548bf"
+  dependencies:
+    adjust-sourcemap-loader "^1.1.0"
+    camelcase "^4.0.0"
+    convert-source-map "^1.1.1"
+    loader-utils "^1.0.0"
+    lodash.defaults "^4.0.0"
+    rework "^1.0.1"
+    rework-visit "^1.0.0"
+    source-map "^0.5.6"
+    urix "^0.1.0"
+
+resolve-url@^0.2.1, resolve-url@~0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+
+resolve@^1.3.3, resolve@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
+  dependencies:
+    path-parse "^1.0.5"
+
+restore-cursor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+  dependencies:
+    onetime "^2.0.0"
+    signal-exit "^3.0.2"
+
+rework-visit@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a"
+
+rework@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/rework/-/rework-1.0.1.tgz#30806a841342b54510aa4110850cd48534144aa7"
+  dependencies:
+    convert-source-map "^0.3.3"
+    css "^2.0.0"
+
+right-align@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+  dependencies:
+    align-text "^0.1.1"
+
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+  dependencies:
+    glob "^7.0.5"
+
+ripemd160@^2.0.0, ripemd160@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
+  dependencies:
+    hash-base "^2.0.0"
+    inherits "^2.0.1"
+
+run-async@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+  dependencies:
+    is-promise "^2.1.0"
+
+rx-lite-aggregates@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
+  dependencies:
+    rx-lite "*"
+
+rx-lite@*, rx-lite@^4.0.8:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
+
+safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
+sax@~1.2.1:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+
+schema-utils@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
+  dependencies:
+    ajv "^5.0.0"
+
+select-hose@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+
+selfsigned@^1.9.1:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.2.tgz#b4449580d99929b65b10a48389301a6592088758"
+  dependencies:
+    node-forge "0.7.1"
+
+"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
+
+send@0.16.1:
+  version "0.16.1"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3"
+  dependencies:
+    debug "2.6.9"
+    depd "~1.1.1"
+    destroy "~1.0.4"
+    encodeurl "~1.0.1"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    fresh "0.5.2"
+    http-errors "~1.6.2"
+    mime "1.4.1"
+    ms "2.0.0"
+    on-finished "~2.3.0"
+    range-parser "~1.2.0"
+    statuses "~1.3.1"
+
+serve-index@^1.7.2:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+  dependencies:
+    accepts "~1.3.4"
+    batch "0.6.1"
+    debug "2.6.9"
+    escape-html "~1.0.3"
+    http-errors "~1.6.2"
+    mime-types "~2.1.17"
+    parseurl "~1.3.2"
+
+serve-static@1.13.1:
+  version "1.13.1"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719"
+  dependencies:
+    encodeurl "~1.0.1"
+    escape-html "~1.0.3"
+    parseurl "~1.3.2"
+    send "0.16.1"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+
+set-getter@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376"
+  dependencies:
+    to-object-path "^0.3.0"
+
+set-immediate-shim@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+
+set-value@^0.4.3:
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1"
+  dependencies:
+    extend-shallow "^2.0.1"
+    is-extendable "^0.1.1"
+    is-plain-object "^2.0.1"
+    to-object-path "^0.3.0"
+
+set-value@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274"
+  dependencies:
+    extend-shallow "^2.0.1"
+    is-extendable "^0.1.1"
+    is-plain-object "^2.0.3"
+    split-string "^3.0.1"
+
+setimmediate@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+
+setprototypeof@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+
+setprototypeof@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+
+sha.js@^2.4.0, sha.js@^2.4.8:
+  version "2.4.10"
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b"
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+shebang-command@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+  dependencies:
+    shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+
+signal-exit@^3.0.0, signal-exit@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+
+simple-is@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/simple-is/-/simple-is-0.2.0.tgz#2abb75aade39deb5cc815ce10e6191164850baf0"
+
+slash@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+
+slice-ansi@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+
+snapdragon-node@^2.0.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
+  dependencies:
+    define-property "^1.0.0"
+    isobject "^3.0.0"
+    snapdragon-util "^3.0.1"
+
+snapdragon-util@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
+  dependencies:
+    kind-of "^3.2.0"
+
+snapdragon@^0.8.1:
+  version "0.8.1"
+  resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370"
+  dependencies:
+    base "^0.11.1"
+    debug "^2.2.0"
+    define-property "^0.2.5"
+    extend-shallow "^2.0.1"
+    map-cache "^0.2.2"
+    source-map "^0.5.6"
+    source-map-resolve "^0.5.0"
+    use "^2.0.0"
+
+sntp@1.x.x:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
+  dependencies:
+    hoek "2.x.x"
+
+sockjs-client@1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.4.tgz#5babe386b775e4cf14e7520911452654016c8b12"
+  dependencies:
+    debug "^2.6.6"
+    eventsource "0.1.6"
+    faye-websocket "~0.11.0"
+    inherits "^2.0.1"
+    json3 "^3.3.2"
+    url-parse "^1.1.8"
+
+sockjs@0.3.19:
+  version "0.3.19"
+  resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d"
+  dependencies:
+    faye-websocket "^0.10.0"
+    uuid "^3.0.1"
+
+sort-keys@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
+  dependencies:
+    is-plain-obj "^1.0.0"
+
+source-list-map@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
+
+source-map-resolve@^0.3.0:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761"
+  dependencies:
+    atob "~1.1.0"
+    resolve-url "~0.2.1"
+    source-map-url "~0.3.0"
+    urix "~0.1.0"
+
+source-map-resolve@^0.5.0:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a"
+  dependencies:
+    atob "^2.0.0"
+    decode-uri-component "^0.2.0"
+    resolve-url "^0.2.1"
+    source-map-url "^0.4.0"
+    urix "^0.1.0"
+
+source-map-support@^0.4.15:
+  version "0.4.18"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+  dependencies:
+    source-map "^0.5.6"
+
+source-map-url@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
+
+source-map-url@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9"
+
+source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1:
+  version "0.5.7"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+
+source-map@^0.1.38:
+  version "0.1.43"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
+  dependencies:
+    amdefine ">=0.0.4"
+
+source-map@^0.6.1, source-map@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+
+spdx-correct@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+  dependencies:
+    spdx-license-ids "^1.0.2"
+
+spdx-expression-parse@~1.0.0:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+
+spdx-license-ids@^1.0.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+
+spdy-transport@^2.0.18:
+  version "2.0.20"
+  resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
+  dependencies:
+    debug "^2.6.8"
+    detect-node "^2.0.3"
+    hpack.js "^2.1.6"
+    obuf "^1.1.1"
+    readable-stream "^2.2.9"
+    safe-buffer "^5.0.1"
+    wbuf "^1.7.2"
+
+spdy@^3.4.1:
+  version "3.4.7"
+  resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
+  dependencies:
+    debug "^2.6.8"
+    handle-thing "^1.2.5"
+    http-deceiver "^1.2.7"
+    safe-buffer "^5.0.1"
+    select-hose "^2.0.0"
+    spdy-transport "^2.0.18"
+
+split-string@^3.0.1, split-string@^3.0.2:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
+  dependencies:
+    extend-shallow "^3.0.0"
+
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+sshpk@^1.7.0:
+  version "1.13.1"
+  resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
+  dependencies:
+    asn1 "~0.2.3"
+    assert-plus "^1.0.0"
+    dashdash "^1.12.0"
+    getpass "^0.1.1"
+  optionalDependencies:
+    bcrypt-pbkdf "^1.0.0"
+    ecc-jsbn "~0.1.1"
+    jsbn "~0.1.0"
+    tweetnacl "~0.14.0"
+
+static-extend@^0.1.1:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
+  dependencies:
+    define-property "^0.2.5"
+    object-copy "^0.1.0"
+
+"statuses@>= 1.3.1 < 2":
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+
+statuses@~1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
+
+stream-browserify@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
+  dependencies:
+    inherits "~2.0.1"
+    readable-stream "^2.0.2"
+
+stream-http@^2.7.2:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10"
+  dependencies:
+    builtin-status-codes "^3.0.0"
+    inherits "^2.0.1"
+    readable-stream "^2.3.3"
+    to-arraybuffer "^1.0.0"
+    xtend "^4.0.0"
+
+strict-uri-encode@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
+
+string-width@^1.0.1, string-width@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    strip-ansi "^3.0.0"
+
+string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^4.0.0"
+
+string_decoder@^1.0.0, string_decoder@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
+  dependencies:
+    safe-buffer "~5.1.0"
+
+string_decoder@~0.10.x:
+  version "0.10.31"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+stringstream@~0.0.4:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+  dependencies:
+    ansi-regex "^3.0.0"
+
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  dependencies:
+    is-utf8 "^0.2.0"
+
+strip-bom@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+
+strip-eof@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+
+strip-indent@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+  dependencies:
+    get-stdin "^4.0.1"
+
+strip-json-comments@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+style-loader@^0.18.2:
+  version "0.18.2"
+  resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.18.2.tgz#cc31459afbcd6d80b7220ee54b291a9fd66ff5eb"
+  dependencies:
+    loader-utils "^1.0.2"
+    schema-utils "^0.3.0"
+
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.2.3:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+  dependencies:
+    has-flag "^1.0.0"
+
+supports-color@^4.2.1:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
+  dependencies:
+    has-flag "^2.0.0"
+
+supports-color@^5.1.0, supports-color@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a"
+  dependencies:
+    has-flag "^3.0.0"
+
+svgo@^0.7.0:
+  version "0.7.2"
+  resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
+  dependencies:
+    coa "~1.0.1"
+    colors "~1.1.2"
+    csso "~2.3.1"
+    js-yaml "~3.7.0"
+    mkdirp "~0.5.1"
+    sax "~1.2.1"
+    whet.extend "~0.9.9"
+
+table@^4.0.1:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"
+  dependencies:
+    ajv "^5.2.3"
+    ajv-keywords "^2.1.0"
+    chalk "^2.1.0"
+    lodash "^4.17.4"
+    slice-ansi "1.0.0"
+    string-width "^2.1.1"
+
+tapable@^0.2.7:
+  version "0.2.8"
+  resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
+
+tar-pack@^3.4.0:
+  version "3.4.1"
+  resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f"
+  dependencies:
+    debug "^2.2.0"
+    fstream "^1.0.10"
+    fstream-ignore "^1.0.5"
+    once "^1.3.3"
+    readable-stream "^2.1.4"
+    rimraf "^2.5.1"
+    tar "^2.2.1"
+    uid-number "^0.0.6"
+
+tar-stream@^1.5.0:
+  version "1.5.5"
+  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55"
+  dependencies:
+    bl "^1.0.0"
+    end-of-stream "^1.0.0"
+    readable-stream "^2.0.0"
+    xtend "^4.0.0"
+
+tar@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
+  dependencies:
+    block-stream "*"
+    fstream "^1.0.2"
+    inherits "2"
+
+text-table@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+through@^2.3.6:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
+thunky@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371"
+
+time-stamp@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357"
+
+timers-browserify@^2.0.4:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae"
+  dependencies:
+    setimmediate "^1.0.4"
+
+tmp@^0.0.33:
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+  dependencies:
+    os-tmpdir "~1.0.2"
+
+to-arraybuffer@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
+
+to-fast-properties@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+
+to-fast-properties@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
+to-object-path@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
+  dependencies:
+    kind-of "^3.0.2"
+
+to-regex-range@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
+  dependencies:
+    is-number "^3.0.0"
+    repeat-string "^1.6.1"
+
+to-regex@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae"
+  dependencies:
+    define-property "^0.2.5"
+    extend-shallow "^2.0.1"
+    regex-not "^1.0.0"
+
+toposort@^1.0.0:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec"
+
+tough-cookie@~2.3.0:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
+  dependencies:
+    punycode "^1.4.1"
+
+trim-newlines@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+
+trim-right@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+
+tryer@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7"
+
+tty-browserify@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+
+tunnel-agent@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+  dependencies:
+    safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+  version "0.14.5"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+
+type-check@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  dependencies:
+    prelude-ls "~1.1.2"
+
+type-is@~1.6.15:
+  version "1.6.16"
+  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
+  dependencies:
+    media-typer "0.3.0"
+    mime-types "~2.1.18"
+
+typedarray@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+
+uglify-js@3.3.x:
+  version "3.3.11"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.11.tgz#e9d058b20715138bb4e8e5cae2ea581686bdaae3"
+  dependencies:
+    commander "~2.14.1"
+    source-map "~0.6.1"
+
+uglify-js@^2.8.29:
+  version "2.8.29"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+  dependencies:
+    source-map "~0.5.1"
+    yargs "~3.10.0"
+  optionalDependencies:
+    uglify-to-browserify "~1.0.0"
+
+uglify-to-browserify@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+
+uglifyjs-webpack-plugin@^0.4.6:
+  version "0.4.6"
+  resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309"
+  dependencies:
+    source-map "^0.5.6"
+    uglify-js "^2.8.29"
+    webpack-sources "^1.0.1"
+
+uid-number@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+
+ultron@~1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
+
+union-value@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
+  dependencies:
+    arr-union "^3.1.0"
+    get-value "^2.0.6"
+    is-extendable "^0.1.1"
+    set-value "^0.4.3"
+
+uniq@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
+
+uniqid@^4.0.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1"
+  dependencies:
+    macaddress "^0.2.8"
+
+uniqs@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+
+unset-value@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
+  dependencies:
+    has-value "^0.3.1"
+    isobject "^3.0.0"
+
+upath@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.2.tgz#80aaae5395abc5fd402933ae2f58694f0860204c"
+  dependencies:
+    lodash.endswith "^4.2.1"
+    lodash.isfunction "^3.0.8"
+    lodash.isstring "^4.0.1"
+    lodash.startswith "^4.2.1"
+
+upper-case@^1.1.1:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
+
+urix@^0.1.0, urix@~0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+
+url-loader@^0.5.9:
+  version "0.5.9"
+  resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295"
+  dependencies:
+    loader-utils "^1.0.2"
+    mime "1.3.x"
+
+url-parse@1.0.x:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
+  dependencies:
+    querystringify "0.0.x"
+    requires-port "1.0.x"
+
+url-parse@^1.1.8:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986"
+  dependencies:
+    querystringify "~1.0.0"
+    requires-port "~1.0.0"
+
+url@^0.11.0:
+  version "0.11.0"
+  resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+  dependencies:
+    punycode "1.3.2"
+    querystring "0.2.0"
+
+use@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8"
+  dependencies:
+    define-property "^0.2.5"
+    isobject "^3.0.0"
+    lazy-cache "^2.0.2"
+
+util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+util@0.10.3, util@^0.10.3:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+  dependencies:
+    inherits "2.0.1"
+
+utila@~0.3:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/utila/-/utila-0.3.3.tgz#d7e8e7d7e309107092b05f8d9688824d633a4226"
+
+utila@~0.4:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
+
+utils-merge@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+
+uuid@^3.0.0, uuid@^3.0.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
+
+validate-npm-package-license@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+  dependencies:
+    spdx-correct "~1.0.0"
+    spdx-expression-parse "~1.0.0"
+
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+
+vendors@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22"
+
+verror@1.10.0:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+  dependencies:
+    assert-plus "^1.0.0"
+    core-util-is "1.0.2"
+    extsprintf "^1.2.0"
+
+vm-browserify@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
+  dependencies:
+    indexof "0.0.1"
+
+walkdir@^0.0.11:
+  version "0.0.11"
+  resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532"
+
+watchpack@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac"
+  dependencies:
+    async "^2.1.2"
+    chokidar "^1.7.0"
+    graceful-fs "^4.1.2"
+
+wbuf@^1.1.0, wbuf@^1.7.2:
+  version "1.7.2"
+  resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe"
+  dependencies:
+    minimalistic-assert "^1.0.0"
+
+webpack-archive-plugin@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/webpack-archive-plugin/-/webpack-archive-plugin-3.0.0.tgz#924f2e5fbfce9385a309143e771fe3f9a6526e00"
+  dependencies:
+    archiver "^1.3.0"
+
+webpack-bundle-analyzer@^2.9.1:
+  version "2.10.0"
+  resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.10.0.tgz#d0646cda342939f6f05eb632a090abbd90317446"
+  dependencies:
+    acorn "^5.3.0"
+    bfj-node4 "^5.2.0"
+    chalk "^2.3.0"
+    commander "^2.13.0"
+    ejs "^2.5.7"
+    express "^4.16.2"
+    filesize "^3.5.11"
+    gzip-size "^4.1.0"
+    lodash "^4.17.4"
+    mkdirp "^0.5.1"
+    opener "^1.4.3"
+    ws "^4.0.0"
+
+webpack-dev-middleware@1.12.2:
+  version "1.12.2"
+  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz#f8fc1120ce3b4fc5680ceecb43d777966b21105e"
+  dependencies:
+    memory-fs "~0.4.1"
+    mime "^1.5.0"
+    path-is-absolute "^1.0.0"
+    range-parser "^1.0.3"
+    time-stamp "^2.0.0"
+
+webpack-dev-server@^2.6.1:
+  version "2.11.1"
+  resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.11.1.tgz#6f9358a002db8403f016e336816f4485384e5ec0"
+  dependencies:
+    ansi-html "0.0.7"
+    array-includes "^3.0.3"
+    bonjour "^3.5.0"
+    chokidar "^2.0.0"
+    compression "^1.5.2"
+    connect-history-api-fallback "^1.3.0"
+    debug "^3.1.0"
+    del "^3.0.0"
+    express "^4.16.2"
+    html-entities "^1.2.0"
+    http-proxy-middleware "~0.17.4"
+    import-local "^1.0.0"
+    internal-ip "1.2.0"
+    ip "^1.1.5"
+    killable "^1.0.0"
+    loglevel "^1.4.1"
+    opn "^5.1.0"
+    portfinder "^1.0.9"
+    selfsigned "^1.9.1"
+    serve-index "^1.7.2"
+    sockjs "0.3.19"
+    sockjs-client "1.1.4"
+    spdy "^3.4.1"
+    strip-ansi "^3.0.0"
+    supports-color "^5.1.0"
+    webpack-dev-middleware "1.12.2"
+    yargs "6.6.0"
+
+webpack-merge@^4.1.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.1.tgz#f1197a0a973e69c6fbeeb6d658219aa8c0c13555"
+  dependencies:
+    lodash "^4.17.4"
+
+webpack-sources@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"
+  dependencies:
+    source-list-map "^2.0.0"
+    source-map "~0.6.1"
+
+webpack@^3.3.0:
+  version "3.11.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.11.0.tgz#77da451b1d7b4b117adaf41a1a93b5742f24d894"
+  dependencies:
+    acorn "^5.0.0"
+    acorn-dynamic-import "^2.0.0"
+    ajv "^6.1.0"
+    ajv-keywords "^3.1.0"
+    async "^2.1.2"
+    enhanced-resolve "^3.4.0"
+    escope "^3.6.0"
+    interpret "^1.0.0"
+    json-loader "^0.5.4"
+    json5 "^0.5.1"
+    loader-runner "^2.3.0"
+    loader-utils "^1.1.0"
+    memory-fs "~0.4.1"
+    mkdirp "~0.5.0"
+    node-libs-browser "^2.0.0"
+    source-map "^0.5.3"
+    supports-color "^4.2.1"
+    tapable "^0.2.7"
+    uglifyjs-webpack-plugin "^0.4.6"
+    watchpack "^1.4.0"
+    webpack-sources "^1.0.1"
+    yargs "^8.0.2"
+
+websocket-driver@>=0.5.1:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb"
+  dependencies:
+    http-parser-js ">=0.4.0"
+    websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
+
+whet.extend@~0.9.9:
+  version "0.9.9"
+  resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"
+
+which-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+
+which-module@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+
+which@^1.2.9:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
+  dependencies:
+    isexe "^2.0.0"
+
+wide-align@^1.1.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
+  dependencies:
+    string-width "^1.0.2"
+
+window-size@0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+
+wordwrap@0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+
+wordwrap@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+wrap-ansi@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+write@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+  dependencies:
+    mkdirp "^0.5.1"
+
+ws@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-4.0.0.tgz#bfe1da4c08eeb9780b986e0e4d10eccd7345999f"
+  dependencies:
+    async-limiter "~1.0.0"
+    safe-buffer "~5.1.0"
+    ultron "~1.1.0"
+
+xml-char-classes@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d"
+
+xtend@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+y18n@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+
+yallist@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+
+yargs-parser@^4.2.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
+  dependencies:
+    camelcase "^3.0.0"
+
+yargs-parser@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"
+  dependencies:
+    camelcase "^4.1.0"
+
+yargs@6.6.0:
+  version "6.6.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
+  dependencies:
+    camelcase "^3.0.0"
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    os-locale "^1.4.0"
+    read-pkg-up "^1.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^1.0.2"
+    which-module "^1.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^4.2.0"
+
+yargs@^8.0.2:
+  version "8.0.2"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360"
+  dependencies:
+    camelcase "^4.1.0"
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    os-locale "^2.0.0"
+    read-pkg-up "^2.0.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^7.0.0"
+
+yargs@~3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+  dependencies:
+    camelcase "^1.0.2"
+    cliui "^2.1.0"
+    decamelize "^1.0.0"
+    window-size "0.1.0"
+
+zip-stream@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04"
+  dependencies:
+    archiver-utils "^1.3.0"
+    compress-commons "^1.2.0"
+    lodash "^4.8.0"
+    readable-stream "^2.0.0"
diff --git a/zuul/_setup_hook.py b/zuul/_setup_hook.py
new file mode 100644
index 0000000..d6c730d
--- /dev/null
+++ b/zuul/_setup_hook.py
@@ -0,0 +1,39 @@
+# Copyright 2018 Red Hat, Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""Hook for pbr to build javascript as part of tarball."""
+
+import os
+import subprocess
+
+import pbr.packaging
+
+_old_from_git = pbr.packaging._from_git
+
+
+def _build_javascript():
+    if subprocess.call(['which', 'yarn']) != 0:
+        return
+    if not os.path.exists('node_modules/.bin/webpack'):
+        subprocess.check_call(['yarn', 'install', '-d'])
+    if not os.path.exists('zuul/web/static/status.bundle.js'):
+        subprocess.check_call(['npm', 'run', 'build:dist'])
+
+
+def _from_git(distribution):
+    _build_javascript()
+    return _old_from_git(distribution)
+
+
+def setup_hook(config):
+    pbr.packaging._from_git = _from_git
diff --git a/zuul/cmd/web.py b/zuul/cmd/web.py
index 8b0e3ee..cfaa2b8 100755
--- a/zuul/cmd/web.py
+++ b/zuul/cmd/web.py
@@ -46,6 +46,9 @@
         params['static_cache_expiry'] = get_default(self.config, 'web',
                                                     'static_cache_expiry',
                                                     3600)
+        params['static_path'] = get_default(self.config,
+                                            'web', 'static_path',
+                                            None)
         params['gear_server'] = get_default(self.config, 'gearman', 'server')
         params['gear_port'] = get_default(self.config, 'gearman', 'port', 4730)
         params['ssl_key'] = get_default(self.config, 'gearman', 'ssl_key')
diff --git a/zuul/web/__init__.py b/zuul/web/__init__.py
index 8f4bf72..1373b2e 100755
--- a/zuul/web/__init__.py
+++ b/zuul/web/__init__.py
@@ -237,7 +237,8 @@
                  ssl_key=None, ssl_cert=None, ssl_ca=None,
                  static_cache_expiry=3600,
                  connections=None,
-                 info=None):
+                 info=None,
+                 static_path=None):
         self.start_time = time.time()
         self.listen_address = listen_address
         self.listen_port = listen_port
@@ -246,6 +247,7 @@
         self.server = None
         self.static_cache_expiry = static_cache_expiry
         self.info = info
+        self.static_path = static_path or STATIC_DIR
         # instanciate handlers
         self.rpc = zuul.rpcclient.RPCClient(gear_server, gear_port,
                                             ssl_key, ssl_cert, ssl_ca)
@@ -320,13 +322,22 @@
         ]
 
         static_routes = [
-            StaticHandler(self, '/{tenant}/status.html'),
-            StaticHandler(self, '/{tenant}/jobs.html'),
-            StaticHandler(self, '/{tenant}/stream.html'),
-            StaticHandler(self, '/tenants.html', 'index.html'),
-            StaticHandler(self, '/', 'index.html'),
+            StaticHandler(self, '/{tenant}/', 'status.html'),
+            StaticHandler(self, '/', 'tenants.html'),
         ]
 
+        for static_file in os.listdir(self.static_path):
+            static_routes.append(
+                StaticHandler(
+                    self, '/{{tenant}}/{static_file}'.format(
+                        static_file=static_file),
+                    static_file))
+            static_routes.append(
+                StaticHandler(
+                    self, '/{static_file}'.format(
+                        static_file=static_file),
+                    static_file))
+
         for route in static_routes + self._plugin_routes:
             routes.append((route.method, route.path, route.handleRequest))
 
@@ -343,7 +354,7 @@
         app = web.Application()
         for method, path, handler in routes:
             app.router.add_route(method, path, handler)
-        app.router.add_static('/static', STATIC_DIR)
+        app.router.add_static('/static', self.static_path)
         handler = app.make_handler(loop=self.event_loop)
 
         # create the server
diff --git a/zuul/web/static/README b/zuul/web/static/README
deleted file mode 100644
index e924dc7..0000000
--- a/zuul/web/static/README
+++ /dev/null
@@ -1,61 +0,0 @@
-External requirements needs to be installed in these locations
-* /static/js/angular.min.js
-* /static/js/jquery.min.js
-* /static/js/jquery-visibility.min.js
-* /static/js/jquery.graphite.min.js
-* /static/bootstrap/css/bootstrap.min.css
-
-
-Use python2-rjsmin or another js minifier:
-```
-DEST_DIR=/var/www/html/static/
-mkdir -p $DEST_DIR/js
-echo "Fetching angular..."
-curl -L --silent https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js > $DEST_DIR/js/angular.min.js
-
-echo "Fetching jquery..."
-curl -L --silent http://code.jquery.com/jquery.min.js > $DEST_DIR/js/jquery.min.js
-
-echo "Fetching jquery-visibility..."
-curl -L --silent https://raw.githubusercontent.com/mathiasbynens/jquery-visibility/master/jquery-visibility.js > $DEST_DIR/js/jquery-visibility.js
-python2 -mrjsmin < $DEST_DIR/js/jquery-visibility.js > $DEST_DIR/js/jquery-visibility.min.js
-
-echo "Fetching bootstrap..."
-curl -L --silent https://github.com/twbs/bootstrap/releases/download/v3.1.1/bootstrap-3.1.1-dist.zip > bootstrap.zip
-unzip -q -o bootstrap.zip -d $DEST_DIR/
-mv $DEST_DIR/bootstrap-3.1.1-dist $DEST_DIR/bootstrap
-rm -f bootstrap.zip
-
-echo "Fetching jquery-graphite..."
-curl -L --silent https://github.com/prestontimmons/graphitejs/archive/master.zip > jquery-graphite.zip
-unzip -q -o jquery-graphite.zip -d $DEST_DIR/
-python2 -mrjsmin < $DEST_DIR/graphitejs-master/jquery.graphite.js > $DEST_DIR/js/jquery.graphite.min.js
-rm -Rf jquery-graphite.zip $DEST_DIR/graphitejs-master
-```
-
-
-Here is an example apache vhost configuration:
-<VirtualHost zuul-web.example.com:80>
-  DocumentRoot /var/www/zuul-web
-
-  LogLevel warn
-
-  Alias "/static" "/var/www/zuul-web"
-  AliasMatch "^/.*/(.*).html" "/var/www/zuul-web/$1.html"
-  AliasMatch "^/.*.html" "/var/www/zuul-web/index.html"
-  <Directory /var/www/zuul-web>
-      Require all granted
-      Order allow,deny
-      Allow from all
-  </Directory>
-
-  # Console-stream needs a special proxy-pass for websocket
-  ProxyPassMatch /(.*)/console-stream ws://localhost:9000/$1/console-stream nocanon retry=0
-
-  # Then only the json calls are sent to the zuul-web endpoints
-  ProxyPassMatch ^/(.*.json)$ http://localhost:9000/$1 nocanon retry=0
-  ProxyPassReverse / http://localhost:9000/
-</VirtualHost>
-
-Then copy the zuul/web/static/ files and external requirements to
-/var/www/zuul-web
diff --git a/zuul/web/static/javascripts/jquery.zuul.js b/zuul/web/static/javascripts/jquery.zuul.js
deleted file mode 100644
index 7da81dc..0000000
--- a/zuul/web/static/javascripts/jquery.zuul.js
+++ /dev/null
@@ -1,945 +0,0 @@
-// jquery plugin for Zuul status page
-//
-// @licstart  The following is the entire license notice for the
-// JavaScript code in this page.
-//
-// Copyright 2012 OpenStack Foundation
-// Copyright 2013 Timo Tijhof
-// Copyright 2013 Wikimedia Foundation
-// Copyright 2014 Rackspace Australia
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-//
-// @licend  The above is the entire license notice
-// for the JavaScript code in this page.
-
-(function ($) {
-    'use strict';
-
-    function set_cookie(name, value) {
-        document.cookie = name + '=' + value + '; path=/';
-    }
-
-    function read_cookie(name, default_value) {
-        var nameEQ = name + '=';
-        var ca = document.cookie.split(';');
-        for(var i=0;i < ca.length;i++) {
-            var c = ca[i];
-            while (c.charAt(0) === ' ') {
-                c = c.substring(1, c.length);
-            }
-            if (c.indexOf(nameEQ) === 0) {
-                return c.substring(nameEQ.length, c.length);
-            }
-        }
-        return default_value;
-    }
-
-    $.zuul = function(options) {
-        options = $.extend({
-            'enabled': true,
-            'graphite_url': '',
-            'source': 'status',
-            'msg_id': '#zuul_msg',
-            'pipelines_id': '#zuul_pipelines',
-            'queue_events_num': '#zuul_queue_events_num',
-            'queue_management_events_num': '#zuul_queue_management_events_num',
-            'queue_results_num': '#zuul_queue_results_num',
-        }, options);
-
-        var collapsed_exceptions = [];
-        var current_filter = read_cookie('zuul_filter_string', '');
-        var change_set_in_url = window.location.href.split('#')[1];
-        if (change_set_in_url) {
-           current_filter = change_set_in_url;
-        }
-        var $jq;
-
-        var xhr,
-            zuul_graph_update_count = 0,
-            zuul_sparkline_urls = {};
-
-        function get_sparkline_url(pipeline_name) {
-            if (options.graphite_url !== '') {
-                if (!(pipeline_name in zuul_sparkline_urls)) {
-                    zuul_sparkline_urls[pipeline_name] = $.fn.graphite
-                        .geturl({
-                        url: options.graphite_url,
-                        from: "-8hours",
-                        width: 100,
-                        height: 26,
-                        margin: 0,
-                        hideLegend: true,
-                        hideAxes: true,
-                        hideGrid: true,
-                        target: [
-                            "color(stats.gauges.zuul.pipeline." + pipeline_name
-                                + ".current_changes, '6b8182')"
-                        ]
-                    });
-                }
-                return zuul_sparkline_urls[pipeline_name];
-            }
-            return false;
-        }
-
-        var format = {
-            job: function(job) {
-                var $job_line = $('<span />');
-
-                if (job.result !== null) {
-                    $job_line.append(
-                        $('<a />')
-                            .addClass('zuul-job-name')
-                            .attr('href', job.report_url)
-                            .text(job.name)
-                    );
-                }
-                else if (job.url !== null) {
-                    $job_line.append(
-                        $('<a />')
-                            .addClass('zuul-job-name')
-                            .attr('href', job.url)
-                            .text(job.name)
-                    );
-                }
-                else {
-                    $job_line.append(
-                        $('<span />')
-                            .addClass('zuul-job-name')
-                            .text(job.name)
-                    );
-                }
-
-                $job_line.append(this.job_status(job));
-
-                if (job.voting === false) {
-                    $job_line.append(
-                        $(' <small />')
-                            .addClass('zuul-non-voting-desc')
-                            .text(' (non-voting)')
-                    );
-                }
-
-                $job_line.append($('<div style="clear: both"></div>'));
-                return $job_line;
-            },
-
-            job_status: function(job) {
-                var result = job.result ? job.result.toLowerCase() : null;
-                if (result === null) {
-                    result = job.url ? 'in progress' : 'queued';
-                }
-
-                if (result === 'in progress') {
-                    return this.job_progress_bar(job.elapsed_time,
-                                                        job.remaining_time);
-                }
-                else {
-                    return this.status_label(result);
-                }
-            },
-
-            status_label: function(result) {
-                var $status = $('<span />');
-                $status.addClass('zuul-job-result label');
-
-                switch (result) {
-                    case 'success':
-                        $status.addClass('label-success');
-                        break;
-                    case 'failure':
-                        $status.addClass('label-danger');
-                        break;
-                    case 'unstable':
-                        $status.addClass('label-warning');
-                        break;
-                    case 'skipped':
-                        $status.addClass('label-info');
-                        break;
-                    // 'in progress' 'queued' 'lost' 'aborted' ...
-                    default:
-                        $status.addClass('label-default');
-                }
-                $status.text(result);
-                return $status;
-            },
-
-            job_progress_bar: function(elapsed_time, remaining_time) {
-                var progress_percent = 100 * (elapsed_time / (elapsed_time +
-                                                              remaining_time));
-                var $bar_inner = $('<div />')
-                    .addClass('progress-bar')
-                    .attr('role', 'progressbar')
-                    .attr('aria-valuenow', 'progressbar')
-                    .attr('aria-valuemin', progress_percent)
-                    .attr('aria-valuemin', '0')
-                    .attr('aria-valuemax', '100')
-                    .css('width', progress_percent + '%');
-
-                var $bar_outter = $('<div />')
-                    .addClass('progress zuul-job-result')
-                    .append($bar_inner);
-
-                return $bar_outter;
-            },
-
-            enqueue_time: function(ms) {
-                // Special format case for enqueue time to add style
-                var hours = 60 * 60 * 1000;
-                var now = Date.now();
-                var delta = now - ms;
-                var status = 'text-success';
-                var text = this.time(delta, true);
-                if (delta > (4 * hours)) {
-                    status = 'text-danger';
-                } else if (delta > (2 * hours)) {
-                    status = 'text-warning';
-                }
-                return '<span class="' + status + '">' + text + '</span>';
-            },
-
-            time: function(ms, words) {
-                if (typeof(words) === 'undefined') {
-                    words = false;
-                }
-                var seconds = (+ms)/1000;
-                var minutes = Math.floor(seconds/60);
-                var hours = Math.floor(minutes/60);
-                seconds = Math.floor(seconds % 60);
-                minutes = Math.floor(minutes % 60);
-                var r = '';
-                if (words) {
-                    if (hours) {
-                        r += hours;
-                        r += ' hr ';
-                    }
-                    r += minutes + ' min';
-                } else {
-                    if (hours < 10) {
-                        r += '0';
-                    }
-                    r += hours + ':';
-                    if (minutes < 10) {
-                        r += '0';
-                    }
-                    r += minutes + ':';
-                    if (seconds < 10) {
-                        r += '0';
-                    }
-                    r += seconds;
-                }
-                return r;
-            },
-
-            change_total_progress_bar: function(change) {
-                var job_percent = Math.floor(100 / change.jobs.length);
-                var $bar_outter = $('<div />')
-                    .addClass('progress zuul-change-total-result');
-
-                $.each(change.jobs, function (i, job) {
-                    var result = job.result ? job.result.toLowerCase() : null;
-                    if (result === null) {
-                        result = job.url ? 'in progress' : 'queued';
-                    }
-
-                    if (result !== 'queued') {
-                        var $bar_inner = $('<div />')
-                            .addClass('progress-bar');
-
-                        switch (result) {
-                            case 'success':
-                                $bar_inner.addClass('progress-bar-success');
-                                break;
-                            case 'lost':
-                            case 'failure':
-                                $bar_inner.addClass('progress-bar-danger');
-                                break;
-                            case 'unstable':
-                                $bar_inner.addClass('progress-bar-warning');
-                                break;
-                            case 'in progress':
-                            case 'queued':
-                                break;
-                        }
-                        $bar_inner.attr('title', job.name)
-                            .css('width', job_percent + '%');
-                        $bar_outter.append($bar_inner);
-                    }
-                });
-                return $bar_outter;
-            },
-
-            change_header: function(change) {
-                var change_id = change.id || 'NA';
-
-                var $change_link = $('<small />');
-                if (change.url !== null) {
-                    var github_id = change_id.match(/^([0-9]+),([0-9a-f]{40})$/);
-                    if (github_id) {
-                        $change_link.append(
-                            $('<a />').attr('href', change.url).append(
-                                $('<abbr />')
-                                    .attr('title', change_id)
-                                    .text('#' + github_id[1])
-                            )
-                        );
-                    } else if (/^[0-9a-f]{40}$/.test(change_id)) {
-                        var change_id_short = change_id.slice(0, 7);
-                        $change_link.append(
-                            $('<a />').attr('href', change.url).append(
-                                $('<abbr />')
-                                    .attr('title', change_id)
-                                    .text(change_id_short)
-                            )
-                        );
-                    }
-                    else {
-                        $change_link.append(
-                            $('<a />').attr('href', change.url).text(change_id)
-                        );
-                    }
-                }
-                else {
-                    if (change_id.length === 40) {
-                        change_id = change_id.substr(0, 7);
-                    }
-                    $change_link.text(change_id);
-                }
-
-                var $change_progress_row_left = $('<div />')
-                    .addClass('col-xs-4')
-                    .append($change_link);
-                var $change_progress_row_right = $('<div />')
-                    .addClass('col-xs-8')
-                    .append(this.change_total_progress_bar(change));
-
-                var $change_progress_row = $('<div />')
-                    .addClass('row')
-                    .append($change_progress_row_left)
-                    .append($change_progress_row_right);
-
-                var $project_span = $('<span />')
-                    .addClass('change_project')
-                    .text(change.project);
-
-                var $left = $('<div />')
-                    .addClass('col-xs-8')
-                    .append($project_span, $change_progress_row);
-
-                var remaining_time = this.time(
-                        change.remaining_time, true);
-                var enqueue_time = this.enqueue_time(
-                        change.enqueue_time);
-                var $remaining_time = $('<small />').addClass('time')
-                    .attr('title', 'Remaining Time').html(remaining_time);
-                var $enqueue_time = $('<small />').addClass('time')
-                    .attr('title', 'Elapsed Time').html(enqueue_time);
-
-                var $right = $('<div />');
-                if (change.live === true) {
-                    $right.addClass('col-xs-4 text-right')
-                        .append($remaining_time, $('<br />'), $enqueue_time);
-                }
-
-                var $header = $('<div />')
-                    .addClass('row')
-                    .append($left, $right);
-                return $header;
-            },
-
-            change_list: function(jobs) {
-                var format = this;
-                var $list = $('<ul />')
-                    .addClass('list-group zuul-patchset-body');
-
-                $.each(jobs, function (i, job) {
-                    var $item = $('<li />')
-                        .addClass('list-group-item')
-                        .addClass('zuul-change-job')
-                        .append(format.job(job));
-                    $list.append($item);
-                });
-
-                return $list;
-            },
-
-            change_panel: function (change) {
-                var $header = $('<div />')
-                    .addClass('panel-heading zuul-patchset-header')
-                    .append(this.change_header(change));
-
-                var panel_id = change.id ? change.id.replace(',', '_')
-                                         : change.project.replace('/', '_') +
-                                           '-' + change.enqueue_time;
-                var $panel = $('<div />')
-                    .attr('id', panel_id)
-                    .addClass('panel panel-default zuul-change')
-                    .append($header)
-                    .append(this.change_list(change.jobs));
-
-                $header.click(this.toggle_patchset);
-                return $panel;
-            },
-
-            change_status_icon: function(change) {
-                var icon_name = 'green.png';
-                var icon_title = 'Succeeding';
-
-                if (change.active !== true) {
-                    // Grey icon
-                    icon_name = 'grey.png';
-                    icon_title = 'Waiting until closer to head of queue to' +
-                        ' start jobs';
-                }
-                else if (change.live !== true) {
-                    // Grey icon
-                    icon_name = 'grey.png';
-                    icon_title = 'Dependent change required for testing';
-                }
-                else if (change.failing_reasons &&
-                         change.failing_reasons.length > 0) {
-                    var reason = change.failing_reasons.join(', ');
-                    icon_title = 'Failing because ' + reason;
-                    if (reason.match(/merge conflict/)) {
-                        // Black icon
-                        icon_name = 'black.png';
-                    }
-                    else {
-                        // Red icon
-                        icon_name = 'red.png';
-                    }
-                }
-
-                var $icon = $('<img />')
-                    .attr('src', '../static/images/' + icon_name)
-                    .attr('title', icon_title)
-                    .css('margin-top', '-6px');
-
-                return $icon;
-            },
-
-            change_with_status_tree: function(change, change_queue) {
-                var $change_row = $('<tr />');
-
-                for (var i = 0; i < change_queue._tree_columns; i++) {
-                    var $tree_cell  = $('<td />')
-                        .css('height', '100%')
-                        .css('padding', '0 0 10px 0')
-                        .css('margin', '0')
-                        .css('width', '16px')
-                        .css('min-width', '16px')
-                        .css('overflow', 'hidden')
-                        .css('vertical-align', 'top');
-
-                    if (i < change._tree.length && change._tree[i] !== null) {
-                        $tree_cell.css('background-image',
-                                       'url(\'../static/images/line.png\')')
-                            .css('background-repeat', 'repeat-y');
-                    }
-
-                    if (i === change._tree_index) {
-                        $tree_cell.append(
-                            this.change_status_icon(change));
-                    }
-                    if (change._tree_branches.indexOf(i) !== -1) {
-                        var $image = $('<img />')
-                            .css('vertical-align', 'baseline');
-                        if (change._tree_branches.indexOf(i) ===
-                            change._tree_branches.length - 1) {
-                            // Angle line
-                            $image.attr('src', '../static/images/line-angle.png');
-                        }
-                        else {
-                            // T line
-                            $image.attr('src', '../static/images/line-t.png');
-                        }
-                        $tree_cell.append($image);
-                    }
-                    $change_row.append($tree_cell);
-                }
-
-                var change_width = 360 - 16*change_queue._tree_columns;
-                var $change_column = $('<td />')
-                    .css('width', change_width + 'px')
-                    .addClass('zuul-change-cell')
-                    .append(this.change_panel(change));
-
-                $change_row.append($change_column);
-
-                var $change_table = $('<table />')
-                    .addClass('zuul-change-box')
-                    .css('-moz-box-sizing', 'content-box')
-                    .css('box-sizing', 'content-box')
-                    .append($change_row);
-
-                return $change_table;
-            },
-
-            pipeline_sparkline: function(pipeline_name) {
-                if (options.graphite_url !== '') {
-                    var $sparkline = $('<img />')
-                        .addClass('pull-right')
-                        .attr('src', get_sparkline_url(pipeline_name));
-                    return $sparkline;
-                }
-                return false;
-            },
-
-            pipeline_header: function(pipeline, count) {
-                // Format the pipeline name, sparkline and description
-                var $header_div = $('<div />')
-                    .addClass('zuul-pipeline-header');
-
-                var $heading = $('<h3 />')
-                    .css('vertical-align', 'middle')
-                    .text(pipeline.name)
-                    .append(
-                        $('<span />')
-                            .addClass('badge pull-right')
-                            .css('vertical-align', 'middle')
-                            .css('margin-top', '0.5em')
-                            .text(count)
-                    )
-                    .append(this.pipeline_sparkline(pipeline.name));
-
-                $header_div.append($heading);
-
-                if (typeof pipeline.description === 'string') {
-                    var descr = $('<small />')
-                    $.each( pipeline.description.split(/\r?\n\r?\n/), function(index, descr_part){
-                        descr.append($('<p />').text(descr_part));
-                    });
-                    $header_div.append(
-                        $('<p />').append(descr)
-                    );
-                }
-                return $header_div;
-            },
-
-            pipeline: function (pipeline, count) {
-                var format = this;
-                var $html = $('<div />')
-                    .addClass('zuul-pipeline col-md-4')
-                    .append(this.pipeline_header(pipeline, count));
-
-                $.each(pipeline.change_queues,
-                       function (queue_i, change_queue) {
-                    $.each(change_queue.heads, function (head_i, changes) {
-                        if (pipeline.change_queues.length > 1 &&
-                            head_i === 0) {
-                            var name = change_queue.name;
-                            var short_name = name;
-                            if (short_name.length > 32) {
-                                short_name = short_name.substr(0, 32) + '...';
-                            }
-                            $html.append(
-                                $('<p />')
-                                    .text('Queue: ')
-                                    .append(
-                                        $('<abbr />')
-                                            .attr('title', name)
-                                            .text(short_name)
-                                    )
-                            );
-                        }
-
-                        $.each(changes, function (change_i, change) {
-                            var $change_box =
-                                format.change_with_status_tree(
-                                    change, change_queue);
-                            $html.append($change_box);
-                            format.display_patchset($change_box);
-                        });
-                    });
-                });
-                return $html;
-            },
-
-            toggle_patchset: function(e) {
-                // Toggle showing/hiding the patchset when the header is
-                // clicked.
-
-                if (e.target.nodeName.toLowerCase() === 'a') {
-                    // Ignore clicks from gerrit patch set link
-                    return;
-                }
-
-                // Grab the patchset panel
-                var $panel = $(e.target).parents('.zuul-change');
-                var $body = $panel.children('.zuul-patchset-body');
-                $body.toggle(200);
-                var collapsed_index = collapsed_exceptions.indexOf(
-                    $panel.attr('id'));
-                if (collapsed_index === -1 ) {
-                    // Currently not an exception, add it to list
-                    collapsed_exceptions.push($panel.attr('id'));
-                }
-                else {
-                    // Currently an except, remove from exceptions
-                    collapsed_exceptions.splice(collapsed_index, 1);
-                }
-            },
-
-            display_patchset: function($change_box, animate) {
-                // Determine if to show or hide the patchset and/or the results
-                // when loaded
-
-                // See if we should hide the body/results
-                var $panel = $change_box.find('.zuul-change');
-                var panel_change = $panel.attr('id');
-                var $body = $panel.children('.zuul-patchset-body');
-                var expand_by_default = $('#expand_by_default')
-                    .prop('checked');
-
-                var collapsed_index = collapsed_exceptions
-                    .indexOf(panel_change);
-
-                if (expand_by_default && collapsed_index === -1 ||
-                    !expand_by_default && collapsed_index !== -1) {
-                    // Expand by default, or is an exception
-                    $body.show(animate);
-                }
-                else {
-                    $body.hide(animate);
-                }
-
-                // Check if we should hide the whole panel
-                var panel_project = $panel.find('.change_project').text()
-                    .toLowerCase();
-
-
-                var panel_pipeline = $change_box
-                    .parents('.zuul-pipeline')
-                    .find('.zuul-pipeline-header > h3')
-                    .html()
-                    .toLowerCase();
-
-                if (current_filter !== '') {
-                    var show_panel = false;
-                    var filter = current_filter.trim().split(/[\s,]+/);
-                    $.each(filter, function(index, f_val) {
-                        if (f_val !== '') {
-                            f_val = f_val.toLowerCase();
-                            if (panel_project.indexOf(f_val) !== -1 ||
-                                panel_pipeline.indexOf(f_val) !== -1 ||
-                                panel_change.indexOf(f_val) !== -1) {
-                                show_panel = true;
-                            }
-                        }
-                    });
-                    if (show_panel === true) {
-                        $change_box.show(animate);
-                    }
-                    else {
-                        $change_box.hide(animate);
-                    }
-                }
-                else {
-                    $change_box.show(animate);
-                }
-            },
-        };
-
-        var app = {
-            schedule: function (app) {
-                app = app || this;
-                if (!options.enabled) {
-                    setTimeout(function() {app.schedule(app);}, 5000);
-                    return;
-                }
-                app.update().always(function () {
-                    setTimeout(function() {app.schedule(app);}, 5000);
-                });
-
-                /* Only update graphs every minute */
-                if (zuul_graph_update_count > 11) {
-                    zuul_graph_update_count = 0;
-                    zuul.update_sparklines();
-                }
-            },
-
-            /** @return {jQuery.Promise} */
-            update: function () {
-                // Cancel the previous update if it hasn't completed yet.
-                if (xhr) {
-                    xhr.abort();
-                }
-
-                this.emit('update-start');
-                var app = this;
-
-                var $msg = $(options.msg_id);
-                xhr = $.getJSON(options.source)
-                    .done(function (data) {
-                        if ('message' in data) {
-                            $msg.removeClass('alert-danger')
-                                .addClass('alert-info')
-                                .text(data.message)
-                                .show();
-                        } else {
-                            $msg.empty()
-                                .hide();
-                        }
-
-                        if ('zuul_version' in data) {
-                            $('#zuul-version-span').text(data.zuul_version);
-                        }
-                        if ('last_reconfigured' in data) {
-                            var last_reconfigured =
-                                new Date(data.last_reconfigured);
-                            $('#last-reconfigured-span').text(
-                                last_reconfigured.toString());
-                        }
-
-                        var $pipelines = $(options.pipelines_id);
-                        $pipelines.html('');
-                        $.each(data.pipelines, function (i, pipeline) {
-                            var count = app.create_tree(pipeline);
-                            $pipelines.append(
-                                format.pipeline(pipeline, count));
-                        });
-
-                        $(options.queue_events_num).text(
-                            data.trigger_event_queue ?
-                                data.trigger_event_queue.length : '0'
-                        );
-                        $(options.queue_management_events_num).text(
-                            data.management_event_queue ?
-                                data.management_event_queue.length : '0'
-                        );
-                        $(options.queue_results_num).text(
-                            data.result_event_queue ?
-                                data.result_event_queue.length : '0'
-                        );
-                    })
-                    .fail(function (jqXHR, statusText, errMsg) {
-                        if (statusText === 'abort') {
-                            return;
-                        }
-                        $msg.text(options.source + ': ' + errMsg)
-                            .addClass('alert-danger')
-                            .removeClass('zuul-msg-wrap-off')
-                            .show();
-                    })
-                    .always(function () {
-                        xhr = undefined;
-                        app.emit('update-end');
-                    });
-
-                return xhr;
-            },
-
-            update_sparklines: function() {
-                $.each(zuul_sparkline_urls, function(name, url) {
-                    var newimg = new Image();
-                    var parts = url.split('#');
-                    newimg.src = parts[0] + '#' + new Date().getTime();
-                    $(newimg).load(function () {
-                        zuul_sparkline_urls[name] = newimg.src;
-                    });
-                });
-            },
-
-            emit: function () {
-                $jq.trigger.apply($jq, arguments);
-                return this;
-            },
-            on: function () {
-                $jq.on.apply($jq, arguments);
-                return this;
-            },
-            one: function () {
-                $jq.one.apply($jq, arguments);
-                return this;
-            },
-
-            control_form: function() {
-                // Build the filter form filling anything from cookies
-
-                var $control_form = $('<form />')
-                    .attr('role', 'form')
-                    .addClass('form-inline')
-                    .submit(this.handle_filter_change);
-
-                $control_form
-                    .append(this.filter_form_group())
-                    .append(this.expand_form_group());
-
-                return $control_form;
-            },
-
-            filter_form_group: function() {
-                // Update the filter form with a clear button if required
-
-                var $label = $('<label />')
-                    .addClass('control-label')
-                    .attr('for', 'filter_string')
-                    .text('Filters')
-                    .css('padding-right', '0.5em');
-
-                var $input = $('<input />')
-                    .attr('type', 'text')
-                    .attr('id', 'filter_string')
-                    .addClass('form-control')
-                    .attr('title',
-                          'project(s), pipeline(s) or review(s) comma ' +
-                          'separated')
-                    .attr('value', current_filter);
-
-                $input.change(this.handle_filter_change);
-
-                var $clear_icon = $('<span />')
-                    .addClass('form-control-feedback')
-                    .addClass('glyphicon glyphicon-remove-circle')
-                    .attr('id', 'filter_form_clear_box')
-                    .attr('title', 'clear filter')
-                    .css('cursor', 'pointer');
-
-                $clear_icon.click(function() {
-                    $('#filter_string').val('').change();
-                });
-
-                if (current_filter === '') {
-                    $clear_icon.hide();
-                }
-
-                var $form_group = $('<div />')
-                    .addClass('form-group has-feedback')
-                    .append($label, $input, $clear_icon);
-                return $form_group;
-            },
-
-            expand_form_group: function() {
-                var expand_by_default = (
-                    read_cookie('zuul_expand_by_default', false) === 'true');
-
-                var $checkbox = $('<input />')
-                    .attr('type', 'checkbox')
-                    .attr('id', 'expand_by_default')
-                    .prop('checked', expand_by_default)
-                    .change(this.handle_expand_by_default);
-
-                var $label = $('<label />')
-                    .css('padding-left', '1em')
-                    .html('Expand by default: ')
-                    .append($checkbox);
-
-                var $form_group = $('<div />')
-                    .addClass('checkbox')
-                    .append($label);
-                return $form_group;
-            },
-
-            handle_filter_change: function() {
-                // Update the filter and save it to a cookie
-                current_filter = $('#filter_string').val();
-                set_cookie('zuul_filter_string', current_filter);
-                if (current_filter === '') {
-                    $('#filter_form_clear_box').hide();
-                }
-                else {
-                    $('#filter_form_clear_box').show();
-                }
-
-                $('.zuul-change-box').each(function(index, obj) {
-                    var $change_box = $(obj);
-                    format.display_patchset($change_box, 200);
-                });
-                return false;
-            },
-
-            handle_expand_by_default: function(e) {
-                // Handle toggling expand by default
-                set_cookie('zuul_expand_by_default', e.target.checked);
-                collapsed_exceptions = [];
-                $('.zuul-change-box').each(function(index, obj) {
-                    var $change_box = $(obj);
-                    format.display_patchset($change_box, 200);
-                });
-            },
-
-            create_tree: function(pipeline) {
-                var count = 0;
-                var pipeline_max_tree_columns = 1;
-                $.each(pipeline.change_queues, function(change_queue_i,
-                                                           change_queue) {
-                    var tree = [];
-                    var max_tree_columns = 1;
-                    var changes = [];
-                    var last_tree_length = 0;
-                    $.each(change_queue.heads, function(head_i, head) {
-                        $.each(head, function(change_i, change) {
-                            changes[change.id] = change;
-                            change._tree_position = change_i;
-                        });
-                    });
-                    $.each(change_queue.heads, function(head_i, head) {
-                        $.each(head, function(change_i, change) {
-                            if (change.live === true) {
-                                count += 1;
-                            }
-                            var idx = tree.indexOf(change.id);
-                            if (idx > -1) {
-                                change._tree_index = idx;
-                                // remove...
-                                tree[idx] = null;
-                                while (tree[tree.length - 1] === null) {
-                                    tree.pop();
-                                }
-                            } else {
-                                change._tree_index = 0;
-                            }
-                            change._tree_branches = [];
-                            change._tree = [];
-                            if (typeof(change.items_behind) === 'undefined') {
-                                change.items_behind = [];
-                            }
-                            change.items_behind.sort(function(a, b) {
-                                return (changes[b]._tree_position -
-                                        changes[a]._tree_position);
-                            });
-                            $.each(change.items_behind, function(i, id) {
-                                tree.push(id);
-                                if (tree.length>last_tree_length &&
-                                    last_tree_length > 0) {
-                                    change._tree_branches.push(
-                                        tree.length - 1);
-                                }
-                            });
-                            if (tree.length > max_tree_columns) {
-                                max_tree_columns = tree.length;
-                            }
-                            if (tree.length > pipeline_max_tree_columns) {
-                                pipeline_max_tree_columns = tree.length;
-                            }
-                            change._tree = tree.slice(0);  // make a copy
-                            last_tree_length = tree.length;
-                        });
-                    });
-                    change_queue._tree_columns = max_tree_columns;
-                });
-                pipeline._tree_columns = pipeline_max_tree_columns;
-                return count;
-            },
-        };
-
-        $jq = $(app);
-        return {
-            options: options,
-            format: format,
-            app: app,
-            jq: $jq
-        };
-    };
-}(jQuery));
diff --git a/zuul/web/static/javascripts/zuul.angular.js b/zuul/web/static/javascripts/zuul.angular.js
deleted file mode 100644
index 49f2518..0000000
--- a/zuul/web/static/javascripts/zuul.angular.js
+++ /dev/null
@@ -1,99 +0,0 @@
-// @licstart  The following is the entire license notice for the
-// JavaScript code in this page.
-//
-// Copyright 2017 Red Hat
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-//
-// @licend  The above is the entire license notice
-// for the JavaScript code in this page.
-
-angular.module('zuulTenants', []).controller(
-    'mainController', function($scope, $http)
-{
-    $scope.tenants = undefined;
-    $scope.tenants_fetch = function() {
-        $http.get("tenants")
-            .then(function success(result) {
-                $scope.tenants = result.data;
-            });
-    }
-    $scope.tenants_fetch();
-});
-
-angular.module('zuulJobs', []).controller(
-    'mainController', function($scope, $http)
-{
-    $scope.jobs = undefined;
-    $scope.jobs_fetch = function() {
-        $http.get("jobs")
-            .then(function success(result) {
-                $scope.jobs = result.data;
-            });
-    }
-    $scope.jobs_fetch();
-});
-
-angular.module('zuulBuilds', [], function($locationProvider) {
-    $locationProvider.html5Mode({
-        enabled: true,
-        requireBase: false
-    });
-}).controller('mainController', function($scope, $http, $location)
-{
-    $scope.rowClass = function(build) {
-        if (build.result == "SUCCESS") {
-            return "success";
-        } else {
-            return "warning";
-        }
-    };
-    var query_args = $location.search();
-    var url = $location.url();
-    var tenant_start = url.lastIndexOf(
-        '/', url.lastIndexOf('/builds.html') - 1) + 1;
-    var tenant_length = url.lastIndexOf('/builds.html') - tenant_start;
-    $scope.tenant = url.substr(tenant_start, tenant_length);
-    $scope.builds = undefined;
-    if (query_args["pipeline"]) {$scope.pipeline = query_args["pipeline"];
-    } else {$scope.pipeline = "";}
-    if (query_args["job_name"]) {$scope.job_name = query_args["job_name"];
-    } else {$scope.job_name = "";}
-    if (query_args["project"]) {$scope.project = query_args["project"];
-    } else {$scope.project = "";}
-    $scope.builds_fetch = function() {
-        query_string = "";
-        if ($scope.tenant) {query_string += "&tenant="+$scope.tenant;}
-        if ($scope.pipeline) {query_string += "&pipeline="+$scope.pipeline;}
-        if ($scope.job_name) {query_string += "&job_name="+$scope.job_name;}
-        if ($scope.project) {query_string += "&project="+$scope.project;}
-        if (query_string != "") {query_string = "?" + query_string.substr(1);}
-        $http.get("builds" + query_string)
-            .then(function success(result) {
-                for (build_pos = 0;
-                     build_pos < result.data.length;
-                     build_pos += 1) {
-                    build = result.data[build_pos]
-                    if (build.node_name == null) {
-                        build.node_name = 'master'
-                    }
-                    /* Fix incorect url for post_failure job */
-                    if (build.log_url == build.job_name) {
-                        build.log_url = undefined;
-                    }
-                }
-                $scope.builds = result.data;
-            });
-    }
-    $scope.builds_fetch()
-});
diff --git a/zuul/web/static/javascripts/zuul.app.js b/zuul/web/static/javascripts/zuul.app.js
deleted file mode 100644
index 6e35eb3..0000000
--- a/zuul/web/static/javascripts/zuul.app.js
+++ /dev/null
@@ -1,108 +0,0 @@
-// Client script for Zuul status page
-//
-// @licstart  The following is the entire license notice for the
-// JavaScript code in this page.
-//
-// Copyright 2013 OpenStack Foundation
-// Copyright 2013 Timo Tijhof
-// Copyright 2013 Wikimedia Foundation
-// Copyright 2014 Rackspace Australia
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-//
-// @licend  The above is the entire license notice
-// for the JavaScript code in this page.
-
-/*exported zuul_build_dom, zuul_start */
-
-function zuul_build_dom($, container) {
-    // Build a default-looking DOM
-    var default_layout = '<div class="container">'
-        + '<div class="zuul-container" id="zuul-container">'
-        + '<div style="display: none;" class="alert" id="zuul_msg"></div>'
-        + '<button class="btn pull-right zuul-spinner">updating <span class="glyphicon glyphicon-refresh"></span></button>'
-        + '<p>Queue lengths: <span id="zuul_queue_events_num">0</span> events, <span id="zuul_queue_management_events_num">0</span> management events, <span id="zuul_queue_results_num">0</span> results.</p>'
-        + '<div id="zuul_controls"></div>'
-        + '<div id="zuul_pipelines" class="row"></div>'
-        + '<p>Zuul version: <span id="zuul-version-span"></span></p>'
-        + '<p>Last reconfigured: <span id="last-reconfigured-span"></span></p>'
-        + '</div></div>';
-
-    $(function ($) {
-        // DOM ready
-        var $container = $(container);
-        $container.html(default_layout);
-    });
-}
-
-/**
- * @return The $.zuul instance
- */
-function zuul_start($) {
-    // Start the zuul app (expects default dom)
-
-    var $container, $indicator;
-    var demo = location.search.match(/[?&]demo=([^?&]*)/),
-        source_url = location.search.match(/[?&]source_url=([^?&]*)/),
-        source = demo ? './status-' + (demo[1] || 'basic') + '.json-sample' :
-            'status';
-    source = source_url ? source_url[1] : source;
-
-    var zuul = $.zuul({
-        source: source,
-        //graphite_url: 'http://graphite.openstack.org/render/'
-    });
-
-    zuul.jq.on('update-start', function () {
-        $container.addClass('zuul-container-loading');
-        $indicator.addClass('zuul-spinner-on');
-    });
-
-    zuul.jq.on('update-end', function () {
-        $container.removeClass('zuul-container-loading');
-        setTimeout(function () {
-            $indicator.removeClass('zuul-spinner-on');
-        }, 500);
-    });
-
-    zuul.jq.one('update-end', function () {
-        // Do this asynchronous so that if the first update adds a
-        // message, it will not animate while we fade in the content.
-        // Instead it simply appears with the rest of the content.
-        setTimeout(function () {
-            // Fade in the content
-            $container.addClass('zuul-container-ready');
-        });
-    });
-
-    $(function ($) {
-        // DOM ready
-        $container = $('#zuul-container');
-        $indicator = $('#zuul-spinner');
-        $('#zuul_controls').append(zuul.app.control_form());
-
-        zuul.app.schedule();
-
-        $(document).on({
-            'show.visibility': function () {
-                zuul.options.enabled = true;
-                zuul.app.update();
-            },
-            'hide.visibility': function () {
-                zuul.options.enabled = false;
-            }
-        });
-    });
-
-    return zuul;
-}
diff --git a/zuul/web/static/status.html b/zuul/web/static/status.html
deleted file mode 100644
index 8471fd1..0000000
--- a/zuul/web/static/status.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!--
-Copyright 2013 OpenStack Foundation
-Copyright 2013 Timo Tijhof
-Copyright 2013 Wikimedia Foundation
-
-Licensed under the Apache License, Version 2.0 (the "License"); you may
-not use this file except in compliance with the License. You may obtain
-a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations
-under the License.
--->
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Zuul Status</title>
-  <link rel="stylesheet" href="../static/bootstrap/css/bootstrap.min.css">
-  <link rel="stylesheet" href="../static/styles/zuul.css" />
-  <script src="../static/js/jquery.min.js"></script>
-  <script src="../static/js/jquery-visibility.min.js"></script>
-  <script src="../static/js/jquery.graphite.min.js"></script>
-  <script src="../static/javascripts/jquery.zuul.js"></script>
-  <script src="../static/javascripts/zuul.app.js"></script>
-</head>
-<body>
-  <nav class="navbar navbar-default">
-  <div class="container-fluid">
-    <div class="navbar-header">
-      <a class="navbar-brand" href="../" target="_self">Zuul Dashboard</a>
-    </div>
-    <ul class="nav navbar-nav">
-      <li class="active"><a href="status.html" target="_self">Status</a></li>
-      <li><a href="jobs.html" target="_self">Jobs</a></li>
-      <li><a href="builds.html" target="_self">Builds</a></li>
-    </ul>
-  </div>
-  </nav>
-  <div id="zuul_container"></div>
-  <script>
-    // @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7&dn=apache-2.0.txt Apache 2.0
-    zuul_build_dom(jQuery, '#zuul_container');
-    zuul_start(jQuery);
-    // @license-end
-  </script>
-</body>
-</html>
diff --git a/zuul/web/static/stream.html b/zuul/web/static/stream.html
deleted file mode 100644
index f2e7081..0000000
--- a/zuul/web/static/stream.html
+++ /dev/null
@@ -1,114 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-   "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-  <head>
-      <style type="text/css">
-
-        body {
-          font-family: monospace;
-          background-color: black;
-          color: lightgrey;
-        }
-
-        #overlay {
-            position: fixed;
-            top: 5px;
-            right: 5px;
-            background-color: darkgrey;
-            color: black;
-        }
-
-        pre {
-            white-space: pre;
-            margin: 0px 10px;
-        }
-      </style>
-
-    <script type="text/javascript">
-
-      function escapeLog(text) {
-          var pattern = /[<>&"']/g;
-
-          return text.replace(pattern, function(match) {
-              return '&#' + match.charCodeAt(0) + ';';
-          });
-      }
-
-      window.onload = function() {
-
-          pageUpdateInMS = 250;
-          var receiveBuffer = "";
-          var websocket_url = null
-
-          setInterval(function() {
-              console.log("autoScroll");
-              if (receiveBuffer != "") {
-                  document.getElementById('pagecontent').innerHTML += receiveBuffer;
-                  receiveBuffer = "";
-                  if (document.getElementById('autoscroll').checked) {
-                      window.scrollTo(0, document.body.scrollHeight);
-                  }
-              }
-          }, pageUpdateInMS);
-
-          var url = new URL(window.location);
-
-          var params = {
-              uuid: url.searchParams.get('uuid')
-          }
-          document.getElementById('pagetitle').innerHTML = params['uuid'];
-          if (url.searchParams.has('logfile')) {
-              params['logfile'] = url.searchParams.get('logfile');
-              var logfile_suffix = "(" + params['logfile'] + ")";
-              document.getElementById('pagetitle').innerHTML += logfile_suffix;
-          }
-          if (url.searchParams.has('websocket_url')) {
-              params['websocket_url'] = url.searchParams.get('websocket_url');
-          } else {
-              // Websocket doesn't accept relative urls so construct an
-              // absolute one.
-              var protocol = '';
-              if (url['protocol'] == 'https:') {
-                  protocol = 'wss://';
-              } else {
-                  protocol = 'ws://';
-              }
-              path = url['pathname'].replace(/stream.html.*$/g, '') + 'console-stream';
-              params['websocket_url'] = protocol + url['host'] + path;
-          }
-          var ws = new WebSocket(params['websocket_url']);
-
-          ws.onmessage = function(event) {
-              console.log("onmessage");
-              receiveBuffer = receiveBuffer + escapeLog(event.data);
-          };
-
-          ws.onopen = function(event) {
-              console.log("onopen");
-              ws.send(JSON.stringify(params));
-          };
-
-          ws.onclose = function(event) {
-              console.log("onclose");
-              receiveBuffer = receiveBuffer + "\n--- END OF STREAM ---\n";
-          };
-
-      };
-
-    </script>
-
-    <title id="pagetitle"></title>
-  </head>
-
-  <body>
-
-    <div id="overlay">
-      <form>
-        <input type="checkbox" id="autoscroll" checked> autoscroll
-      </form>
-    </div>
-
-    <pre id="pagecontent"></pre>
-
-  </body>
-</html>
diff --git a/zuul/web/static/styles/zuul.css b/zuul/web/static/styles/zuul.css
deleted file mode 100644
index 44fd737..0000000
--- a/zuul/web/static/styles/zuul.css
+++ /dev/null
@@ -1,58 +0,0 @@
-.zuul-change {
-    margin-bottom: 10px;
-}
-
-.zuul-change-id {
-    float: right;
-}
-
-.zuul-job-result {
-    float: right;
-    width: 70px;
-    height: 15px;
-    margin: 2px 0 0 0;
-}
-
-.zuul-change-total-result {
-    height: 10px;
-    width: 100px;
-    margin: 0;
-    display: inline-block;
-    vertical-align: middle;
-}
-
-.zuul-spinner,
-.zuul-spinner:hover {
-    opacity: 0;
-    transition: opacity 0.5s ease-out;
-    cursor: default;
-    pointer-events: none;
-}
-
-.zuul-spinner-on,
-.zuul-spinner-on:hover {
-    opacity: 1;
-    transition-duration: 0.2s;
-    cursor: progress;
-}
-
-.zuul-change-cell {
-    padding-left: 5px;
-}
-
-.zuul-change-job {
-    padding: 2px 8px;
-}
-
-.zuul-job-name {
-    font-size: small;
-}
-
-.zuul-non-voting-desc {
-    font-size: smaller;
-}
-
-.zuul-patchset-header {
-    font-size: small;
-    padding: 8px 12px;
-}
\ No newline at end of file