diff --git a/.gitignore b/.gitignore
index a5199a571..c66028864 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
*.pyc
-*.egg-info
\ No newline at end of file
+*.egg-info
+*node_modules
+.history
+settings.json
+jupyter_geppetto/*.js
+jupyter_geppetto/*.js.map
+*.DS_Store
\ No newline at end of file
diff --git a/README.md b/README.md
index 21c8925b8..2df68e5c3 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,177 @@
-
+
# Geppetto Jupyter Notebook Extension
-This is an experimental repo for a Jupyter notebook extension. This extension extends Jupyter Python server based on tornado that allows the client to establish a websocket connection and server static resources.
+This is an experimental repo for a Jupyter notebook [extension](https://ipython.readthedocs.io/en/stable/config/extensions/).
+This extension enables the Jupyter Python server based
+on tornado that allows the client to establish a websocket connection and serve static resources.
-How to install:
+Other than serving the application as a Geppetto backend, Jupyter Geppetto allows, by embedding a notebook in the page,
+to interact with the notebook and synchronize frontend features with the notebook.
+
+## How to install
+
+Before installing, it is recommended to activate a Python 3 virtual environment:
+```bash
+python3 -m venv jupyter-geppetto
+source jupyter-geppetto/bin/activate
+```
+
+Or, with conda
+
+```bash
+conda create -n jupyter-geppetto python=3.7
+conda activate jupyter-geppetto
```
+
+Install with pip
+```bash
pip install jupyter_geppetto
jupyter nbextension enable --py --sys-prefix jupyter_geppetto
```
-How to install extension from sources:
-```
+Install extension from sources
+```bash
git clone --recursive https://github.com/openworm/org.geppetto.frontend.jupyter.git
pip install .
-jupyter nbextension install --py jupyter_geppetto
-jupyter nbextension enable --py jupyter_geppetto
-```
-To overwrite the local install:
+
+jupyter nbextension install --py --symlink --sys-prefix jupyter_geppetto
+jupyter nbextension enable --py --sys-prefix jupyter_geppetto
+jupyter serverextension enable --py --sys-prefix jupyter_geppetto
```
+## Overwrite the local install
+```bash
pip install . --upgrade --no-deps --force-reinstall
```
+Notice: old installs made without --sys-prefix (so )
+
+## How to run
+After the extension is installed the Jupyter notebook must be run with the parameter --library, which specifies the
+Python libraries to be loaded together with the extension:
+```bash
+exec jupyter notebook --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=my_geppetto_application_lib
+```
To connect go to the URL:
http://localhost:8888/geppetto
-assuming the default Jupyter configuration, otherwise change port accordingly.
+assuming the default Jupyter configuration, otherwise change the port accordingly.
Note if you get a 404 and you have a custom configuration of Jupyter notebook you will have to add the following to your jupyter_notebook_config.py:
```
c.NotebookApp.nbserver_extensions = {'jupyter_geppetto':True}
```
+
+
+# Development
+
+Jupyter Geppetto serves In order to use the synchronization capability,
+
+## Geppetto websocket api
+Jupyter Geppetto implements the websocket api through a Tornado handler. It supports the messages coming from
+a [geppetto-application](https://github.com/openworm/geppetto-application) frontend. See
+[geppetto-client](https://github.com/openworm/geppetto-client) for the available messages and implementation.
+
+Currently, only a subset of the messages is supported. For further information, see the current release of
+[pygeppetto](https://github.com/openworm/pygeppetto).
+
+## Web api
+Allows to add own custom routes and handlers from inside the application.
+The dependencies must be added from within the libraries specified in the parameter --library
+
+In the file root of your module (__init__.py of your package), call the RouteManager methods to add your custom routes:
+```python
+from jupyter_geppetto.webapi import RouteManager
+
+RouteManager.add_controller(MyController) # Add a controller (preferred way for http requests)
+RouteManager.add_route('/my/path', MyTornadoHandler) # for more custom control
+```
+
+A controller class is a standard class with webapi annotations on methods.
+Methods return the response as a string.
+The RouteManager creates a handler for each method and binds the method with the handler.
+
+Example:
+```Python
+from jupyter_geppetto.webapi import get, post
+
+class MyController:
+
+ @get('/my/simple/path')
+ def simple_action(handler):
+ return "My response payload" # Simple text response
+
+ @get('/myresource/(.*)')
+ def action_with_url_param(handler, param):
+ import json
+ return json.dumps({'param':param}) # JSON response
+
+ @get('/myresource')
+ def action_with_query_string_params(handler, param1, param2=None):
+ '''Handles
+ /myresource?param1=something¶m2=somethingelse
+ /myresource?param1=something
+ '''
+ return ...
+
+ @get('/myresource1')
+ def alt_action_with_query_string_params(handler, **kwargs):
+ '''Handles any query string parameter'''
+ return ...
+
+ @get('/myresource1/(.*)')
+ def action_with_url_and_query_string_params(handler, param, param1, param2):
+ '''Handles /myresource?param1=comething¶m2=somethingelse'''
+ return ...
+
+ @post('/myresource2')
+ def simple_post_action(handler, payload, param1, param2):
+ '''Handles /myresource and body param1=something¶m2=somethingelse'''
+ return ...
+
+ @get('/myresource3', {'Content-type': 'image/png', 'Cache-Control': 'max-age=600'})
+ def get_action_with_headers(handler):
+ '''Sets headers'''
+ return ...
+
+ @get('/myresource3')
+ def get_action_use_handler(handler):
+ '''The first parameter is the tornado handler'''
+ handler.write('Whatever')
+ return ...
+```
+
+## Iframe embedding
+In the frontend, it is required to embed an iframe with a jupyter notebook.
+
+Example
+```javascript
+import PythonConsole from 'geppetto-client/js/components/interface/pythonConsole/PythonConsole';
+
+// Inside your React component render:
+
+```
+
+## Synchronization
+This feature allows to synchronize backend and frontend objects. In order to use synchronization, it is required to have
+the iframe embed enabled and initialized.
+It's implemented through a [IPython/Jupyter widget](https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Basics.html).
+On the JS side, the connection is achieved through the PythonControlledCapability of the [Geppetto client](https://github.com/openworm/geppetto-client/).
+
+
+Usage
+```python
+from jupyter_geppetto import synchronization
+class MyClass:
+ def a(self):
+ ...
+ def b(self):
+ ...
+synchronization.startSynchronization(MyClass().__dict__)
+
+```
+
+## Deployment
+An application based on Jupyter Geppetto can be deployed as a standard jupyter notebook application.
+It is recommended a dockerized setup with JupyterHub (e.g. on Kubernetes).
+
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/js/package-lock.json b/js/package-lock.json
index 4a3bc6f4f..b9d9dc010 100644
--- a/js/package-lock.json
+++ b/js/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "org.geppetto.frontend.jupyter",
- "version": "0.4.1",
+ "version": "0.4.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -25,7 +25,7 @@
"@jupyterlab/coreutils": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-2.2.1.tgz",
- "integrity": "sha512-XkGMBXqEAnENC4fK/L3uEqqxyNUtf4TI/1XNDln7d5VOPHQJSBTbYlBAZ0AQotn2qbs4WqmV6icxje2ITVedqQ==",
+ "integrity": "sha1-wnHq8vbkaHV7qWYPJL08Pl1v5YM=",
"dev": true,
"requires": {
"@phosphor/algorithm": "^1.1.2",
@@ -43,7 +43,7 @@
"@jupyterlab/observables": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-2.1.1.tgz",
- "integrity": "sha512-PzmJ/jF5fWzHCvjPAWBi3YjtHRAF0bwyjpd8W8aJt64TzhEZh0se8xCNGOURzD+8TxOsTF9JpQ9wIDBr4V226Q==",
+ "integrity": "sha1-xditKVxbC86RSmB6NCsK9FULIYc=",
"dev": true,
"requires": {
"@phosphor/algorithm": "^1.1.2",
@@ -56,7 +56,7 @@
"@jupyterlab/services": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-3.2.1.tgz",
- "integrity": "sha512-zCMruGGYxTe427ESK4YUO1V/liFOFYpebYPRsJ+j9CFdV+Hm760+nx4pFX6N6Z9TbS+5cs8BgZ+ebm8unRZrJg==",
+ "integrity": "sha1-6Nkyntc/eUkJ94bSLF6UsHvrBBs=",
"dev": true,
"requires": {
"@jupyterlab/coreutils": "^2.2.1",
@@ -85,7 +85,7 @@
"@phosphor/commands": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@phosphor/commands/-/commands-1.6.1.tgz",
- "integrity": "sha512-iRgn7QX64e0VwZ91KFo964a/LVpw9XtiYIYtpymEyKY757NXvx6ZZMt1CqKfntoDcSZJeVte4eV8jJWhZoVlDA==",
+ "integrity": "sha1-b2DCo7dZMWzRNjtCbfO0A2uyx/0=",
"dev": true,
"requires": {
"@phosphor/algorithm": "^1.1.2",
@@ -170,7 +170,7 @@
"@phosphor/widgets": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@phosphor/widgets/-/widgets-1.6.0.tgz",
- "integrity": "sha512-HqVckVF8rJ15ss0Zf/q0AJ69ZKNFOO26qtNKAdGZ9SmmkSMf73X6pB0R3Fj5+Y4Sjl8ezIIKG6mXj+DxOofnwA==",
+ "integrity": "sha1-67qACLaxMkfQPnPl84cskNLJx48=",
"dev": true,
"requires": {
"@phosphor/algorithm": "^1.1.2",
@@ -214,7 +214,7 @@
"@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
- "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
+ "integrity": "sha1-qBG4wY4rq6t9VCszZYh64uTZ3kc=",
"dev": true
},
"@types/underscore": {
@@ -236,7 +236,7 @@
"acorn": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
- "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=",
"dev": true
},
"acorn-dynamic-import": {
@@ -311,7 +311,7 @@
"anymatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=",
"dev": true,
"requires": {
"micromatch": "^3.1.4",
@@ -321,7 +321,7 @@
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
@@ -336,7 +336,7 @@
"arr-flatten": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
- "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
"dev": true
},
"arr-union": {
@@ -392,7 +392,7 @@
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
- "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=",
"dev": true,
"optional": true,
"requires": {
@@ -402,7 +402,7 @@
"asn1.js": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
- "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=",
"dev": true,
"requires": {
"bn.js": "^4.0.0",
@@ -474,7 +474,7 @@
"atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=",
"dev": true
},
"autoprefixer": {
@@ -501,7 +501,7 @@
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
- "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=",
"dev": true,
"optional": true
},
@@ -534,7 +534,7 @@
"base": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
- "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
"dev": true,
"requires": {
"cache-base": "^1.0.1",
@@ -558,7 +558,7 @@
"is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -567,7 +567,7 @@
"is-data-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -576,7 +576,7 @@
"is-descriptor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
"dev": true,
"requires": {
"is-accessor-descriptor": "^1.0.0",
@@ -587,7 +587,7 @@
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"dev": true
}
}
@@ -595,7 +595,7 @@
"base64-js": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
- "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
+ "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=",
"dev": true
},
"batch": {
@@ -629,7 +629,7 @@
"bn.js": {
"version": "4.11.8",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
- "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+ "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=",
"dev": true
},
"body-parser": {
@@ -669,6 +669,7 @@
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
"dev": true,
+ "optional": true,
"requires": {
"hoek": "2.x.x"
}
@@ -676,7 +677,7 @@
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
@@ -686,7 +687,7 @@
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
"dev": true,
"requires": {
"arr-flatten": "^1.1.0",
@@ -735,7 +736,7 @@
"browserify-cipher": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
- "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=",
"dev": true,
"requires": {
"browserify-aes": "^1.0.4",
@@ -746,7 +747,7 @@
"browserify-des": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
- "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=",
"dev": true,
"requires": {
"cipher-base": "^1.0.1",
@@ -783,7 +784,7 @@
"browserify-zlib": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
- "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
"dev": true,
"requires": {
"pako": "~1.0.5"
@@ -813,7 +814,7 @@
"buffer-indexof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
- "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+ "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=",
"dev": true
},
"buffer-xor": {
@@ -843,7 +844,7 @@
"cache-base": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
- "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
"dev": true,
"requires": {
"collection-visit": "^1.0.0",
@@ -943,7 +944,7 @@
"cipher-base": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
- "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
"dev": true,
"requires": {
"inherits": "^2.0.1",
@@ -953,7 +954,7 @@
"clap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz",
- "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==",
+ "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=",
"dev": true,
"requires": {
"chalk": "^1.1.3"
@@ -962,7 +963,7 @@
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
- "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
"dev": true,
"requires": {
"arr-union": "^3.1.0",
@@ -1052,7 +1053,7 @@
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
"dev": true,
"requires": {
"color-name": "1.1.3"
@@ -1093,8 +1094,9 @@
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
- "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+ "integrity": "sha1-LR0kMXr7ir6V1tLAsHtXgTU52Cg=",
"dev": true,
+ "optional": true,
"requires": {
"delayed-stream": "~1.0.0"
}
@@ -1126,7 +1128,7 @@
"compression": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz",
- "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==",
+ "integrity": "sha1-J+DhdqryYPfywoE8PkQK258Zk9s=",
"dev": true,
"requires": {
"accepts": "~1.3.5",
@@ -1174,7 +1176,7 @@
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
"dev": true
},
"cookie": {
@@ -1204,7 +1206,7 @@
"create-ecdh": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
- "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
@@ -1262,7 +1264,7 @@
"crypto-browserify": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
- "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=",
"dev": true,
"requires": {
"browserify-cipher": "^1.0.0",
@@ -1287,7 +1289,7 @@
"css-loader": {
"version": "0.28.7",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz",
- "integrity": "sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==",
+ "integrity": "sha1-Xy7pid0y7dkHcX+VMxdlYWCZnBs=",
"dev": true,
"requires": {
"babel-code-frame": "^6.11.0",
@@ -1410,7 +1412,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"dev": true,
"requires": {
"ms": "2.0.0"
@@ -1437,7 +1439,7 @@
"default-gateway": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz",
- "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==",
+ "integrity": "sha1-t+8znl4CSwRUZ69APVA0jbRkLQ8=",
"dev": true,
"requires": {
"execa": "^0.10.0",
@@ -1447,7 +1449,7 @@
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
@@ -1460,7 +1462,7 @@
"execa": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
- "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "integrity": "sha1-/0Vqj1P5D47MxxqW0Rvfx/CCy1A=",
"dev": true,
"requires": {
"cross-spawn": "^6.0.0",
@@ -1477,7 +1479,7 @@
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=",
"dev": true,
"requires": {
"object-keys": "^1.0.12"
@@ -1486,7 +1488,7 @@
"define-property": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=",
"dev": true,
"requires": {
"is-descriptor": "^1.0.2",
@@ -1496,7 +1498,7 @@
"is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -1505,7 +1507,7 @@
"is-data-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -1514,7 +1516,7 @@
"is-descriptor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
"dev": true,
"requires": {
"is-accessor-descriptor": "^1.0.0",
@@ -1525,7 +1527,7 @@
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"dev": true
}
}
@@ -1562,7 +1564,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"depd": {
"version": "1.1.2",
@@ -1589,7 +1592,7 @@
"detect-node": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
- "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+ "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=",
"dev": true
},
"diffie-hellman": {
@@ -1612,7 +1615,7 @@
"dns-packet": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
- "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=",
"dev": true,
"requires": {
"ip": "^1.1.0",
@@ -1631,7 +1634,7 @@
"domain-browser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
- "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=",
"dev": true
},
"ecc-jsbn": {
@@ -1660,7 +1663,7 @@
"elliptic": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
- "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
+ "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=",
"dev": true,
"requires": {
"bn.js": "^4.4.0",
@@ -1699,7 +1702,7 @@
"errno": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
- "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=",
"dev": true,
"requires": {
"prr": "~1.0.1"
@@ -1708,7 +1711,7 @@
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=",
"dev": true,
"requires": {
"is-arrayish": "^0.2.1"
@@ -1730,7 +1733,7 @@
"es-to-primitive": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
- "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=",
"dev": true,
"requires": {
"is-callable": "^1.1.4",
@@ -1842,7 +1845,7 @@
"esrecurse": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
- "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=",
"dev": true,
"requires": {
"estraverse": "^4.1.0"
@@ -1879,7 +1882,7 @@
"eventemitter3": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
- "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
+ "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=",
"dev": true
},
"events": {
@@ -1900,7 +1903,7 @@
"evp_bytestokey": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
- "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=",
"dev": true,
"requires": {
"md5.js": "^1.3.4",
@@ -1969,7 +1972,7 @@
"fill-range": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
- "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
+ "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=",
"dev": true,
"requires": {
"is-number": "^2.1.0",
@@ -2054,7 +2057,7 @@
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=",
"dev": true,
"optional": true
},
@@ -2071,7 +2074,7 @@
"is-extendable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
"dev": true,
"requires": {
"is-plain-object": "^2.0.4"
@@ -2082,7 +2085,7 @@
"extglob": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=",
"dev": true,
"requires": {
"array-unique": "^0.3.2",
@@ -2116,7 +2119,7 @@
"is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -2125,7 +2128,7 @@
"is-data-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -2134,7 +2137,7 @@
"is-descriptor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
"dev": true,
"requires": {
"is-accessor-descriptor": "^1.0.0",
@@ -2145,7 +2148,7 @@
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"dev": true
}
}
@@ -2154,7 +2157,8 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"fastparse": {
"version": "1.1.1",
@@ -2747,7 +2751,8 @@
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -2847,25 +2852,27 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=",
"dev": true
},
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=",
"dev": true
},
"get-stream": {
@@ -2902,7 +2909,7 @@
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
- "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
@@ -3029,7 +3036,7 @@
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
@@ -3136,12 +3143,13 @@
"version": "2.16.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"hosted-git-info": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
- "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+ "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=",
"dev": true
},
"hpack.js": {
@@ -3159,7 +3167,7 @@
"html-comment-regex": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
- "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==",
+ "integrity": "sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c=",
"dev": true
},
"html-entities": {
@@ -3195,7 +3203,7 @@
"http-proxy": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
- "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+ "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=",
"dev": true,
"requires": {
"eventemitter3": "^3.0.0",
@@ -3358,7 +3366,7 @@
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
@@ -3384,7 +3392,7 @@
"postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
- "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -3395,13 +3403,13 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
@@ -3412,7 +3420,7 @@
"ieee754": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
- "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==",
+ "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=",
"dev": true
},
"image-size": {
@@ -3453,7 +3461,7 @@
"internal-ip": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-2.0.3.tgz",
- "integrity": "sha512-XxJMiJOjXbb9LlwH6SVTsnUPymYACunXzKg3dqU+HIC+xYIkUhMyTiT/H6xxPmhlE4zHq50lKlx0CZlyN2C76Q==",
+ "integrity": "sha1-7Tz5tnGsf/IwN7+srULrQ5zZVGw=",
"dev": true,
"requires": {
"default-gateway": "^2.2.2",
@@ -3523,7 +3531,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
"dev": true
},
"is-builtin-module": {
@@ -3538,7 +3546,7 @@
"is-callable": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
- "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=",
"dev": true
},
"is-data-descriptor": {
@@ -3559,7 +3567,7 @@
"is-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
"dev": true,
"requires": {
"is-accessor-descriptor": "^0.1.6",
@@ -3570,7 +3578,7 @@
"kind-of": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
"dev": true
}
}
@@ -3638,7 +3646,7 @@
"is-path-in-cwd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
- "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+ "integrity": "sha1-WsSLNF72dTOb1sekipEhELJBz1I=",
"dev": true,
"requires": {
"is-path-inside": "^1.0.0"
@@ -3662,7 +3670,7 @@
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
- "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
"dev": true,
"requires": {
"isobject": "^3.0.1"
@@ -3707,7 +3715,7 @@
"is-symbol": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
- "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=",
"dev": true,
"requires": {
"has-symbols": "^1.0.0"
@@ -3729,7 +3737,7 @@
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
- "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=",
"dev": true
},
"is-wsl": {
@@ -3766,7 +3774,7 @@
"jquery": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
- "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==",
+ "integrity": "sha1-lYzinoHJeQ8xvneS311NlfxX+8o=",
"dev": true
},
"js-base64": {
@@ -3807,7 +3815,7 @@
"json-loader": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
- "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==",
+ "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=",
"dev": true
},
"json-parser": {
@@ -3915,7 +3923,7 @@
"less": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz",
- "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==",
+ "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=",
"dev": true,
"requires": {
"errno": "^0.1.1",
@@ -3981,7 +3989,7 @@
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+ "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=",
"dev": true
},
"lodash.camelcase": {
@@ -4060,7 +4068,7 @@
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
- "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=",
"dev": true,
"requires": {
"hash-base": "^3.0.0",
@@ -4108,7 +4116,7 @@
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
"dev": true,
"requires": {
"arr-diff": "^4.0.0",
@@ -4129,7 +4137,7 @@
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"dev": true
}
}
@@ -4137,7 +4145,7 @@
"miller-rabin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
- "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=",
"dev": true,
"requires": {
"bn.js": "^4.0.0",
@@ -4168,13 +4176,13 @@
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
- "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=",
"dev": true
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=",
"dev": true
},
"minimalistic-crypto-utils": {
@@ -4186,7 +4194,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
@@ -4201,7 +4209,7 @@
"mixin-deep": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
- "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+ "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=",
"dev": true,
"requires": {
"for-in": "^1.0.2",
@@ -4211,7 +4219,7 @@
"is-extendable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
"dev": true,
"requires": {
"is-plain-object": "^2.0.4"
@@ -4251,7 +4259,7 @@
"multicast-dns": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
- "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=",
"dev": true,
"requires": {
"dns-packet": "^1.3.1",
@@ -4274,7 +4282,7 @@
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
- "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=",
"dev": true,
"requires": {
"arr-diff": "^4.0.0",
@@ -4293,7 +4301,7 @@
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"dev": true
}
}
@@ -4319,13 +4327,13 @@
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=",
"dev": true
},
"node-forge": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
- "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
+ "integrity": "sha1-bBUsNFzhHFL0ZcKr2VfoY5zWdN8=",
"dev": true
},
"node-libs-browser": {
@@ -4491,7 +4499,7 @@
"obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
- "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=",
"dev": true
},
"on-finished": {
@@ -4521,7 +4529,7 @@
"opn": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz",
- "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==",
+ "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=",
"dev": true,
"requires": {
"is-wsl": "^1.1.0"
@@ -4530,7 +4538,7 @@
"original": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
- "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=",
"dev": true,
"requires": {
"url-parse": "^1.4.3"
@@ -4545,7 +4553,7 @@
"os-locale": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
- "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
"dev": true,
"requires": {
"execa": "^0.7.0",
@@ -4562,7 +4570,7 @@
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=",
"dev": true,
"requires": {
"p-try": "^1.0.0"
@@ -4580,7 +4588,7 @@
"p-map": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
- "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "integrity": "sha1-5OlPMR6rvIYzoeeZCBZfyiYkG2s=",
"dev": true
},
"p-try": {
@@ -4718,7 +4726,7 @@
"pbkdf2": {
"version": "3.0.17",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
- "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+ "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=",
"dev": true,
"requires": {
"create-hash": "^1.1.2",
@@ -4784,7 +4792,7 @@
"postcss": {
"version": "5.2.18",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
- "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=",
"dev": true,
"requires": {
"chalk": "^1.1.3",
@@ -4891,7 +4899,7 @@
"postcss-filter-plugins": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz",
- "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==",
+ "integrity": "sha1-giRf34IzcEFkXkdxFNjlk6oYuOw=",
"dev": true,
"requires": {
"postcss": "^5.0.4"
@@ -5057,7 +5065,7 @@
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
@@ -5083,7 +5091,7 @@
"postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
- "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -5094,13 +5102,13 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
@@ -5121,7 +5129,7 @@
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
@@ -5147,7 +5155,7 @@
"postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
- "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -5158,13 +5166,13 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
@@ -5185,7 +5193,7 @@
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
@@ -5211,7 +5219,7 @@
"postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
- "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -5222,13 +5230,13 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
@@ -5369,13 +5377,13 @@
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
- "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=",
"dev": true
},
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
- "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
"dev": true,
"optional": true,
"requires": {
@@ -5385,7 +5393,7 @@
"proxy-addr": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
- "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+ "integrity": "sha1-7PxzO/Iv+Mb0B/onUye5q2fki5M=",
"dev": true,
"requires": {
"forwarded": "~0.1.2",
@@ -5407,7 +5415,7 @@
"public-encrypt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
- "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
@@ -5501,7 +5509,7 @@
"randomfill": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
- "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=",
"dev": true,
"requires": {
"randombytes": "^2.0.5",
@@ -5591,7 +5599,7 @@
"readdirp": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.11",
@@ -5638,13 +5646,13 @@
"regenerate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
- "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
+ "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=",
"dev": true
},
"regex-cache": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
- "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=",
"dev": true,
"requires": {
"is-equal-shallow": "^0.1.3"
@@ -5653,7 +5661,7 @@
"regex-not": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
- "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=",
"dev": true,
"requires": {
"extend-shallow": "^3.0.2",
@@ -5695,7 +5703,7 @@
"repeat-element": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
- "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=",
"dev": true
},
"repeat-string": {
@@ -5778,7 +5786,7 @@
"ret": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
- "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=",
"dev": true
},
"right-align": {
@@ -5802,7 +5810,7 @@
"ripemd160": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
- "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=",
"dev": true,
"requires": {
"hash-base": "^3.0.0",
@@ -5812,7 +5820,7 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=",
"dev": true
},
"safe-regex": {
@@ -5827,13 +5835,14 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
+ "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
+ "dev": true,
+ "optional": true
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=",
"dev": true
},
"select-hose": {
@@ -5860,7 +5869,7 @@
"send": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
- "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+ "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=",
"dev": true,
"requires": {
"debug": "2.6.9",
@@ -5896,7 +5905,7 @@
"serve-static": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
- "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+ "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=",
"dev": true,
"requires": {
"encodeurl": "~1.0.2",
@@ -5914,7 +5923,7 @@
"set-value": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
- "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=",
"dev": true,
"requires": {
"extend-shallow": "^2.0.1",
@@ -5943,7 +5952,7 @@
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
- "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=",
"dev": true
},
"sha.js": {
@@ -5980,7 +5989,7 @@
"snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=",
"dev": true,
"requires": {
"base": "^0.11.1",
@@ -6016,7 +6025,7 @@
"snapdragon-node": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
- "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
"dev": true,
"requires": {
"define-property": "^1.0.0",
@@ -6036,7 +6045,7 @@
"is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -6045,7 +6054,7 @@
"is-data-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
"dev": true,
"requires": {
"kind-of": "^6.0.0"
@@ -6054,7 +6063,7 @@
"is-descriptor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
"dev": true,
"requires": {
"is-accessor-descriptor": "^1.0.0",
@@ -6065,7 +6074,7 @@
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"dev": true
}
}
@@ -6073,7 +6082,7 @@
"snapdragon-util": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
- "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
"dev": true,
"requires": {
"kind-of": "^3.2.0"
@@ -6148,7 +6157,7 @@
"source-map-resolve": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
- "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=",
"dev": true,
"requires": {
"atob": "^2.1.1",
@@ -6177,13 +6186,13 @@
"spdx-exceptions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
- "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=",
"dev": true
},
"spdx-expression-parse": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
- "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=",
"dev": true,
"requires": {
"spdx-exceptions": "^2.1.0",
@@ -6228,7 +6237,7 @@
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
- "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
"dev": true,
"requires": {
"extend-shallow": "^3.0.0"
@@ -6291,7 +6300,7 @@
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
- "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+ "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=",
"dev": true
},
"stream-browserify": {
@@ -6307,7 +6316,7 @@
"stream-http": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
- "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=",
"dev": true,
"requires": {
"builtin-status-codes": "^3.0.0",
@@ -6326,7 +6335,7 @@
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
- "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
@@ -6359,7 +6368,7 @@
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
@@ -6368,7 +6377,7 @@
"stringstream": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
- "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==",
+ "integrity": "sha1-eIAiWw1K0Q4wkn0Weh1vL9OzOnI=",
"dev": true,
"optional": true
},
@@ -6447,7 +6456,7 @@
"timers-browserify": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
- "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
+ "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=",
"dev": true,
"requires": {
"setimmediate": "^1.0.4"
@@ -6471,7 +6480,7 @@
"to-regex": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
- "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=",
"dev": true,
"requires": {
"define-property": "^2.0.2",
@@ -6493,7 +6502,7 @@
"tough-cookie": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
- "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+ "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=",
"dev": true,
"optional": true,
"requires": {
@@ -6526,7 +6535,7 @@
"type-is": {
"version": "1.6.16",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
- "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+ "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=",
"dev": true,
"requires": {
"media-typer": "0.3.0",
@@ -6579,7 +6588,7 @@
"underscore": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
- "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==",
+ "integrity": "sha1-BtzjSg5op7q8KbNluOdLiSUgOWE=",
"dev": true
},
"union-value": {
@@ -6718,7 +6727,7 @@
"use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
- "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=",
"dev": true
},
"util": {
@@ -6751,7 +6760,7 @@
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=",
"dev": true,
"requires": {
"spdx-correct": "^3.0.0",
@@ -6767,7 +6776,7 @@
"vendors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz",
- "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==",
+ "integrity": "sha1-f8te759WI7FWvOqJ7DfWNnbyGAE=",
"dev": true
},
"verror": {
@@ -6803,7 +6812,7 @@
"watchpack": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
- "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+ "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=",
"dev": true,
"requires": {
"chokidar": "^2.0.2",
@@ -6814,7 +6823,7 @@
"wbuf": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
- "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=",
"dev": true,
"requires": {
"minimalistic-assert": "^1.0.0"
@@ -6823,7 +6832,7 @@
"webpack": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.6.0.tgz",
- "integrity": "sha512-OsHT3D0W0KmPPh60tC7asNnOmST6bKTiR90UyEdT9QYoaJ4OYN4Gg7WK1k3VxHK07ZoiYWPsKvlS/gAjwL/vRA==",
+ "integrity": "sha1-qJqSn77iBdNaT6LMSHvpy+yImLw=",
"dev": true,
"requires": {
"acorn": "^5.0.0",
@@ -6853,7 +6862,7 @@
"webpack-dev-middleware": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz",
- "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==",
+ "integrity": "sha1-+PwRIM47T8VoDO7LQ9d3lmshEF4=",
"dev": true,
"requires": {
"memory-fs": "~0.4.1",
@@ -6874,7 +6883,7 @@
"webpack-dev-server": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.8.2.tgz",
- "integrity": "sha512-wD9bs+Z1uwvf3Jc+8ZkyMI0Xi+aJJYjC2UZplOWoo/vStelK5Mv62X2uXYEYIQEjy9wJQMzC0fEFqQsg7vVEIg==",
+ "integrity": "sha1-q9YfQQd4zEyEPXzrv0FGWxq3c0w=",
"dev": true,
"requires": {
"ansi-html": "0.0.7",
@@ -6906,7 +6915,7 @@
"anymatch": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
- "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+ "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=",
"dev": true,
"requires": {
"micromatch": "^2.1.5",
@@ -7170,7 +7179,7 @@
"webpack-sources": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
- "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==",
+ "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=",
"dev": true,
"requires": {
"source-list-map": "^2.0.0",
@@ -7180,7 +7189,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
"dev": true
}
}
@@ -7198,7 +7207,7 @@
"websocket-extensions": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
- "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+ "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=",
"dev": true
},
"whet.extend": {
@@ -7210,7 +7219,7 @@
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
"dev": true,
"requires": {
"isexe": "^2.0.0"
diff --git a/js/src/index.js b/js/src/index.js
index 4fcc17d8f..e2ded815b 100644
--- a/js/src/index.js
+++ b/js/src/index.js
@@ -1,51 +1,51 @@
import './jupyter_geppetto';
import './geppettoJupyter.less';
+
function load_extension() {
+ if(IPython.notebook.kernel == null) {
+ console.warn("Kernel not initialized. Waiting to load Jupyter Geppetto extension");
+ setTimeout(load_extension, 100);
+ return;
+ }
+ console.log("Jupyter Geppetto extension loading");
+ // Hide the header
+ $('#header').hide();
+
+ // Add shortcut to hide/show header
+ IPython.keyboard_manager.command_shortcuts.add_shortcut('ctrl-`', function (event) {
+ if (IPython.notebook.mode == 'command') {
+ $('#header').toggle();
+ return false;
+ }
+ return true;
+ });
+
+
+ // Make Jupyter (aka IPython) available to Geppetto
+ window.parent.IPython = IPython;
+
+ // This loads the requirements into the notebook kernel
+ // TODO import synchronization as jupyter_geppetto is deprecated
+ IPython.notebook.kernel.execute('from jupyter_geppetto import synchronization, utils, synchronization as jupyter_geppetto');
+
+ // This will allow the application to be aware that the notebook kernel is ready
+ window.parent.GEPPETTO.trigger('jupyter_geppetto_extension_ready');
- // Hide the header
- $('#header').hide();
-
- // Add shortcut to hide/show header
- IPython.keyboard_manager.command_shortcuts.add_shortcut('ctrl-`', function (event) {
- if (IPython.notebook.mode == 'command') {
- $('#header').toggle();
- return false;
- }
- return true;
- });
-
- // Make Jupyter (aka IPython) available to Geppetto
- window.parent.IPython = IPython;
-
- // If a Geppetto extension is defining a custom behavior to load the kernel we call it
- IPython.notebook.restart_kernel({ confirm: false }).then(function () {
-
- //Import the GUI sync to use the Python Controlled Capabilities, logging, etc
- IPython.notebook.kernel.execute('from jupyter_geppetto import jupyter_geppetto, utils');
-
- // Load the project & activate the experiment
- var project = { id: 1, name: 'Project', experiments: [{ "id": 1, "name": 'Experiment', "status": 'DESIGN' }] }
- window.parent.GEPPETTO.Manager.loadProject(project, false);
- window.parent.GEPPETTO.Manager.loadExperiment(1, [], []);
-
- // Trigger event for the extension (ComponentInitialization) to run custom code
- window.parent.GEPPETTO.trigger('jupyter_geppetto_extension_ready')
- });
}
var load_ipython_extension = function () {
- if (IPython.notebook !== undefined && IPython.notebook._fully_loaded) {
- console.log("Kernel ready")
- load_extension();
- } else {
- console.log("Waiting for kernel to be ready")
- IPython.notebook.events.on("notebook_loaded.Notebook", function () {
- load_extension();
- })
- }
+ if (IPython.notebook !== undefined && IPython.notebook._fully_loaded) {
+ console.log("Kernel ready")
+ load_extension();
+ } else {
+ console.log("Waiting for kernel to be ready")
+ IPython.notebook.events.on("notebook_loaded.Notebook", function () {
+ load_extension();
+ })
+ }
};
export {
- load_ipython_extension
+ load_ipython_extension
};
diff --git a/jupyter_geppetto/__init__.py b/jupyter_geppetto/__init__.py
index 7293e5550..0801d4d9b 100644
--- a/jupyter_geppetto/__init__.py
+++ b/jupyter_geppetto/__init__.py
@@ -1,25 +1,29 @@
+import logging
import os.path
-import json
-import codecs
-from notebook.utils import url_path_join
-from notebook.base.handlers import IPythonHandler
-import tornado.websocket
+
import tornado.web
-import nbformat as nbf
-import logging
-from nbformat.v4.nbbase import new_notebook
-import pkg_resources
-import traceback
+from jupyter_geppetto.handlers import GeppettoController
+from jupyter_geppetto.service import PathService
+from jupyter_geppetto.settings import host_pattern, notebook_path, webapp_root_paths, home_page, \
+ geppetto_servlet_path_name
+from jupyter_geppetto.utils import createNotebook
+from jupyter_geppetto.webapi import RouteManager
+from jupyter_geppetto.websocket_connection import TornadoGeppettoWebSocketHandler
+from notebook.utils import url_path_join
+from tornado.routing import Matcher
+from tornado.web import StaticFileHandler
+
+# @deprecated Backward compatibility: remove when every application stop using
+import jupyter_geppetto.synchronization as jupyter_geppetto
def _jupyter_server_extension_paths():
-
return [{
"module": "jupyter_geppetto"
}]
+
def _jupyter_nbextension_paths():
-
return [dict(
section="notebook",
# the path is relative to the `jupyter_geppetto` directory
@@ -30,89 +34,111 @@ def _jupyter_nbextension_paths():
require="jupyter_geppetto/index")]
-class GeppettoHandler(IPythonHandler):
+def _add_routes(nbapp, routes, host_pattern='.*$', base_path='/'):
+ nbapp.log.info('Adding routes starting at base path {}'.format(base_path))
+ for route in routes:
+ nbapp.log.info('Adding http route {}'.format(route.path))
+ route_path = url_path_join(base_path, route.path)
+ nbapp.log.info('Complete route url: {}'.format(route_path))
+ nbapp.web_app.add_handlers(host_pattern, [(route_path, route.handler)])
+ if route_path[-1] != '/':
+ nbapp.web_app.add_handlers(host_pattern, [(route_path + '/', route.handler)])
+ else:
+ nbapp.web_app.add_handlers(host_pattern, [(route_path[0:-1], route.handler)])
- def get(self):
- try:
- config = self.application.settings['config']
- if 'library' in config:
- # Create initial ipynb if it doesn't exist
- if not os.path.isfile('notebook.ipynb'):
- nb0 = new_notebook(cells=[],
- metadata={'language': 'python',})
- f = codecs.open('notebook.ipynb', encoding='utf-8', mode='w')
- nbf.write(nb0, f, 4)
- f.close()
-
- template = pkg_resources.resource_filename(config['library'], 'geppetto/src/main/webapp/build/geppetto.vm')
- self.write(open(template).read())
- else:
- self.log.warning('Package to load missing in the url')
- self.write('Package to load missing in the url')
- except Exception:
- self.log.info('Error on Geppetto Server extension')
- traceback.print_exc()
-
-
-
-
-class GeppettoProjectsHandler(IPythonHandler):
- def get(self):
- self.write({})
+def _add_static_routes(nbapp, static_paths, host_pattern='.*$', base_path='/'):
+ nbapp.log.info('Adding routes starting at base path {}'.format(base_path))
+ for static_path in static_paths:
+ nbapp.log.info('Adding static http route {} pointing at'.format(static_path))
+ for webapp_root_path in webapp_root_paths:
+ route_path = url_path_join(base_path, webapp_root_path, '(.*)')
+ nbapp.log.info('Complete route url: {}'.format(route_path))
+ nbapp.web_app.add_handlers(host_pattern, [(route_path, StaticFileHandler, {"path": static_path})])
+
+
+def init_routes(nbapp, base_path):
+ web_app = nbapp.web_app
+ config = web_app.settings['config']
+ if 'library' in config:
+ modules = config['library'].split(',')
+ for moduleName in modules:
+ nbapp.log.info('Initializing library module {}'.format(moduleName))
+ module = __import__(moduleName) # Here the module should add its routes to the RouteManager
+
+ _add_routes(nbapp, RouteManager.routes, host_pattern, base_path)
+ _add_static_routes(nbapp, RouteManager.static, host_pattern, base_path)
+
+class GeppettoServletMatcher(Matcher):
-class WebSocketHandler(tornado.websocket.WebSocketHandler):
+ def match(self, request):
+ if geppetto_servlet_path_name == request.path[-len(geppetto_servlet_path_name):]:
+ return {}
- def open(self):
- # 1 -> Send the connection
- self.write_message(
- {"type": "client_id", "data": "{\"clientID\":\"Connection1\"}"})
- # 2 -> Check user privileges
- self.write_message(
- {"type": "user_privileges", "data": "{\"user_privileges\": \"{\\\"userName\\\":\\\"Python User\\\",\\\"loggedIn\\\":true,\\\"hasPersistence\\\":false,\\\"privileges\\\":[\\\"READ_PROJECT\\\",\\\"DOWNLOAD\\\",\\\"DROPBOX_INTEGRATION\\\", \\\"RUN_EXPERIMENT\\\", \\\"WRITE_PROJECT\\\"]}\"}"})
- def on_message(self, message):
- jsonMessage = json.loads(message)
- if (jsonMessage['type'] == 'geppetto_version'):
- # Where do we get the geppetto version from?
- self.write_message({"requestID": jsonMessage['requestID'], "type": "geppetto_version", "data": "{\"geppetto_version\":\"0.4.1\"}"})
+class BasePathRecognitionMatcher(Matcher):
+ '''Allows adding routes dynamically starting to the first call to /geppetto.
+ Starts as a catch-all then turns off after all the routes are added.'''
- def on_close(self):
- pass
+ def __init__(self, nbapp):
+ self.paths = []
+ self.nbapp = nbapp
+
+ def match(self, request):
+ path = request.path
+ self.nbapp.log.debug('Trying to match path: {}'.format(path))
+
+ if home_page not in path:
+ return None # We activate the path initialization only for the first home call
+
+ base_path = path.split(home_page)[0]
+ if not base_path or base_path[0] != '/':
+ base_path = '/' + base_path
+
+ self.nbapp.log.debug('Path found: {}'.format(base_path))
+ if base_path in self.paths:
+ return None # Skip already added base path
+
+ self.paths.append(base_path)
+ self.nbapp.log.info('New context path found: {}. Relative routes will be added.'.format(base_path))
+ init_routes(self.nbapp, base_path)
+ return {}
+
+
+class RetryHandler(tornado.web.RequestHandler):
+
+ def get(self):
+ self.redirect(self.request.path)
def load_jupyter_server_extension(nbapp):
-
try:
+ nbapp.log.info("Starting Geppetto Jupyter extension")
+ logging.info = nbapp.log.info
+ logging.debug = nbapp.log.debug
+ logging.error = nbapp.log.error
+
+ if settings.debug:
+ nbapp.log_level = 'DEBUG'
+ RouteManager.initNotebookApp(nbapp)
+
+ if not os.path.exists(notebook_path):
+ nbapp.log.info("Creating notebook {}".format(notebook_path))
+ createNotebook(notebook_path)
+ else:
+ nbapp.log.info("Using notebook {}".format(notebook_path))
+
+ # Just add the wildcard matcher here. Other routes will be added dinamically from within the matcher.
+ nbapp.web_app.add_handlers(host_pattern, [(BasePathRecognitionMatcher(nbapp), RetryHandler)])
+ nbapp.web_app.add_handlers(host_pattern, [(GeppettoServletMatcher(), TornadoGeppettoWebSocketHandler)])
+ # init_routes(nbapp, '/')
+
nbapp.log.info("Geppetto Jupyter extension is running!")
- web_app = nbapp.web_app
- config = web_app.settings['config']
-
- host_pattern = '.*$'
- route_pattern = url_path_join(web_app.settings['base_url'], '/geppetto')
- web_app.add_handlers(host_pattern, [(route_pattern, GeppettoHandler)])
-
- route_pattern_geppetto_projects = url_path_join(
- web_app.settings['base_url'], '/geppettoprojects')
- web_app.add_handlers(
- host_pattern, [(route_pattern_geppetto_projects, GeppettoProjectsHandler)])
-
- websocket_pattern = url_path_join(
- web_app.settings['base_url'], '/org.geppetto.frontend/GeppettoServlet')
- web_app.add_handlers(host_pattern, [(websocket_pattern, WebSocketHandler)])
-
- if 'library' in config:
- nbapp.log.info("Geppetto Jupyter extension loading library: " + str(config['library']))
- template = pkg_resources.resource_filename(config['library'], 'geppetto/src/main/webapp/') # always use slash
- web_app.add_handlers(host_pattern, [(r"/geppetto/(.*)", tornado.web.StaticFileHandler, {
- 'path': template})])
- web_app.add_handlers(host_pattern, [(r"/org.geppetto.frontend/geppetto/(.*)", tornado.web.StaticFileHandler, {
- 'path': template})])
- else:
- nbapp.log.warning('Package to load missing in the url')
- raise Exception
-
except Exception:
- nbapp.log.info('Error on Geppetto Server extension')
- traceback.print_exc()
+ nbapp.log.error('Error on Geppetto Server extension')
+ raise
+
+# We're adding here the base routes: or maybe it should be the application to add all the routes it needs
+RouteManager.add_controller(GeppettoController)
+RouteManager.add_web_client(PathService.get_webapp_directory())
\ No newline at end of file
diff --git a/jupyter_geppetto/handlers.py b/jupyter_geppetto/handlers.py
new file mode 100644
index 000000000..3415b7b36
--- /dev/null
+++ b/jupyter_geppetto/handlers.py
@@ -0,0 +1,23 @@
+import logging
+
+from jupyter_geppetto.service import PathService
+
+from .settings import template_path, home_page
+from .webapi import get
+
+
+class GeppettoController:
+
+ @get('/geppettoprojects')
+ def getProjects(self, **kwargs):
+ # TODO still no project handling here.
+ return {}
+
+ @get(home_page)
+ def index(self, **kwargs):
+ try:
+ template = template_path
+ return open(PathService.get_webapp_resource(template)).read()
+ except Exception:
+ logging.info('Error on Geppetto Server extension')
+ raise
diff --git a/jupyter_geppetto/jupyter_geppetto.py b/jupyter_geppetto/jupyter_geppetto.py
deleted file mode 100644
index 38af1c1f4..000000000
--- a/jupyter_geppetto/jupyter_geppetto.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-jupyter_geppetto.py
-"""
-import logging
-from collections import defaultdict
-import ipywidgets as widgets
-import json
-from traitlets import (CUnicode, Unicode, Instance, List, Dict, Bool, Float, Int)
-from jupyter_geppetto import utils
-
-
-# This is a list of all the models that are synched between Python and Javascript
-synched_models = defaultdict(list)
-context = None
-
-utils.configure_logging()
-
-def remove_component_sync(componentType, model):
- component_to_remove = None
- for existingModel, synched_component in list(synched_models.items()):
- if existingModel == model:
- component_to_remove = model
- break
- if(component_to_remove):
- synched_models[component_to_remove].disconnect()
- del synched_models[component_to_remove]
-
-class ComponentSync(widgets.Widget):
- _model_name = Unicode('ComponentSync').tag(sync=True)
- _model_module = Unicode('jupyter_geppetto').tag(sync=True)
- _model_module_version = Unicode('~1.0.0')
-
- componentType = Unicode('componentType').tag(sync=True)
- model = Unicode('').tag(sync=True)
- id = Unicode('').tag(sync=True)
- value = CUnicode().tag(sync=True)
-
- widget_name = Unicode('').tag(sync=True)
- embedded = Bool(True).tag(sync=True)
- read_only = Bool(False).tag(sync=True)
- extraData = None
-
- def __init__(self, **kwargs):
- super(ComponentSync, self).__init__(**kwargs)
-
- if 'model' in kwargs and kwargs["model"] is not None and kwargs["model"] != '':
- synched_models[kwargs["model"]] = self
-
- self._value_handler = widgets.CallbackDispatcher()
- #the method updateModel is executed in response to the sync_value event
- self._value_handler.register_callback(self.updateModel)
-
- self.on_msg(self._handle_component_msg)
-
- def _handle_component_msg(self, _, content, buffers):
- if content.get('event', '') == 'sync_value':
- self._value_handler(self, content)
-
-
- def updateModel(self, *args):
- if self.model != None and self.model != '' and args[1]['value'] != None:
- try:
- value = json.loads(args[1]['value'])
- if isinstance(value, str):
- value = "'" + value + "'"
- else:
- value = str(value)
- logging.debug("Updating model with new value " + value)
-
- context_path = next(iter(context))
- if(context_path and context_path!=""):
- logging.debug("self.model = " + context_path+"."+self.model)
- exec(context_path+"."+self.model + "=" + value, context)
- else:
- logging.debug("self.model = " + self.model)
- exec(self.model + "=" + value)
- except Exception as identifier:
- logging.exception("Error updating model")
-
- def connect(self):
- logging.debug("ComponentSync connecting to " + self.model)
- self.send({"type": "connect"})
-
- def disconnect(self):
- logging.debug("ComponentSync disconnecting from " + self.model)
- self.send({"type": "disconnect"})
- self._value_handler.register_callback(self.updateModel, remove=True)
- self.on_msg(self._handle_component_msg, remove=True)
-
-
- def __str__(self):
- return "Component Sync => Widget Name: " + self.widget_name + ", Embedded: " + str(self.embedded) + ", Sync Value: " + self.value + ", Model: " + str(self.model) + ", Extra Data: " + self.extraData
diff --git a/jupyter_geppetto/service.py b/jupyter_geppetto/service.py
new file mode 100644
index 000000000..1f375db82
--- /dev/null
+++ b/jupyter_geppetto/service.py
@@ -0,0 +1,25 @@
+from jupyter_geppetto import settings
+from notebook.utils import url_path_join
+import logging
+import os
+import sys
+import glob
+
+class PathService:
+ webapp_directory = os.path.abspath(".") + '/webapp/'
+
+ @classmethod
+ def get_webapp_directory(cls):
+ if not os.path.exists(cls.webapp_directory):
+
+ discovered_paths = glob.glob(os.path.abspath(".") + '/*/' + settings.geppetto_webapp_file)
+ if discovered_paths:
+ cls.webapp_directory = os.path.dirname(discovered_paths[0])
+ logging.info('Webapp directory discovered: {}'.format(cls.webapp_directory))
+ else:
+ logging.error('Cannot determine webapp directory. PathService won\'t work')
+ return cls.webapp_directory
+
+ @classmethod
+ def get_webapp_resource(cls, path):
+ return url_path_join(cls.get_webapp_directory(), path)
diff --git a/jupyter_geppetto/settings.py b/jupyter_geppetto/settings.py
new file mode 100644
index 000000000..3d4c0dad9
--- /dev/null
+++ b/jupyter_geppetto/settings.py
@@ -0,0 +1,29 @@
+'''
+Settings for the module. Change right after importing, if needed.
+'''
+
+# The path of the geppetto client. Relative path is from the application root
+geppetto_webapp_file = 'GeppettoConfiguration.json'
+
+# The path of the template. It should be relative to the webapp path
+template_path = 'build/geppetto.vm'
+# The path of the Jupyter notebook file
+notebook_path = 'notebook.ipynb'
+# Server host pattern
+host_pattern = '.*$'
+
+webapp_root_paths = ['/geppetto']
+
+home_page = '/geppetto'
+
+geppetto_servlet_path_name = 'GeppettoServlet'
+
+
+debug = False
+
+
+class websocket:
+ compression_enabled = False
+ min_message_length_for_compression = 200
+
+
diff --git a/jupyter_geppetto/synchronization.py b/jupyter_geppetto/synchronization.py
index ceaafcf6f..af607f767 100644
--- a/jupyter_geppetto/synchronization.py
+++ b/jupyter_geppetto/synchronization.py
@@ -1,14 +1,101 @@
"""
synchronization.py
"""
-import traceback
-
-import logging
-from jupyter_geppetto import jupyter_geppetto
import time
import threading
-import importlib
+
+
+import logging
+from collections import defaultdict
+import ipywidgets as widgets
import json
+from traitlets import (CUnicode, Unicode, Instance, List, Dict, Bool, Float, Int)
+from jupyter_geppetto import utils
+
+# This is a list of all the models that are synched between Python and Javascript
+synched_models = defaultdict(list)
+context = None
+
+utils.configure_logging()
+
+
+def remove_component_sync(componentType, model):
+ component_to_remove = None
+ for existingModel, synched_component in list(synched_models.items()):
+ if existingModel == model:
+ component_to_remove = model
+ break
+ if (component_to_remove):
+ synched_models[component_to_remove].disconnect()
+ del synched_models[component_to_remove]
+
+
+class ComponentSync(widgets.Widget):
+ '''Defines the synchronization widget'''
+ _model_name = Unicode('ComponentSync').tag(sync=True)
+ _model_module = Unicode('jupyter_geppetto').tag(sync=True)
+ _model_module_version = Unicode('~1.0.0')
+
+ componentType = Unicode('componentType').tag(sync=True)
+ model = Unicode('').tag(sync=True)
+ id = Unicode('').tag(sync=True)
+ value = CUnicode().tag(sync=True)
+
+ widget_name = Unicode('').tag(sync=True)
+ embedded = Bool(True).tag(sync=True)
+ read_only = Bool(False).tag(sync=True)
+ extraData = None
+
+ def __init__(self, **kwargs):
+ super(ComponentSync, self).__init__(**kwargs)
+
+ if 'model' in kwargs and kwargs["model"] is not None and kwargs["model"] != '':
+ synched_models[kwargs["model"]] = self
+
+ self._value_handler = widgets.CallbackDispatcher()
+ # the method updateModel is executed in response to the sync_value event
+ self._value_handler.register_callback(self.updateModel)
+
+ self.on_msg(self._handle_component_msg)
+
+ def _handle_component_msg(self, _, content, buffers):
+ if content.get('event', '') == 'sync_value':
+ self._value_handler(self, content)
+
+ def updateModel(self, *args):
+ if self.model != None and self.model != '' and args[1]['value'] != None:
+ try:
+ value = json.loads(args[1]['value'])
+ if isinstance(value, str):
+ value = "'" + value + "'"
+ else:
+ value = str(value)
+ logging.debug("Updating model with new value " + value)
+
+ object_name = next(iter(context))
+ if (object_name and object_name != ""):
+ logging.debug("self.model = " + object_name + "." + self.model)
+ exec(object_name + "." + self.model + "=" + value, context)
+ else:
+ logging.debug("self.model = " + self.model)
+ exec(self.model + "=" + value)
+ except Exception as identifier:
+ logging.exception("Error updating model")
+
+ def connect(self):
+ logging.debug("ComponentSync connecting to " + self.model)
+ self.send({"type": "connect"})
+
+ def disconnect(self):
+ logging.debug("ComponentSync disconnecting from " + self.model)
+ self.send({"type": "disconnect"})
+ self._value_handler.register_callback(self.updateModel, remove=True)
+ self.on_msg(self._handle_component_msg, remove=True)
+
+ def __str__(self):
+ return "Component Sync => Widget Name: " + self.widget_name + ", Embedded: " + str(
+ self.embedded) + ", Sync Value: " + self.value + ", Model: " + str(
+ self.model) + ", Extra Data: " + self.extraData
def startSynchronization(scope):
@@ -21,10 +108,9 @@ class LoopTimer(threading.Thread):
"""
a Timer that calls f every interval
- A thread that checks all the variables that we are synching between Python and Javascript and if
+ A thread that checks all the variables that we are syncing between Python and Javascript and if
these variables have changed on the Python side will propagate the changes to Javascript
- TODO This code should move to a generic geppetto class since it's not NetPyNE specific
"""
def __init__(self, interval, scope, fun=None):
@@ -49,7 +135,7 @@ def run(self):
def process_events(self):
try:
- for model, synched_component in list(jupyter_geppetto.synched_models.items()):
+ for model, synched_component in list(synched_models.items()):
modelValue=None
if model != '':
try:
diff --git a/jupyter_geppetto/utils.py b/jupyter_geppetto/utils.py
index fd6c48309..077084295 100644
--- a/jupyter_geppetto/utils.py
+++ b/jupyter_geppetto/utils.py
@@ -1,27 +1,32 @@
import logging
+
+from ipykernel.jsonutil import json_clean
# from jupyter_client import session
from zmq.utils import jsonapi
-from ipykernel.jsonutil import json_clean
+
def convertToJS(content):
# return session.json_packer(content).decode("utf-8")
# Old way: this needs to be deleted if the above line is enough
return jsonapi.dumps(json_clean(content)).decode("utf-8")
+
def convertToPython(content):
# return session.json_unpacker(content)
# Old way: this needs to be deleted if the above line is enough
return jsonapi.loads(content)
+
def exception_to_string(exc_info):
import IPython.core.ultratb
tb = IPython.core.ultratb.VerboseTB()
return tb.text(*exc_info)
+
def getJSONError(message, exc_info):
data = {}
data['type'] = 'ERROR'
- data['message'] = message
+ data['websocket'] = message
if isinstance(exc_info, str):
details = exc_info
@@ -30,21 +35,37 @@ def getJSONError(message, exc_info):
data['details'] = details
return data
+
def getJSONReply():
data = {}
data['type'] = 'OK'
return data
+
def configure_logging():
try:
# Configure log
logger = logging.getLogger()
- fhandler = logging.FileHandler(filename='netpyne-ui.log', mode='a')
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fhandler = logging.FileHandler(filename='app.log', mode='a')
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s')
fhandler.setFormatter(formatter)
logger.addHandler(fhandler)
logger.setLevel(logging.DEBUG)
logging.debug('Log configured')
except Exception as exception:
logging.exception("Unexpected error while initializing Geppetto from Python:")
- logging.error(exception)
\ No newline at end of file
+ logging.error(exception)
+
+
+def createNotebook(filename):
+ import nbformat as nbf
+ from nbformat.v4.nbbase import new_notebook
+ import codecs
+ nb0 = new_notebook(cells=[], metadata={"kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ }})
+ f = codecs.open(filename, encoding='utf-8', mode='w')
+ nbf.write(nb0, f, 4)
+ f.close()
diff --git a/jupyter_geppetto/webapi.py b/jupyter_geppetto/webapi.py
new file mode 100644
index 000000000..37cc46691
--- /dev/null
+++ b/jupyter_geppetto/webapi.py
@@ -0,0 +1,180 @@
+'''
+Define decorators to easily define action controllers
+
+'''
+from notebook.base.handlers import IPythonHandler
+from tornado.web import RequestHandler, StaticFileHandler
+import logging
+from jupyter_geppetto import utils
+
+
+import sys
+
+
+def export(fn):
+ '''Decorator to add to the __all__ variable'''
+ mod = sys.modules[fn.__module__]
+ if not hasattr(mod, '__all__'):
+ mod.__all__ = []
+ mod.__all__.append(fn.__name__)
+ return fn
+
+
+class METHODS:
+ GET = 'get'
+ POST = 'post'
+ PUT = 'put'
+ DELETE = 'delete'
+
+
+class Route:
+ def __init__(self, path, handler):
+ self.path = path
+ self.handler = handler
+
+
+@export
+class RouteManager:
+ '''Gives an access point to define routes and relates controllers/handlers'''
+ routes = []
+ static = []
+
+ @classmethod
+ def initNotebookApp(cls, nbapp):
+ cls.nbapp = nbapp
+
+ @classmethod
+ def add_routes(cls, routes):
+ cls.routes += routes
+
+ @classmethod
+ def add_route(cls, path, handler):
+ cls.routes.append(Route(path, handler))
+
+ @classmethod
+ def add_controller(cls, controller_class):
+ '''A controller is a class which defined the actions as methods decorated with tornado_action decorators
+ (get, post, or custom)'''
+ cls.routes += [c for c in controller_class.__dict__.values() if type(c) == Route]
+
+ @classmethod
+ def add_web_client(cls, files_path):
+ cls.static.append(files_path)
+
+
+class HandlerType(type):
+ '''Just a recognizable metaclass'''
+ pass
+
+
+def tornado_action(method, path, headers={}):
+ '''Annotation to build a tornado web handler on a function or method'''
+
+ assert method in (getattr(METHODS, m) for m in dir(METHODS)), \
+ 'Method {} not allowed. Should be one of {}'.format(
+ method, tuple(getattr(METHODS, m) for m in dir(METHODS) if not '_' in m))
+
+ def real_decorator(fn):
+ def handlerFn(self, *args):
+ logging.info('Calling {}'.format(fn.__name__))
+ function_arguments = fn.__code__.co_varnames
+ kwargs = {name: self.get_query_argument(name)
+ for name in function_arguments[len(args) + 1:]
+ if self.get_query_argument(name, None) != None
+ }
+ kwargs.update({name: self.get_body_argument(name)
+ for name in function_arguments[len(args) + 1:]
+ if self.get_body_argument(name, None) != None
+ })
+ logging.debug('Positional arguments: {}'.format(args))
+ logging.debug('Keyword arguments: {}'.format(kwargs))
+ value = fn(self, *args, **kwargs)
+
+ for hname, hvalue in headers.items():
+ self.set_header(hname, hvalue)
+ if value is not None:
+ self.finish(value)
+
+ route = Route(path, HandlerType(path, (IPythonHandler,), {method: handlerFn}))
+ return route
+
+ return real_decorator
+
+
+@export
+def get(path, headers={}):
+ '''Annotation for get actions.
+ Parameters are taken first from the path wildcard pieces (.*), then from the query string. Query string parameters
+ must have the same name of decorated function arguments.
+ '''
+ return tornado_action(METHODS.GET, path, headers)
+
+
+@export
+def post(path, headers={}):
+ '''Annotation for post actions'''
+ return tornado_action(METHODS.POST, path, headers)
+
+
+if __name__ == '__main__':
+ class TestController:
+
+ @get('/test')
+ def foo(self, arg, argument=1):
+ return '{} {} {}'.format('foo', arg, argument)
+
+
+ print(TestController.foo.path, TestController.foo.handler)
+
+
+ class MockApplication:
+ ui_methods = {}
+ ui_modules = {}
+ settings = {}
+
+ def log_request(self, *args):
+ pass
+
+
+ class MockConnection:
+ def set_close_callback(self, *args):
+ return 0
+
+ def write(self, something, callback=None):
+ print('write')
+ print(something)
+
+ def finish(self, *args, **kwargs):
+ print('finish')
+
+ def write_headers(self, *args, **kwargs):
+ print('write_headers')
+
+
+ class MockRequest:
+ connection = MockConnection()
+ query_arguments = {'argument': ['2']}
+ method = 'GET'
+ headers = {}
+ uri = ''
+ remote_ip = ''
+
+
+ print("\n\nTest auto created handler")
+ handler = TestController.foo.handler(MockApplication(), MockRequest())
+ handler._execute([])
+ handler._finished = False
+ handler.get(1)
+
+ print("\n\nTest standard handler")
+
+
+ class EquivalentHandler(RequestHandler):
+ def get(self, arg):
+ self.finish('{} {} {}'.format('foo', arg, self.get_query_argument('argument')))
+
+
+ handler = EquivalentHandler(MockApplication(), MockRequest())
+ handler._execute([])
+ handler._finished = False
+ handler.get(1)
diff --git a/jupyter_geppetto/websocket_connection.py b/jupyter_geppetto/websocket_connection.py
new file mode 100644
index 000000000..5c561ad2b
--- /dev/null
+++ b/jupyter_geppetto/websocket_connection.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+""" generated source for module WebsocketConnection """
+from __future__ import print_function
+
+import gzip
+import json
+import logging
+
+from jupyter_geppetto import settings
+from pyecore.valuecontainer import EList
+from pygeppetto.api.message_handler import GeppettoMessageHandler
+from tornado.websocket import WebSocketHandler
+
+
+# package: org.geppetto.frontend.controllers
+#
+# * Class used to process Web Socket Connections. Messages sent from the connecting clients, web socket connections, are received in here.
+# *
+# * @author matteocantarelli
+# *
+#
+
+
+class TornadoGeppettoWebSocketHandler(WebSocketHandler, GeppettoMessageHandler):
+
+ def __init__(self, *args, **kwargs):
+ WebSocketHandler.__init__(self, *args, **kwargs)
+ GeppettoMessageHandler.__init__(self)
+
+ def open(self):
+ # 1 -> Send the connection
+ logging.info('Open websocket')
+ self.__class__.connection_id += 1
+
+ self.sendClientId()
+
+ # 2 -> Check user privileges
+ self.sendPrivileges()
+
+ def send_message_data(self, msg_data):
+ msg = json.dumps(msg_data)
+ if settings.websocket.compression_enabled and len(msg) > settings.websocket.min_message_length_for_compression:
+ self.write_message(gzip.compress(bytes(msg, 'utf-8')), binary=True)
+ self.write_message(msg)
+
+ def on_message(self, message):
+ self.handle_message(json.loads(message))
+
+ def on_close(self):
+ # self.write_message({
+ # 'type': 'socket_closed',
+ # 'data': ''
+ # })
+ # self.geppettoHandler.closeProject()
+ logging.info("Closed Connection ...")
+
+ # NOTE: no other websocket expected for now
+
+ #
+ # * @param runnableQueries
+ # * @return A list based on the EMF class. It's not possible to use directly the EMF class as Gson requires fields with public access modifiers which breaks EMF encapsulation
+ #
+
+ def convertRunnableQueriesDataTransferModel(self, runnableQueries):
+ """ generated source for method convertRunnableQueriesDataTransferModel """
+ runnableQueriesEMF = EList('')
+ from pygeppetto.model.datasources.datasources import RunnableQuery
+ for dt in runnableQueries:
+ rqEMF = RunnableQuery(targetVariablePath=dt.targetVariablePath, queryPath=dt.queryPath)
+ runnableQueriesEMF.append(rqEMF)
+ return runnableQueriesEMF
diff --git a/setup.py b/setup.py
index 2cd8c2671..53affba7b 100644
--- a/setup.py
+++ b/setup.py
@@ -9,7 +9,7 @@
setuptools.setup(
name="jupyter_geppetto",
- version="0.4.2",
+ version="1.0.0",
url="https://github.com/openworm/org.geppetto.frontend.jupyter",
author="The Geppetto Development Team",
author_email="info@geppetto.org",
@@ -66,7 +66,7 @@
'prometheus-client==0.3.1',
'prompt-toolkit==1.0.15',
'ptyprocess==0.6.0',
- 'pyecore==0.8.7',
+ #'pyecore==0.8.7',
'Pygments==2.2.0',
'pyparsing==2.2.0',
'python-dateutil==2.7.3',
@@ -86,6 +86,6 @@
'webencodings==0.5.1',
'widgetsnbextension==3.4.1',
'jupyter==1.0.0',
- 'pygeppetto==0.4.2'
+ 'pygeppetto>=0.5.0'
],
)