├── .gitignore ├── CHANGELOG.md ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── RELEASE.md ├── binder └── requirements.txt ├── conda.recipe └── meta.yaml ├── extensions └── jupyterlab │ ├── .prettierrc │ ├── lib │ ├── index.d.ts │ └── index.js │ ├── package.json │ ├── src │ └── index.ts │ ├── style │ └── index.css │ ├── tsconfig.json │ └── yarn.lock ├── jupyter_dash ├── __init__.py ├── comms.py ├── jupyter_app.py ├── labextension │ ├── dist │ │ └── jupyterlab-dash-v0.4.2.tgz │ └── package.json ├── nbextension │ ├── README.md │ ├── __init__.py │ ├── description.yaml │ ├── jupyter_dash.json │ └── main.js └── version.py ├── notebooks ├── getting_started.ipynb └── getting_started.py ├── renovate.json ├── requirements-dev.txt ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | .idea 3 | /extensions/jupyterlab/node_modules/ 4 | /extensions/jupyterlab/*.tgz 5 | /dist 6 | /build/ 7 | .ipynb_checkpoints 8 | /extensions/jupyterlab/README.md 9 | __pycache__/ 10 | *.py[cod] 11 | *$py.class 12 | .mypy_cache/ 13 | .DS_Store 14 | .env 15 | .venv 16 | env/ 17 | venv/ 18 | ENV/ 19 | env.bak/ 20 | venv.bak/ 21 | vv 22 | .vscode/settings.json 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log for JupyterDash 2 | All notable changes to `jupyter-dash` will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [UNRELEASED] 6 | ### Fixed 7 | - Propagate start error message. [#94](https://github.com/plotly/jupyter-dash/pull/94) 8 | - Fix rerun server with newer flask/werkzeug. [#105](https://github.com/plotly/jupyter-dash/pull/105) 9 | 10 | ### Added 11 | 12 | - Support for `Dash.run` method added in Dash 2.4.0 13 | 14 | ## 0.4.2 - 2022-03-31 15 | ### Fixed 16 | - Fixed `werkzeug` 2.1.0 import and `skip` calculation, shutdown deprecation warning. 17 | - Work around a partial import of `orjson` when it's installed and you use `mode="jupyterlab"` 18 | - Fix `infer_jupyter_proxy_config` for newer jupyterlab versions 19 | 20 | ## 0.4.1 - 2022-02-16 21 | ### Fixed 22 | - Support Dash 2.1, fix `AttributeError: Read-only... requests_pathname_prefix` 23 | 24 | ## 0.4.0 - 2021-01-22 25 | ### Added 26 | - JuypterLab 3.0 support 27 | 28 | ## 0.3.0 - 2020-07-21 29 | ### Added 30 | - Added support for using JupyterDash in Google Colab ([#27](https://github.com/plotly/jupyter-dash/pull/27)) 31 | - Added support for installing JupyterDash from git using pip: (e.g. `pip install git+https://github.com/plotly/jupyter-dash.git@master`) 32 | 33 | ### Changed 34 | - The default display width in `mode='inline'` is now `100%` to fill the screen width. 35 | 36 | ## 0.2.1 - 2020-05-19 37 | ### Added 38 | - Remove f-strings to support Python 3.5 39 | 40 | ## 0.2.0 - 2020-05-19 41 | Initial Release 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Plotly, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include jupyter_dash/nbextension *.json 2 | include jupyter_dash/nbextension *.js 3 | include jupyter_dash/labextension/package.json 4 | include jupyter_dash/labextension/dist *.tgz 5 | include requirements.txt 6 | include requirements-dev.txt 7 | include README.md 8 | include LICENSE.txt 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## NOTICE: as of Dash v2.11, Jupyter support is built into the main Dash package. 2 | 3 | The `jupyter-dash` package is no longer necessary, all of its functionality has been merged into `dash`. See https://dash.plotly.com/dash-in-jupyter for usage details, and if you have any questions please join the discussion at https://community.plotly.com/ 4 | 5 | The old readme is below for those still using the package, but `jupyter-dash` will not receive any further updates. 6 | 7 | --- 8 | 9 | # Jupyter Dash 10 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/plotly/jupyter-dash/master?urlpath=tree/notebooks/getting_started.ipynb) 11 | 12 | This library makes it easy to develop Plotly Dash apps interactively from within Jupyter environments (e.g. classic Notebook, JupyterLab, Visual Studio Code notebooks, nteract, PyCharm notebooks, etc.). 13 | 14 | ![jupterlab example](https://user-images.githubusercontent.com/15064365/82324108-150d4200-99a7-11ea-8d22-5c1bb8acaadb.gif) 15 | 16 | See the [notebooks/getting_started.ipynb](https://github.com/plotly/jupyter-dash/blob/master/notebooks/getting_started.ipynb) for more information and example usage. 17 | 18 | # Installation 19 | You can install the JupyterDash Python package using pip... 20 | ``` 21 | $ pip install jupyter-dash 22 | ``` 23 | or conda 24 | ``` 25 | $ conda install -c conda-forge -c plotly jupyter-dash 26 | ``` 27 | 28 | ## JupyterLab support 29 | When used in JupyterLab, JupyterDash depends on the [`jupyterlab-dash`](https://www.npmjs.com/package/jupyterlab-dash) JupyterLab extension, which requires JupyterLab version 2.0 or above. 30 | 31 | This extension is included with the Python package, but in order to activate it JupyterLab must be rebuilt. JupyterLab should automatically produce a popup dialog asking for permission to rebuild, but the rebuild can also be performed manually from the command line using: 32 | 33 | ``` 34 | $ jupyter lab build 35 | ``` 36 | 37 | To check that the extension is installed properly, call `jupyter labextension list`. 38 | 39 | ## Colab support 40 | As of version 0.3.0, `JupyterDash` works in Colab with no additional configuration. Just install `jupyter-dash` using pip in a Colab notebook cell 41 | ``` 42 | !pip install jupyter-dash 43 | ``` 44 | 45 | # Features 46 | To learn more about the features of JupyterDash, check out the [announcement post](https://medium.com/plotly/introducing-jupyterdash-811f1f57c02e). 47 | 48 | # Development 49 | To develop JupyterDash, first create and activate a virtual environment using virtualenv or conda. 50 | 51 | Then clone the repository and change directory to the repository root: 52 | ``` 53 | $ git clone https://github.com/plotly/jupyter-dash.git 54 | $ cd jupyter-dash 55 | ``` 56 | 57 | Then install the dependencies: 58 | ``` 59 | $ pip install -r requirements.txt -r requirements-dev.txt 60 | ``` 61 | 62 | Then install the Python package in editable mode. Note: this will require [nodejs](https://nodejs.org/en/) to be installed. 63 | ``` 64 | $ pip install -e . 65 | ``` 66 | 67 | Then install the classic notebook extension in development mode: 68 | ``` 69 | $ jupyter nbextension install --sys-prefix --symlink --py jupyter_dash 70 | $ jupyter nbextension enable --py jupyter_dash 71 | ``` 72 | 73 | Then install the JupyterLab extension in development mode: 74 | ``` 75 | $ jupyter labextension link extensions/jupyterlab 76 | ``` 77 | 78 | For release, build the JupyterLab extension to bundle with the Python package (see [RELEASE.md](https://github.com/plotly/jupyter-dash/blob/master/RELEASE.md) for the full process): 79 | 80 | ``` 81 | $ python setup.py build_js 82 | ``` 83 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # jupyter-dash release process: 2 | 3 | - Update the version number in two places: 4 | - `jupyter_dash/version.py` 5 | - `extensions/jupyterlab/package.json` 6 | - Update `CHANGELOG.md` using the new version number and any changes since the last release 7 | - Empty old tarballs from `dist/` and `jupyter_dash/labextension/dist/` 8 | - Build the extension: `python setup.py build_js` 9 | - Build the PyPI release: `python setup.py sdist bdist_wheel` 10 | - Sanity: 11 | - In an env with jupyter installed, `pip install dist/jupyter_dash<...>.whl` 12 | - Run jupyter lab - it should ask to rebuild. After it finishes, make sure it’s working and using the newly installed package 13 | - Upload to PyPI: `twine upload dist/*` 14 | - Build the conda release, in an env with conda: `conda build conda.recipe/` 15 | - Find and run the command it prints near the end of its output: `anaconda upload ` 16 | - commit all of this to master - you should see: 17 | - the version change (two places you explicitly changed, plus one autogenerated by build_js) 18 | - `CHANGELOG.md` 19 | - the new extension tarball in `jupyter_dash/labextension/dist/` replacing the old 20 | - tag it: `git tag -a ‘vX.Y.Z’ -m ‘vX.Y.Z’` 21 | - `git push origin master` 22 | - `git push origin —tags` 23 | - on GitHub, draft a new release - choose the new tag, give it exactly the same name as the tag. For the description, copy in the changelog entry for the new release. 24 | -------------------------------------------------------------------------------- /binder/requirements.txt: -------------------------------------------------------------------------------- 1 | -r ../requirements.txt 2 | notebook==6.0.3 3 | jupyter_server_proxy 4 | pandas 5 | numpy 6 | jupyter-dash 7 | -------------------------------------------------------------------------------- /conda.recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set sdata = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True) %} 2 | {% set version = sdata.get('version') %} 3 | {% set name = sdata.get('name') %} 4 | 5 | package: 6 | name: jupyter-dash 7 | version: {{ version }} 8 | 9 | source: 10 | path: .. 11 | 12 | build: 13 | number: 0 14 | script: | 15 | {{ PYTHON }} -m pip install . --no-deps --ignore-installed --no-cache-dir -q 16 | noarch: python 17 | 18 | requirements: 19 | host: 20 | - python>=3.7 21 | - pip 22 | - nodejs 23 | - jupyterlab>=2.0 24 | 25 | run: 26 | - python>=3.6 27 | {% for dep in sdata.get('install_requires',{}) %} 28 | - {{ dep }} 29 | {% endfor %} 30 | 31 | test: 32 | imports: 33 | - jupyter_dash 34 | 35 | about: 36 | home: {{ sdata['url'] }} 37 | summary: {{ sdata['description'] }} 38 | license: {{ sdata['license'] }} 39 | license_file: '{{ environ["RECIPE_DIR"] }}/../LICENSE.txt' 40 | -------------------------------------------------------------------------------- /extensions/jupyterlab/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /extensions/jupyterlab/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | import { JupyterFrontEndPlugin } from '@jupyterlab/application'; 2 | import '../style/index.css'; 3 | /** 4 | * Initialization data for the jupyterlab-dash extension. 5 | */ 6 | declare const extension: JupyterFrontEndPlugin; 7 | export default extension; 8 | -------------------------------------------------------------------------------- /extensions/jupyterlab/lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const application_1 = require("@jupyterlab/application"); 4 | const coreutils_1 = require("@jupyterlab/coreutils"); 5 | const notebook_1 = require("@jupyterlab/notebook"); 6 | const console_1 = require("@jupyterlab/console"); 7 | const widgets_1 = require("@lumino/widgets"); 8 | require("../style/index.css"); 9 | class DashIFrameWidget extends widgets_1.Widget { 10 | /** 11 | * Construct a new DashIFrameWidget. 12 | */ 13 | constructor(port, url) { 14 | super(); 15 | this.id = port; 16 | this.title.label = `Dash (port: ${port})`; 17 | this.title.closable = true; 18 | this.addClass('jp-dashWidget'); 19 | // Add jp-IFrame class to keep drag events from being lost to the iframe 20 | // See https://github.com/phosphorjs/phosphor/issues/305 21 | // See https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/style/iframe.css#L17-L35 22 | this.addClass('jp-IFrame'); 23 | const serviceUrl = url; 24 | const iframeElement = document.createElement('iframe'); 25 | iframeElement.setAttribute('baseURI', serviceUrl); 26 | this.iframe = iframeElement; 27 | this.iframe.src = serviceUrl; 28 | this.iframe.id = 'iframe-' + this.id; 29 | this.node.appendChild(this.iframe); 30 | } 31 | /** 32 | * Handle update requests for the widget. 33 | */ 34 | onUpdateRequest(msg) { 35 | this.iframe.src += ''; 36 | } 37 | } 38 | function activate(app, restorer, notebooks, consoles) { 39 | // Declare a widget variable 40 | let widgets = new Map(); 41 | // Watch notebook creation 42 | notebooks.widgetAdded.connect((sender, nbPanel) => { 43 | // const session = nbPanel.session; 44 | const sessionContext = nbPanel.sessionContext; 45 | sessionContext.ready.then(() => { 46 | const session = sessionContext.session; 47 | let kernel = session.kernel; 48 | registerCommTarget(kernel, widgets, app); 49 | }); 50 | }); 51 | // Watch console creation 52 | consoles.widgetAdded.connect((sender, consolePanel) => { 53 | const sessionContext = consolePanel.sessionContext; 54 | sessionContext.ready.then(() => { 55 | const session = sessionContext.session; 56 | let kernel = session.kernel; 57 | registerCommTarget(kernel, widgets, app); 58 | }); 59 | }); 60 | } 61 | function registerCommTarget(kernel, widgets, app) { 62 | kernel.registerCommTarget('jupyter_dash', (comm, msg) => { 63 | comm.onMsg = (msg) => { 64 | let msgData = msg.content.data; 65 | if (msgData.type === 'show') { 66 | let widget; 67 | if (!widgets.has(msgData.port)) { 68 | // Create a new widget 69 | widget = new DashIFrameWidget(msgData.port, msgData.url); 70 | widget.update(); 71 | widgets.set(msgData.port, widget); 72 | // Add instance tracker stuff 73 | } 74 | else { 75 | widget = widgets.get(msgData.port); 76 | } 77 | if (!widget.isAttached) { 78 | // Attach the widget to the main work area 79 | // if it's not there 80 | app.shell.add(widget, 'main'); 81 | widget.update(); 82 | } 83 | else { 84 | // Refresh the widget 85 | widget.update(); 86 | } 87 | // Activate the widget 88 | app.shell.activateById(widget.id); 89 | } 90 | else if (msgData.type === 'base_url_request') { 91 | // Build server url and base subpath. 92 | const baseUrl = coreutils_1.PageConfig.getBaseUrl(); 93 | const baseSubpath = coreutils_1.PageConfig.getOption('baseUrl'); 94 | const n = baseUrl.lastIndexOf(baseSubpath); 95 | const serverUrl = baseUrl.slice(0, n); 96 | comm.send({ 97 | type: 'base_url_response', 98 | server_url: serverUrl, 99 | base_subpath: baseSubpath, 100 | frontend: "jupyterlab", 101 | }); 102 | } 103 | }; 104 | }); 105 | } 106 | /** 107 | * Initialization data for the jupyterlab-dash extension. 108 | */ 109 | const extension = { 110 | id: 'jupyterlab_dash', 111 | autoStart: true, 112 | requires: [application_1.ILayoutRestorer, notebook_1.INotebookTracker, console_1.IConsoleTracker], 113 | activate: activate 114 | }; 115 | exports.default = extension; 116 | -------------------------------------------------------------------------------- /extensions/jupyterlab/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jupyterlab-dash", 3 | "version": "0.4.2", 4 | "description": "A JupyterLab extensions for rendering Plotly Dash apps", 5 | "keywords": [ 6 | "jupyter", 7 | "jupyterlab", 8 | "jupyterlab-extension" 9 | ], 10 | "homepage": "https://github.com/plotly/jupyter-dash", 11 | "bugs": { 12 | "url": "https://github.com/plotly/jupyter-dash/issues" 13 | }, 14 | "license": "MIT", 15 | "author": "Plotly", 16 | "files": [ 17 | "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", 18 | "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}" 19 | ], 20 | "main": "lib/index.js", 21 | "types": "lib/index.d.ts", 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/plotly/jupyter-dash.git" 25 | }, 26 | "scripts": { 27 | "build": "tsc", 28 | "clean": "rimraf lib", 29 | "prepare": "npm run clean && npm run build", 30 | "prettier": "prettier --write '{!(package),src/**,!(lib)/**}{.js,.jsx,.ts,.tsx,.css,.json,.md}'", 31 | "watch": "tsc -w" 32 | }, 33 | "dependencies": { 34 | "@jupyterlab/application": "^2.0.0 || ^3.0.0", 35 | "@jupyterlab/notebook": "^2.0.0 || ^3.0.0", 36 | "@jupyterlab/console": "^2.0.0 || ^3.0.0" 37 | }, 38 | "devDependencies": { 39 | "prettier": "2.0.5", 40 | "rimraf": "3.0.2", 41 | "typescript": "3.9.3" 42 | }, 43 | "jupyterlab": { 44 | "extension": true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /extensions/jupyterlab/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ILayoutRestorer, 3 | JupyterFrontEnd, 4 | JupyterFrontEndPlugin 5 | } from '@jupyterlab/application'; 6 | 7 | import { PageConfig } from '@jupyterlab/coreutils'; 8 | 9 | import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook'; 10 | 11 | import { KernelMessage, Kernel } from '@jupyterlab/services'; 12 | 13 | import { IConsoleTracker } from '@jupyterlab/console'; 14 | 15 | import { Message } from '@lumino/messaging'; 16 | 17 | import { Widget } from '@lumino/widgets'; 18 | 19 | import '../style/index.css'; 20 | 21 | class DashIFrameWidget extends Widget { 22 | /** 23 | * Construct a new DashIFrameWidget. 24 | */ 25 | constructor(port: string, url: string) { 26 | super(); 27 | 28 | this.id = port; 29 | this.title.label = `Dash (port: ${port})`; 30 | this.title.closable = true; 31 | this.addClass('jp-dashWidget'); 32 | 33 | // Add jp-IFrame class to keep drag events from being lost to the iframe 34 | // See https://github.com/phosphorjs/phosphor/issues/305 35 | // See https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/style/iframe.css#L17-L35 36 | this.addClass('jp-IFrame'); 37 | 38 | const serviceUrl = url; 39 | const iframeElement = document.createElement('iframe'); 40 | iframeElement.setAttribute('baseURI', serviceUrl); 41 | this.iframe = iframeElement; 42 | this.iframe.src = serviceUrl; 43 | this.iframe.id = 'iframe-' + this.id; 44 | 45 | this.node.appendChild(this.iframe); 46 | } 47 | 48 | /** 49 | * The image element associated with the widget. 50 | */ 51 | readonly iframe: HTMLIFrameElement; 52 | 53 | /** 54 | * Handle update requests for the widget. 55 | */ 56 | onUpdateRequest(msg: Message): void { 57 | this.iframe.src += ''; 58 | } 59 | } 60 | 61 | interface DashMessageData { 62 | type: string; 63 | port: string; 64 | url: string; 65 | } 66 | 67 | function activate( 68 | app: JupyterFrontEnd, 69 | restorer: ILayoutRestorer, 70 | notebooks: INotebookTracker, 71 | consoles: IConsoleTracker 72 | ) { 73 | 74 | // Declare a widget variable 75 | let widgets = new Map(); 76 | 77 | // Watch notebook creation 78 | notebooks.widgetAdded.connect((sender, nbPanel: NotebookPanel) => { 79 | // const session = nbPanel.session; 80 | const sessionContext = nbPanel.sessionContext; 81 | sessionContext.ready.then(() => { 82 | const session = sessionContext.session; 83 | let kernel = session.kernel; 84 | registerCommTarget(kernel, widgets, app); 85 | }) 86 | }); 87 | 88 | // Watch console creation 89 | consoles.widgetAdded.connect((sender, consolePanel) => { 90 | const sessionContext = consolePanel.sessionContext; 91 | sessionContext.ready.then(() => { 92 | const session = sessionContext.session; 93 | let kernel = session.kernel; 94 | registerCommTarget(kernel, widgets, app); 95 | }) 96 | }); 97 | } 98 | 99 | function registerCommTarget( 100 | kernel: Kernel.IKernelConnection, 101 | widgets: Map, 102 | app: JupyterFrontEnd 103 | ) { 104 | kernel.registerCommTarget( 105 | 'jupyter_dash', 106 | (comm: Kernel.IComm, msg: KernelMessage.ICommOpenMsg) => { 107 | comm.onMsg = (msg: KernelMessage.ICommMsgMsg) => { 108 | let msgData = (msg.content.data as unknown) as DashMessageData; 109 | if (msgData.type === 'show') { 110 | let widget: DashIFrameWidget; 111 | if (!widgets.has(msgData.port)) { 112 | // Create a new widget 113 | widget = new DashIFrameWidget(msgData.port, msgData.url); 114 | widget.update(); 115 | widgets.set(msgData.port, widget); 116 | 117 | // Add instance tracker stuff 118 | } else { 119 | widget = widgets.get(msgData.port); 120 | } 121 | 122 | if (!widget.isAttached) { 123 | // Attach the widget to the main work area 124 | // if it's not there 125 | app.shell.add(widget, 'main'); 126 | widget.update(); 127 | } else { 128 | // Refresh the widget 129 | widget.update(); 130 | } 131 | 132 | // Activate the widget 133 | app.shell.activateById(widget.id); 134 | } else if (msgData.type === 'base_url_request') { 135 | 136 | // Build server url and base subpath. 137 | const baseUrl = PageConfig.getBaseUrl(); 138 | const baseSubpath = PageConfig.getOption('baseUrl'); 139 | const n = baseUrl.lastIndexOf(baseSubpath) 140 | const serverUrl = baseUrl.slice(0, n) 141 | comm.send({ 142 | type: 'base_url_response', 143 | server_url: serverUrl, 144 | base_subpath: baseSubpath, 145 | frontend: "jupyterlab", 146 | }); 147 | } 148 | }; 149 | } 150 | ); 151 | } 152 | 153 | /** 154 | * Initialization data for the jupyterlab-dash extension. 155 | */ 156 | const extension: JupyterFrontEndPlugin = { 157 | id: 'jupyterlab_dash', 158 | autoStart: true, 159 | requires: [ILayoutRestorer, INotebookTracker, IConsoleTracker], 160 | activate: activate 161 | }; 162 | 163 | export default extension; 164 | -------------------------------------------------------------------------------- /extensions/jupyterlab/style/index.css: -------------------------------------------------------------------------------- 1 | .jp-dashWidget iframe { 2 | height: 100%; 3 | width: 100%; 4 | padding: 20px; 5 | box-sizing: border-box; 6 | } 7 | -------------------------------------------------------------------------------- /extensions/jupyterlab/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "lib": ["es2015", "dom"], 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "noEmitOnError": true, 8 | "noUnusedLocals": true, 9 | "outDir": "lib", 10 | "rootDir": "src", 11 | "strict": true, 12 | "strictNullChecks": false, 13 | "target": "es2015", 14 | "types": [], 15 | "esModuleInterop": true 16 | }, 17 | "include": ["src/*"] 18 | } 19 | -------------------------------------------------------------------------------- /extensions/jupyterlab/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/runtime@^7.1.2": 6 | version "7.9.2" 7 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" 8 | integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== 9 | dependencies: 10 | regenerator-runtime "^0.13.4" 11 | 12 | "@blueprintjs/core@^3.36.0", "@blueprintjs/core@^3.38.0": 13 | version "3.38.0" 14 | resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.38.0.tgz#9b8eb086e22b424153fa0e1483c4c8abd9e6c8e0" 15 | integrity sha512-U4yf6B+SbCspNDuvSU2/pl+a80hr9iQgyf2cJ2cOz5It+RV8M+dg9BgB1WaZgqdWgxx/4+A425X5zt2Jw9xalw== 16 | dependencies: 17 | "@blueprintjs/icons" "^3.24.0" 18 | "@types/dom4" "^2.0.1" 19 | classnames "^2.2" 20 | dom4 "^2.1.5" 21 | normalize.css "^8.0.1" 22 | popper.js "^1.16.1" 23 | react-lifecycles-compat "^3.0.4" 24 | react-popper "^1.3.7" 25 | react-transition-group "^2.9.0" 26 | resize-observer-polyfill "^1.5.1" 27 | tslib "~1.13.0" 28 | 29 | "@blueprintjs/icons@^3.24.0": 30 | version "3.24.0" 31 | resolved "https://registry.yarnpkg.com/@blueprintjs/icons/-/icons-3.24.0.tgz#aa7e6042e40806d22f85da8d62990ff0296adcf2" 32 | integrity sha512-OvDDI5EUueS1Y3t594iS8LAGoHhLhYjC2GuN/01a85n+ASLSp0jf0/+uix2JeCOj41iTdRRCINbWuRwVQNNGPw== 33 | dependencies: 34 | classnames "^2.2" 35 | tslib "~1.13.0" 36 | 37 | "@blueprintjs/select@^3.15.0": 38 | version "3.15.2" 39 | resolved "https://registry.yarnpkg.com/@blueprintjs/select/-/select-3.15.2.tgz#89237fb129076277be98535a4e3c0e053ad4f83a" 40 | integrity sha512-3uY89fSxH4zrvZObDx1SEr/K3KizjgY7Z/005/acFkSN+2GFSD9GU5rmwEQfBDdHk5VjqHEWykD5c8YySH1nDA== 41 | dependencies: 42 | "@blueprintjs/core" "^3.38.0" 43 | classnames "^2.2" 44 | tslib "~1.13.0" 45 | 46 | "@fortawesome/fontawesome-free@^5.12.0": 47 | version "5.13.0" 48 | resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz#fcb113d1aca4b471b709e8c9c168674fbd6e06d9" 49 | integrity sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg== 50 | 51 | "@jupyterlab/application@^2.0.0 || ^3.0.0": 52 | version "3.0.3" 53 | resolved "https://registry.yarnpkg.com/@jupyterlab/application/-/application-3.0.3.tgz#9fc6fe9873842d5a16b205ff9a8bedf76b4456e5" 54 | integrity sha512-aJDG5A/Rc1bWnKtoMM77k6hmjZrf0jRioYYFSbZrJ63k0KG27lCYR7EK1XNucRPMw2qz3IolfYJFPf+quYW9Iw== 55 | dependencies: 56 | "@fortawesome/fontawesome-free" "^5.12.0" 57 | "@jupyterlab/apputils" "^3.0.2" 58 | "@jupyterlab/coreutils" "^5.0.1" 59 | "@jupyterlab/docregistry" "^3.0.3" 60 | "@jupyterlab/rendermime" "^3.0.3" 61 | "@jupyterlab/rendermime-interfaces" "^3.0.2" 62 | "@jupyterlab/services" "^6.0.2" 63 | "@jupyterlab/statedb" "^3.0.1" 64 | "@jupyterlab/translation" "^3.0.2" 65 | "@jupyterlab/ui-components" "^3.0.2" 66 | "@lumino/algorithm" "^1.3.3" 67 | "@lumino/application" "^1.13.1" 68 | "@lumino/commands" "^1.12.0" 69 | "@lumino/coreutils" "^1.5.3" 70 | "@lumino/disposable" "^1.4.3" 71 | "@lumino/messaging" "^1.4.3" 72 | "@lumino/polling" "^1.3.3" 73 | "@lumino/properties" "^1.2.3" 74 | "@lumino/signaling" "^1.4.3" 75 | "@lumino/widgets" "^1.16.1" 76 | 77 | "@jupyterlab/apputils@^3.0.2": 78 | version "3.0.2" 79 | resolved "https://registry.yarnpkg.com/@jupyterlab/apputils/-/apputils-3.0.2.tgz#e45e6b65c9d9dea0d0cbc8074a809ecc960e8bbe" 80 | integrity sha512-nTXwpRUPSVR3yevQyGZH6kKsl41Df3nkKCjp8nAqwAPjcwv+nuxLIwnBQP1BFZ+JfIKn18aoZ8ULoH79qasKNg== 81 | dependencies: 82 | "@jupyterlab/coreutils" "^5.0.1" 83 | "@jupyterlab/services" "^6.0.2" 84 | "@jupyterlab/settingregistry" "^3.0.1" 85 | "@jupyterlab/statedb" "^3.0.1" 86 | "@jupyterlab/translation" "^3.0.2" 87 | "@jupyterlab/ui-components" "^3.0.2" 88 | "@lumino/algorithm" "^1.3.3" 89 | "@lumino/commands" "^1.12.0" 90 | "@lumino/coreutils" "^1.5.3" 91 | "@lumino/disposable" "^1.4.3" 92 | "@lumino/domutils" "^1.2.3" 93 | "@lumino/messaging" "^1.4.3" 94 | "@lumino/properties" "^1.2.3" 95 | "@lumino/signaling" "^1.4.3" 96 | "@lumino/virtualdom" "^1.8.0" 97 | "@lumino/widgets" "^1.16.1" 98 | "@types/react" "^17.0.0" 99 | buffer "^5.6.0" 100 | react "^17.0.1" 101 | react-dom "^17.0.1" 102 | sanitize-html "~1.27.4" 103 | url "^0.11.0" 104 | 105 | "@jupyterlab/attachments@^3.0.3": 106 | version "3.0.3" 107 | resolved "https://registry.yarnpkg.com/@jupyterlab/attachments/-/attachments-3.0.3.tgz#63294c9bc05fa17bec0144a6ce5e4c575b251fb9" 108 | integrity sha512-U6d6NHXcujCefnQuSY/X0cwPpxRDzMzQbHci5uixdWpgt3wJbmTm5tVahgEUZdsTj2ne0gcEsUOeQBeDy6KjBg== 109 | dependencies: 110 | "@jupyterlab/nbformat" "^3.0.1" 111 | "@jupyterlab/observables" "^4.0.1" 112 | "@jupyterlab/rendermime" "^3.0.3" 113 | "@jupyterlab/rendermime-interfaces" "^3.0.2" 114 | "@lumino/disposable" "^1.4.3" 115 | "@lumino/signaling" "^1.4.3" 116 | 117 | "@jupyterlab/cells@^3.0.3": 118 | version "3.0.3" 119 | resolved "https://registry.yarnpkg.com/@jupyterlab/cells/-/cells-3.0.3.tgz#ad9508ce4438f18a92d1af1cc1ffeca0b89f632c" 120 | integrity sha512-NufBnb7y3BiuXZTckj9U6ZOe0gBRMAaSpLXnC04XqtHHrJziZDc0PuiZHEZS7umMdoB04HKui/7/G9y6zjpN3A== 121 | dependencies: 122 | "@jupyterlab/apputils" "^3.0.2" 123 | "@jupyterlab/attachments" "^3.0.3" 124 | "@jupyterlab/codeeditor" "^3.0.2" 125 | "@jupyterlab/codemirror" "^3.0.2" 126 | "@jupyterlab/coreutils" "^5.0.1" 127 | "@jupyterlab/filebrowser" "^3.0.3" 128 | "@jupyterlab/nbformat" "^3.0.1" 129 | "@jupyterlab/observables" "^4.0.1" 130 | "@jupyterlab/outputarea" "^3.0.3" 131 | "@jupyterlab/rendermime" "^3.0.3" 132 | "@jupyterlab/services" "^6.0.2" 133 | "@jupyterlab/ui-components" "^3.0.2" 134 | "@lumino/algorithm" "^1.3.3" 135 | "@lumino/coreutils" "^1.5.3" 136 | "@lumino/dragdrop" "^1.7.1" 137 | "@lumino/messaging" "^1.4.3" 138 | "@lumino/signaling" "^1.4.3" 139 | "@lumino/virtualdom" "^1.8.0" 140 | "@lumino/widgets" "^1.16.1" 141 | react "^17.0.1" 142 | 143 | "@jupyterlab/codeeditor@^3.0.2": 144 | version "3.0.2" 145 | resolved "https://registry.yarnpkg.com/@jupyterlab/codeeditor/-/codeeditor-3.0.2.tgz#45d88eb229f1a57177dc9865f92dcf9cb7f70263" 146 | integrity sha512-0pF/B1G+8l87QRcBCOFWieXGVyuJnTYO2Vp8R/jBKV0hqHljAgao40o1mInt1xGGSkTOcAydETbXEt1J4OCWuA== 147 | dependencies: 148 | "@jupyterlab/coreutils" "^5.0.1" 149 | "@jupyterlab/nbformat" "^3.0.1" 150 | "@jupyterlab/observables" "^4.0.1" 151 | "@jupyterlab/translation" "^3.0.2" 152 | "@jupyterlab/ui-components" "^3.0.2" 153 | "@lumino/coreutils" "^1.5.3" 154 | "@lumino/disposable" "^1.4.3" 155 | "@lumino/dragdrop" "^1.7.1" 156 | "@lumino/messaging" "^1.4.3" 157 | "@lumino/signaling" "^1.4.3" 158 | "@lumino/widgets" "^1.16.1" 159 | 160 | "@jupyterlab/codemirror@^3.0.2": 161 | version "3.0.2" 162 | resolved "https://registry.yarnpkg.com/@jupyterlab/codemirror/-/codemirror-3.0.2.tgz#931bfb8c68aa3daa08cee5f5335c177878b86298" 163 | integrity sha512-i6IhCHDTcTCrNK58I4OjNX9S4erkKu285c47hiJTHxO03YFHOjLtl+i0Ly76R8Qc1+3rpyQxztXve0ZA/K+apQ== 164 | dependencies: 165 | "@jupyterlab/apputils" "^3.0.2" 166 | "@jupyterlab/codeeditor" "^3.0.2" 167 | "@jupyterlab/coreutils" "^5.0.1" 168 | "@jupyterlab/nbformat" "^3.0.1" 169 | "@jupyterlab/observables" "^4.0.1" 170 | "@jupyterlab/statusbar" "^3.0.2" 171 | "@jupyterlab/translation" "^3.0.2" 172 | "@lumino/algorithm" "^1.3.3" 173 | "@lumino/commands" "^1.12.0" 174 | "@lumino/coreutils" "^1.5.3" 175 | "@lumino/disposable" "^1.4.3" 176 | "@lumino/polling" "^1.3.3" 177 | "@lumino/signaling" "^1.4.3" 178 | "@lumino/widgets" "^1.16.1" 179 | codemirror "~5.57.0" 180 | react "^17.0.1" 181 | 182 | "@jupyterlab/console@^2.0.0 || ^3.0.0": 183 | version "3.0.3" 184 | resolved "https://registry.yarnpkg.com/@jupyterlab/console/-/console-3.0.3.tgz#f041af90d798258de8e6cd1199173e5e0195268e" 185 | integrity sha512-Pk5eLlsDHppEGRXmvbhUdAByFizU8vxue3CNmmLW1dqBulCoCLMRVdBv+MlbMKhrrKQwvRshQ5u1zz8OMDSBkQ== 186 | dependencies: 187 | "@jupyterlab/apputils" "^3.0.2" 188 | "@jupyterlab/cells" "^3.0.3" 189 | "@jupyterlab/codeeditor" "^3.0.2" 190 | "@jupyterlab/coreutils" "^5.0.1" 191 | "@jupyterlab/nbformat" "^3.0.1" 192 | "@jupyterlab/observables" "^4.0.1" 193 | "@jupyterlab/rendermime" "^3.0.3" 194 | "@jupyterlab/services" "^6.0.2" 195 | "@jupyterlab/translation" "^3.0.2" 196 | "@jupyterlab/ui-components" "^3.0.2" 197 | "@lumino/algorithm" "^1.3.3" 198 | "@lumino/coreutils" "^1.5.3" 199 | "@lumino/disposable" "^1.4.3" 200 | "@lumino/dragdrop" "^1.7.1" 201 | "@lumino/messaging" "^1.4.3" 202 | "@lumino/signaling" "^1.4.3" 203 | "@lumino/widgets" "^1.16.1" 204 | 205 | "@jupyterlab/coreutils@^5.0.1": 206 | version "5.0.1" 207 | resolved "https://registry.yarnpkg.com/@jupyterlab/coreutils/-/coreutils-5.0.1.tgz#f50305be93d2e0f1e60546f816d103229a92ba24" 208 | integrity sha512-eYjEtZAgoRx0UJY/wfdm7Og+Z1dkcmEjTL5J6MfTROe164F6OCodEFbKECIyVfGt+hoAOiqs3Jg9cPqMw+DA3Q== 209 | dependencies: 210 | "@lumino/coreutils" "^1.5.3" 211 | "@lumino/disposable" "^1.4.3" 212 | "@lumino/signaling" "^1.4.3" 213 | minimist "~1.2.0" 214 | moment "^2.24.0" 215 | path-browserify "^1.0.0" 216 | url-parse "~1.4.7" 217 | 218 | "@jupyterlab/docmanager@^3.0.3": 219 | version "3.0.3" 220 | resolved "https://registry.yarnpkg.com/@jupyterlab/docmanager/-/docmanager-3.0.3.tgz#41e89a8857500501f4e15679fd8fb0379c4db1dd" 221 | integrity sha512-6zId9EWd/X/wlJ7Bhppsdn/5BVuAvMWFSGmv0FtjVPXbPoGN2jZviPwlux4o8cUFS6uj8s0U9eaFfwM5juh9qA== 222 | dependencies: 223 | "@jupyterlab/apputils" "^3.0.2" 224 | "@jupyterlab/coreutils" "^5.0.1" 225 | "@jupyterlab/docregistry" "^3.0.3" 226 | "@jupyterlab/services" "^6.0.2" 227 | "@jupyterlab/statusbar" "^3.0.2" 228 | "@jupyterlab/translation" "^3.0.2" 229 | "@lumino/algorithm" "^1.3.3" 230 | "@lumino/coreutils" "^1.5.3" 231 | "@lumino/disposable" "^1.4.3" 232 | "@lumino/messaging" "^1.4.3" 233 | "@lumino/properties" "^1.2.3" 234 | "@lumino/signaling" "^1.4.3" 235 | "@lumino/widgets" "^1.16.1" 236 | react "^17.0.1" 237 | 238 | "@jupyterlab/docregistry@^3.0.3": 239 | version "3.0.3" 240 | resolved "https://registry.yarnpkg.com/@jupyterlab/docregistry/-/docregistry-3.0.3.tgz#7a99ae8ef7f815e4fe07cf457d83c4ee3ca6589f" 241 | integrity sha512-9qs8suB5fWpzfR4uUemR2lbEvOH9ROuSWNGZxuO8+mN6XEnI+PLbGDO2WuctGxXsWgkg/6foOxIl6xoceCo9vg== 242 | dependencies: 243 | "@jupyterlab/apputils" "^3.0.2" 244 | "@jupyterlab/codeeditor" "^3.0.2" 245 | "@jupyterlab/codemirror" "^3.0.2" 246 | "@jupyterlab/coreutils" "^5.0.1" 247 | "@jupyterlab/observables" "^4.0.1" 248 | "@jupyterlab/rendermime" "^3.0.3" 249 | "@jupyterlab/rendermime-interfaces" "^3.0.2" 250 | "@jupyterlab/services" "^6.0.2" 251 | "@jupyterlab/translation" "^3.0.2" 252 | "@jupyterlab/ui-components" "^3.0.2" 253 | "@lumino/algorithm" "^1.3.3" 254 | "@lumino/coreutils" "^1.5.3" 255 | "@lumino/disposable" "^1.4.3" 256 | "@lumino/messaging" "^1.4.3" 257 | "@lumino/signaling" "^1.4.3" 258 | "@lumino/widgets" "^1.16.1" 259 | 260 | "@jupyterlab/filebrowser@^3.0.3": 261 | version "3.0.3" 262 | resolved "https://registry.yarnpkg.com/@jupyterlab/filebrowser/-/filebrowser-3.0.3.tgz#ca00522719542324136fae3bc83645c8e0004989" 263 | integrity sha512-XlOqvk7XinLadd23W45jI9QqRSpPetxwItyatvMqosR+jtSAuUJBBcFpYfu/TiSItBzKwZ8JuDJYlTJ399O7Wg== 264 | dependencies: 265 | "@jupyterlab/apputils" "^3.0.2" 266 | "@jupyterlab/coreutils" "^5.0.1" 267 | "@jupyterlab/docmanager" "^3.0.3" 268 | "@jupyterlab/docregistry" "^3.0.3" 269 | "@jupyterlab/services" "^6.0.2" 270 | "@jupyterlab/statedb" "^3.0.1" 271 | "@jupyterlab/statusbar" "^3.0.2" 272 | "@jupyterlab/translation" "^3.0.2" 273 | "@jupyterlab/ui-components" "^3.0.2" 274 | "@lumino/algorithm" "^1.3.3" 275 | "@lumino/coreutils" "^1.5.3" 276 | "@lumino/disposable" "^1.4.3" 277 | "@lumino/domutils" "^1.2.3" 278 | "@lumino/dragdrop" "^1.7.1" 279 | "@lumino/messaging" "^1.4.3" 280 | "@lumino/polling" "^1.3.3" 281 | "@lumino/signaling" "^1.4.3" 282 | "@lumino/virtualdom" "^1.8.0" 283 | "@lumino/widgets" "^1.16.1" 284 | react "^17.0.1" 285 | 286 | "@jupyterlab/nbformat@^3.0.1": 287 | version "3.0.1" 288 | resolved "https://registry.yarnpkg.com/@jupyterlab/nbformat/-/nbformat-3.0.1.tgz#56c18449fb6100dd85f22ee73e252ab27eb17dcd" 289 | integrity sha512-cojRKJPoCPei8XiHqGx9IwjMI5llOumrSSYzyBR5qm/NYGOG1mgFwNW2aTf+MoUrZwhpQo8oW27p/W2k2zQAbQ== 290 | dependencies: 291 | "@lumino/coreutils" "^1.5.3" 292 | 293 | "@jupyterlab/notebook@^2.0.0 || ^3.0.0": 294 | version "3.0.3" 295 | resolved "https://registry.yarnpkg.com/@jupyterlab/notebook/-/notebook-3.0.3.tgz#c6ad8091650cee226830c5392b6dd7a62186c04d" 296 | integrity sha512-ennnJaO+fW4Bk6ibotHIYSkb3M3G8NEr+BvrSfIQizlagcuquvk+INO5m2fVL1G623dRaR+2WqNE0UkxK0dBJw== 297 | dependencies: 298 | "@jupyterlab/apputils" "^3.0.2" 299 | "@jupyterlab/cells" "^3.0.3" 300 | "@jupyterlab/codeeditor" "^3.0.2" 301 | "@jupyterlab/coreutils" "^5.0.1" 302 | "@jupyterlab/docregistry" "^3.0.3" 303 | "@jupyterlab/nbformat" "^3.0.1" 304 | "@jupyterlab/observables" "^4.0.1" 305 | "@jupyterlab/rendermime" "^3.0.3" 306 | "@jupyterlab/services" "^6.0.2" 307 | "@jupyterlab/statusbar" "^3.0.2" 308 | "@jupyterlab/translation" "^3.0.2" 309 | "@jupyterlab/ui-components" "^3.0.2" 310 | "@lumino/algorithm" "^1.3.3" 311 | "@lumino/coreutils" "^1.5.3" 312 | "@lumino/domutils" "^1.2.3" 313 | "@lumino/dragdrop" "^1.7.1" 314 | "@lumino/messaging" "^1.4.3" 315 | "@lumino/properties" "^1.2.3" 316 | "@lumino/signaling" "^1.4.3" 317 | "@lumino/virtualdom" "^1.8.0" 318 | "@lumino/widgets" "^1.16.1" 319 | react "^17.0.1" 320 | 321 | "@jupyterlab/observables@^4.0.1": 322 | version "4.0.1" 323 | resolved "https://registry.yarnpkg.com/@jupyterlab/observables/-/observables-4.0.1.tgz#d767fc0831a2ae32ef772492fffc77dd0ffaabe9" 324 | integrity sha512-f+y7w/eBQfw2AWe9cwa6wj5sqKxJMJYlzjUuSlXfSehKp7SR9s+L3d+JOBmfbBF5WHvaF9XA4cGkZM/HZt8ARQ== 325 | dependencies: 326 | "@lumino/algorithm" "^1.3.3" 327 | "@lumino/coreutils" "^1.5.3" 328 | "@lumino/disposable" "^1.4.3" 329 | "@lumino/messaging" "^1.4.3" 330 | "@lumino/signaling" "^1.4.3" 331 | 332 | "@jupyterlab/outputarea@^3.0.3": 333 | version "3.0.3" 334 | resolved "https://registry.yarnpkg.com/@jupyterlab/outputarea/-/outputarea-3.0.3.tgz#4ca2f3857db3611c7ab208a5fef28b35c5b5f53a" 335 | integrity sha512-NBB0aJE0IVPNAEiLj8shLKAX9oAsl1oreKcfd/cfYYQFflKHpWTxlzA25NNv7xcfVqT78i704FemW/k/9kPozA== 336 | dependencies: 337 | "@jupyterlab/apputils" "^3.0.2" 338 | "@jupyterlab/nbformat" "^3.0.1" 339 | "@jupyterlab/observables" "^4.0.1" 340 | "@jupyterlab/rendermime" "^3.0.3" 341 | "@jupyterlab/rendermime-interfaces" "^3.0.2" 342 | "@jupyterlab/services" "^6.0.2" 343 | "@lumino/algorithm" "^1.3.3" 344 | "@lumino/coreutils" "^1.5.3" 345 | "@lumino/disposable" "^1.4.3" 346 | "@lumino/messaging" "^1.4.3" 347 | "@lumino/properties" "^1.2.3" 348 | "@lumino/signaling" "^1.4.3" 349 | "@lumino/widgets" "^1.16.1" 350 | resize-observer-polyfill "^1.5.1" 351 | 352 | "@jupyterlab/rendermime-interfaces@^3.0.2": 353 | version "3.0.2" 354 | resolved "https://registry.yarnpkg.com/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-3.0.2.tgz#0af6022045a12286ceb6cd732c2a84e322d26d5f" 355 | integrity sha512-BxGXIrGziW+9fvzDF57F4kebJz9p1SWH7Id6VNI21JzCZxJkz7wZpbeUfHzpUiXIh+qogEXEESKKuQg9CzNyqw== 356 | dependencies: 357 | "@jupyterlab/translation" "^3.0.2" 358 | "@lumino/coreutils" "^1.5.3" 359 | "@lumino/widgets" "^1.16.1" 360 | 361 | "@jupyterlab/rendermime@^3.0.3": 362 | version "3.0.3" 363 | resolved "https://registry.yarnpkg.com/@jupyterlab/rendermime/-/rendermime-3.0.3.tgz#f4a213e7d42e253dc02dcb536b00843690adaf92" 364 | integrity sha512-s72CajNpj0UEe4rJVnm5pVbf/jZXc3c5YuXF39BTxpGtsg0uqSysPpYtc1/VjsBoS3R5Bc73P3NIEvOzl6G5cA== 365 | dependencies: 366 | "@jupyterlab/apputils" "^3.0.2" 367 | "@jupyterlab/codemirror" "^3.0.2" 368 | "@jupyterlab/coreutils" "^5.0.1" 369 | "@jupyterlab/nbformat" "^3.0.1" 370 | "@jupyterlab/observables" "^4.0.1" 371 | "@jupyterlab/rendermime-interfaces" "^3.0.2" 372 | "@jupyterlab/services" "^6.0.2" 373 | "@jupyterlab/translation" "^3.0.2" 374 | "@lumino/algorithm" "^1.3.3" 375 | "@lumino/coreutils" "^1.5.3" 376 | "@lumino/messaging" "^1.4.3" 377 | "@lumino/signaling" "^1.4.3" 378 | "@lumino/widgets" "^1.16.1" 379 | lodash.escape "^4.0.1" 380 | marked "^1.1.1" 381 | 382 | "@jupyterlab/services@^6.0.2": 383 | version "6.0.2" 384 | resolved "https://registry.yarnpkg.com/@jupyterlab/services/-/services-6.0.2.tgz#ca9f5f8b6c69013d9d52a15e034eb8b7935fdc5e" 385 | integrity sha512-J0wghVeqMlG71VXkOhlh3ZcyG787wzz9hSFHMGu/1ATlIDtn9z8dbdCAn92rd12jD1nDX1L2KcyjH5pLT+CKeA== 386 | dependencies: 387 | "@jupyterlab/coreutils" "^5.0.1" 388 | "@jupyterlab/nbformat" "^3.0.1" 389 | "@jupyterlab/observables" "^4.0.1" 390 | "@jupyterlab/settingregistry" "^3.0.1" 391 | "@jupyterlab/statedb" "^3.0.1" 392 | "@lumino/algorithm" "^1.3.3" 393 | "@lumino/coreutils" "^1.5.3" 394 | "@lumino/disposable" "^1.4.3" 395 | "@lumino/polling" "^1.3.3" 396 | "@lumino/signaling" "^1.4.3" 397 | node-fetch "^2.6.0" 398 | ws "^7.2.0" 399 | 400 | "@jupyterlab/settingregistry@^3.0.1": 401 | version "3.0.1" 402 | resolved "https://registry.yarnpkg.com/@jupyterlab/settingregistry/-/settingregistry-3.0.1.tgz#8462a3a142f31641e45ed45cd5b1712fcd5fa99e" 403 | integrity sha512-Em/gDygAojndYo7qR4jG0EKCInVQEhTRAnTE/sOYXhwD74Ib3ppFl67N8CvJSr8+jSFhDrLyyVaevI1o6fep9w== 404 | dependencies: 405 | "@jupyterlab/statedb" "^3.0.1" 406 | "@lumino/commands" "^1.12.0" 407 | "@lumino/coreutils" "^1.5.3" 408 | "@lumino/disposable" "^1.4.3" 409 | "@lumino/signaling" "^1.4.3" 410 | ajv "^6.12.3" 411 | json5 "^2.1.1" 412 | 413 | "@jupyterlab/statedb@^3.0.1": 414 | version "3.0.1" 415 | resolved "https://registry.yarnpkg.com/@jupyterlab/statedb/-/statedb-3.0.1.tgz#8b6c757e20a8072c5276019a07c65725a9829aa9" 416 | integrity sha512-+00qBVlboCz945o2CFXrCUJ9oyKcAviA7+dlnE92N5UWBelp8dulMAgWNIW8Uew5O0mvbb1dVAcN9bnbLphGfw== 417 | dependencies: 418 | "@lumino/commands" "^1.12.0" 419 | "@lumino/coreutils" "^1.5.3" 420 | "@lumino/disposable" "^1.4.3" 421 | "@lumino/properties" "^1.2.3" 422 | "@lumino/signaling" "^1.4.3" 423 | 424 | "@jupyterlab/statusbar@^3.0.2": 425 | version "3.0.2" 426 | resolved "https://registry.yarnpkg.com/@jupyterlab/statusbar/-/statusbar-3.0.2.tgz#135ea22d62b79de3e29657abd9569297bbe39203" 427 | integrity sha512-71sx7GRR4FGJExBjBB8TMD63h5wv09aRLO+cQj3xMygG47EX9TaW2Q8zAq4ZQM400UNAh/NGVmr7P7EBdH8jhg== 428 | dependencies: 429 | "@jupyterlab/apputils" "^3.0.2" 430 | "@jupyterlab/codeeditor" "^3.0.2" 431 | "@jupyterlab/coreutils" "^5.0.1" 432 | "@jupyterlab/services" "^6.0.2" 433 | "@jupyterlab/translation" "^3.0.2" 434 | "@jupyterlab/ui-components" "^3.0.2" 435 | "@lumino/algorithm" "^1.3.3" 436 | "@lumino/coreutils" "^1.5.3" 437 | "@lumino/disposable" "^1.4.3" 438 | "@lumino/messaging" "^1.4.3" 439 | "@lumino/signaling" "^1.4.3" 440 | "@lumino/widgets" "^1.16.1" 441 | csstype "~3.0.3" 442 | react "^17.0.1" 443 | typestyle "^2.0.4" 444 | 445 | "@jupyterlab/translation@^3.0.2": 446 | version "3.0.2" 447 | resolved "https://registry.yarnpkg.com/@jupyterlab/translation/-/translation-3.0.2.tgz#478c1eb70c0f730cf1061a92443e5371a823295c" 448 | integrity sha512-OAA3+aD5pxXroB2z3M0xXWRJn246aooAXiPV7lQFFN1IR2Aovb+sBB61TQr+sjqDpHfVA9qADC65RIsr3XOmoA== 449 | dependencies: 450 | "@jupyterlab/coreutils" "^5.0.1" 451 | "@jupyterlab/services" "^6.0.2" 452 | "@jupyterlab/statedb" "^3.0.1" 453 | "@lumino/coreutils" "^1.5.3" 454 | 455 | "@jupyterlab/ui-components@^3.0.2": 456 | version "3.0.2" 457 | resolved "https://registry.yarnpkg.com/@jupyterlab/ui-components/-/ui-components-3.0.2.tgz#f6b87e352446a143d5d76c69d3c7796787605e65" 458 | integrity sha512-QfTMwAMDfHNtJZ0+zCeW8EXPlcPyGKooiMCmZXd1onFIxSpg/mdwV231uiakwARt3on+XBT8JrMgoSf03ywV6w== 459 | dependencies: 460 | "@blueprintjs/core" "^3.36.0" 461 | "@blueprintjs/select" "^3.15.0" 462 | "@jupyterlab/coreutils" "^5.0.1" 463 | "@lumino/coreutils" "^1.5.3" 464 | "@lumino/signaling" "^1.4.3" 465 | "@lumino/virtualdom" "^1.8.0" 466 | "@lumino/widgets" "^1.16.1" 467 | react "^17.0.1" 468 | react-dom "^17.0.1" 469 | typestyle "^2.0.4" 470 | 471 | "@lumino/algorithm@^1.3.3": 472 | version "1.3.3" 473 | resolved "https://registry.yarnpkg.com/@lumino/algorithm/-/algorithm-1.3.3.tgz#fdf4daa407a1ce6f233e173add6a2dda0c99eef4" 474 | integrity sha512-I2BkssbOSLq3rDjgAC3fzf/zAIwkRUnAh60MO0lYcaFdSGyI15w4K3gwZHGIO0p9cKEiNHLXKEODGmOjMLOQ3g== 475 | 476 | "@lumino/application@^1.13.1": 477 | version "1.15.0" 478 | resolved "https://registry.yarnpkg.com/@lumino/application/-/application-1.15.0.tgz#8b7e5142bc6d38d1300164507e0a214a55ea6d05" 479 | integrity sha512-W/12+UFk1oBdJ793L3NegQvt0T355k64fPmDVzPhM48TW8vM/0tDc+zBx1KShn52eRMTrVBDc2cG5t6C5/XF1w== 480 | dependencies: 481 | "@lumino/commands" "^1.12.0" 482 | "@lumino/coreutils" "^1.5.3" 483 | "@lumino/widgets" "^1.18.0" 484 | 485 | "@lumino/collections@^1.3.3": 486 | version "1.3.3" 487 | resolved "https://registry.yarnpkg.com/@lumino/collections/-/collections-1.3.3.tgz#fa95c826b93ee6e24b3c4b07c8f595312525f8cc" 488 | integrity sha512-vN3GSV5INkgM6tMLd+WqTgaPnQNTY7L/aFUtTOC8TJQm+vg1eSmR4fNXsoGHM3uA85ctSJThvdZr5triu1Iajg== 489 | dependencies: 490 | "@lumino/algorithm" "^1.3.3" 491 | 492 | "@lumino/commands@^1.12.0": 493 | version "1.12.0" 494 | resolved "https://registry.yarnpkg.com/@lumino/commands/-/commands-1.12.0.tgz#63a744d034d8bc524455e47f06c0ac5f2eb6ec38" 495 | integrity sha512-5TFlhDzZk1X8rCBjhh0HH3j6CcJ03mx2Pd/1rGa7MB5R+3+yYYk+gTlfHRqsxdehNRmiISaHRSrMnW8bynW7ZQ== 496 | dependencies: 497 | "@lumino/algorithm" "^1.3.3" 498 | "@lumino/coreutils" "^1.5.3" 499 | "@lumino/disposable" "^1.4.3" 500 | "@lumino/domutils" "^1.2.3" 501 | "@lumino/keyboard" "^1.2.3" 502 | "@lumino/signaling" "^1.4.3" 503 | "@lumino/virtualdom" "^1.8.0" 504 | 505 | "@lumino/coreutils@^1.5.3": 506 | version "1.5.3" 507 | resolved "https://registry.yarnpkg.com/@lumino/coreutils/-/coreutils-1.5.3.tgz#89dd7b7f381642a1bf568910c5b62c7bde705d71" 508 | integrity sha512-G72jJ6sgOwAUuilz+cri7LpHIJxllK+qz+YZUC3fyyWHK7oRlZemcc43jZAVE+tagTdMxKYSQWNIVzM5lI8sWw== 509 | 510 | "@lumino/disposable@^1.4.3": 511 | version "1.4.3" 512 | resolved "https://registry.yarnpkg.com/@lumino/disposable/-/disposable-1.4.3.tgz#0a69b15cc5a1e506f93bb390ac44aae338da3c36" 513 | integrity sha512-zKQ9N2AEGcYpG6PJkeMWQXvoXU9w1ocji78z+fboM/SmSgtOIVGeQt3fZeldymf0XrlOPpNXs1ZFg54yWUMnXA== 514 | dependencies: 515 | "@lumino/algorithm" "^1.3.3" 516 | "@lumino/signaling" "^1.4.3" 517 | 518 | "@lumino/domutils@^1.2.3": 519 | version "1.2.3" 520 | resolved "https://registry.yarnpkg.com/@lumino/domutils/-/domutils-1.2.3.tgz#7e8e549a97624bfdbd4dd95ae4d1e30b87799822" 521 | integrity sha512-SEi8WZSy+DWMkL5CfAY78MHbi3x83AVmRFxjs9+A6qsFPde+Hr1I4DNtLsSDmfAWsobHHgBnjyNp2ZkQEq0IEA== 522 | 523 | "@lumino/dragdrop@^1.7.1": 524 | version "1.7.1" 525 | resolved "https://registry.yarnpkg.com/@lumino/dragdrop/-/dragdrop-1.7.1.tgz#1466206d43a64dadca383e0b9a87cc8a14c8c59b" 526 | integrity sha512-IeSSOTmpqBSWz+EVsbGVeHe/KIaHaUsQXZ4BJCEbCKgNGHbqMfUOtlneiKq7rEhZGF4wYs7gWWjNhMVZbUGO9Q== 527 | dependencies: 528 | "@lumino/coreutils" "^1.5.3" 529 | "@lumino/disposable" "^1.4.3" 530 | 531 | "@lumino/keyboard@^1.2.3": 532 | version "1.2.3" 533 | resolved "https://registry.yarnpkg.com/@lumino/keyboard/-/keyboard-1.2.3.tgz#594c73233636d85ed035b1a37a095acf956cfe8c" 534 | integrity sha512-ibS0sz0VABeuJXx2JVSz36sUBMUOcQNCNPybVhwzN/GkJFs0dnDKluMu+3Px0tkB2y33bGPZU/RLZY1Xj/faEA== 535 | 536 | "@lumino/messaging@^1.4.3": 537 | version "1.4.3" 538 | resolved "https://registry.yarnpkg.com/@lumino/messaging/-/messaging-1.4.3.tgz#75a1901f53086c7c0e978a63cb784eae5cc59f3f" 539 | integrity sha512-wa2Pj2KOuLNLS2n0wVBzUVFGbvjL1FLbuCOAUEYfN6xXVleqqtGGzd08uTF7ebu01KCO3VQ38+dkvoaM/C2qPw== 540 | dependencies: 541 | "@lumino/algorithm" "^1.3.3" 542 | "@lumino/collections" "^1.3.3" 543 | 544 | "@lumino/polling@^1.3.3": 545 | version "1.3.3" 546 | resolved "https://registry.yarnpkg.com/@lumino/polling/-/polling-1.3.3.tgz#6336638cb9ba2f4f4c3ef2529c7f260abbd25148" 547 | integrity sha512-uMRi6sPRnKW8m38WUY3qox1jxwzpvceafUbDJATCwyrZ48+YoY5Fxfmd9dqwioHS1aq9np5c6L35a9ZGuS0Maw== 548 | dependencies: 549 | "@lumino/coreutils" "^1.5.3" 550 | "@lumino/disposable" "^1.4.3" 551 | "@lumino/signaling" "^1.4.3" 552 | 553 | "@lumino/properties@^1.2.3": 554 | version "1.2.3" 555 | resolved "https://registry.yarnpkg.com/@lumino/properties/-/properties-1.2.3.tgz#10675e554e4a9dcc4022de01875fd51f33e2c785" 556 | integrity sha512-dbS9V/L+RpQoRjxHMAGh1JYoXaLA6F7xkVbg/vmYXqdXZ7DguO5C3Qteu9tNp7Z7Q31TqFWUCrniTI9UJiJCoQ== 557 | 558 | "@lumino/signaling@^1.4.3": 559 | version "1.4.3" 560 | resolved "https://registry.yarnpkg.com/@lumino/signaling/-/signaling-1.4.3.tgz#d29f7f542fdcd70b91ca275d3ca793ae21cebf6a" 561 | integrity sha512-6clc8SMcH0tyKXIX31xw6sxjxJl5hj4YRd1DTHTS62cegQ0FkO8JjJeuv+Nc1pgTg6nEAf65aSOHpUdsFHDAvQ== 562 | dependencies: 563 | "@lumino/algorithm" "^1.3.3" 564 | 565 | "@lumino/virtualdom@^1.8.0": 566 | version "1.8.0" 567 | resolved "https://registry.yarnpkg.com/@lumino/virtualdom/-/virtualdom-1.8.0.tgz#42ea5778e3870e4961ea36697b28aab997c75fa6" 568 | integrity sha512-X/1b8b7TxB9tb4+xQiS8oArcA/AK7NBZrsg2dzu/gHa3JC45R8nzQ+0tObD8Nd0gF/e9w9Ps9M62rLfefcbbKw== 569 | dependencies: 570 | "@lumino/algorithm" "^1.3.3" 571 | 572 | "@lumino/widgets@^1.16.1", "@lumino/widgets@^1.18.0": 573 | version "1.18.0" 574 | resolved "https://registry.yarnpkg.com/@lumino/widgets/-/widgets-1.18.0.tgz#fa8ce727126a1e91b9f3ba78e08425115046e3ac" 575 | integrity sha512-8i10njkGjctuXrbaoV2dRI2rVUaL7eA5djtHj36pX9cALwciEPHNecF6hoZXmQ4ODv6LTwhr87Uz8LT4Aan77A== 576 | dependencies: 577 | "@lumino/algorithm" "^1.3.3" 578 | "@lumino/commands" "^1.12.0" 579 | "@lumino/coreutils" "^1.5.3" 580 | "@lumino/disposable" "^1.4.3" 581 | "@lumino/domutils" "^1.2.3" 582 | "@lumino/dragdrop" "^1.7.1" 583 | "@lumino/keyboard" "^1.2.3" 584 | "@lumino/messaging" "^1.4.3" 585 | "@lumino/properties" "^1.2.3" 586 | "@lumino/signaling" "^1.4.3" 587 | "@lumino/virtualdom" "^1.8.0" 588 | 589 | "@types/dom4@^2.0.1": 590 | version "2.0.1" 591 | resolved "https://registry.yarnpkg.com/@types/dom4/-/dom4-2.0.1.tgz#506d5781b9bcab81bd9a878b198aec7dee2a6033" 592 | integrity sha512-kSkVAvWmMZiCYtvqjqQEwOmvKwcH+V4uiv3qPQ8pAh1Xl39xggGEo8gHUqV4waYGHezdFw0rKBR8Jt0CrQSDZA== 593 | 594 | "@types/prop-types@*": 595 | version "15.7.3" 596 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" 597 | integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== 598 | 599 | "@types/react@^17.0.0": 600 | version "17.0.0" 601 | resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8" 602 | integrity sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw== 603 | dependencies: 604 | "@types/prop-types" "*" 605 | csstype "^3.0.2" 606 | 607 | ajv@^6.12.3: 608 | version "6.12.6" 609 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 610 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 611 | dependencies: 612 | fast-deep-equal "^3.1.1" 613 | fast-json-stable-stringify "^2.0.0" 614 | json-schema-traverse "^0.4.1" 615 | uri-js "^4.2.2" 616 | 617 | ansi-styles@^3.2.1: 618 | version "3.2.1" 619 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 620 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 621 | dependencies: 622 | color-convert "^1.9.0" 623 | 624 | balanced-match@^1.0.0: 625 | version "1.0.0" 626 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 627 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 628 | 629 | base64-js@^1.3.1: 630 | version "1.5.1" 631 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 632 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 633 | 634 | brace-expansion@^1.1.7: 635 | version "1.1.11" 636 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 637 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 638 | dependencies: 639 | balanced-match "^1.0.0" 640 | concat-map "0.0.1" 641 | 642 | buffer@^5.6.0: 643 | version "5.7.1" 644 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" 645 | integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 646 | dependencies: 647 | base64-js "^1.3.1" 648 | ieee754 "^1.1.13" 649 | 650 | chalk@^2.4.2: 651 | version "2.4.2" 652 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 653 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 654 | dependencies: 655 | ansi-styles "^3.2.1" 656 | escape-string-regexp "^1.0.5" 657 | supports-color "^5.3.0" 658 | 659 | classnames@^2.2: 660 | version "2.2.6" 661 | resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" 662 | integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== 663 | 664 | codemirror@~5.57.0: 665 | version "5.57.0" 666 | resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.57.0.tgz#d26365b72f909f5d2dbb6b1209349ca1daeb2d50" 667 | integrity sha512-WGc6UL7Hqt+8a6ZAsj/f1ApQl3NPvHY/UQSzG6fB6l4BjExgVdhFaxd7mRTw1UCiYe/6q86zHP+kfvBQcZGvUg== 668 | 669 | color-convert@^1.9.0: 670 | version "1.9.3" 671 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 672 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 673 | dependencies: 674 | color-name "1.1.3" 675 | 676 | color-name@1.1.3: 677 | version "1.1.3" 678 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 679 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 680 | 681 | concat-map@0.0.1: 682 | version "0.0.1" 683 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 684 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 685 | 686 | create-react-context@^0.3.0: 687 | version "0.3.0" 688 | resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c" 689 | integrity sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw== 690 | dependencies: 691 | gud "^1.0.0" 692 | warning "^4.0.3" 693 | 694 | csstype@2.6.9: 695 | version "2.6.9" 696 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098" 697 | integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q== 698 | 699 | csstype@^3.0.2, csstype@~3.0.3: 700 | version "3.0.6" 701 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.6.tgz#865d0b5833d7d8d40f4e5b8a6d76aea3de4725ef" 702 | integrity sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw== 703 | 704 | deep-equal@^1.1.1: 705 | version "1.1.1" 706 | resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" 707 | integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== 708 | dependencies: 709 | is-arguments "^1.0.4" 710 | is-date-object "^1.0.1" 711 | is-regex "^1.0.4" 712 | object-is "^1.0.1" 713 | object-keys "^1.1.1" 714 | regexp.prototype.flags "^1.2.0" 715 | 716 | define-properties@^1.1.2, define-properties@^1.1.3: 717 | version "1.1.3" 718 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" 719 | integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== 720 | dependencies: 721 | object-keys "^1.0.12" 722 | 723 | dom-helpers@^3.4.0: 724 | version "3.4.0" 725 | resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" 726 | integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== 727 | dependencies: 728 | "@babel/runtime" "^7.1.2" 729 | 730 | dom-serializer@^1.0.1: 731 | version "1.2.0" 732 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.2.0.tgz#3433d9136aeb3c627981daa385fc7f32d27c48f1" 733 | integrity sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA== 734 | dependencies: 735 | domelementtype "^2.0.1" 736 | domhandler "^4.0.0" 737 | entities "^2.0.0" 738 | 739 | dom4@^2.1.5: 740 | version "2.1.5" 741 | resolved "https://registry.yarnpkg.com/dom4/-/dom4-2.1.5.tgz#f98a94eb67b340f0fa5b42b0ee9c38cda035428e" 742 | integrity sha512-gJbnVGq5zaBUY0lUh0LUEVGYrtN75Ks8ZwpwOYvnVFrKy/qzXK4R/1WuLIFExWj/tBxbRAkTzZUGJHXmqsBNjQ== 743 | 744 | domelementtype@^2.0.1: 745 | version "2.0.1" 746 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" 747 | integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== 748 | 749 | domelementtype@^2.1.0: 750 | version "2.1.0" 751 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" 752 | integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== 753 | 754 | domhandler@^3.0.0: 755 | version "3.3.0" 756 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" 757 | integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== 758 | dependencies: 759 | domelementtype "^2.0.1" 760 | 761 | domhandler@^4.0.0: 762 | version "4.0.0" 763 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e" 764 | integrity sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA== 765 | dependencies: 766 | domelementtype "^2.1.0" 767 | 768 | domutils@^2.0.0: 769 | version "2.4.4" 770 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3" 771 | integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA== 772 | dependencies: 773 | dom-serializer "^1.0.1" 774 | domelementtype "^2.0.1" 775 | domhandler "^4.0.0" 776 | 777 | entities@^2.0.0: 778 | version "2.0.0" 779 | resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" 780 | integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== 781 | 782 | es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: 783 | version "1.17.5" 784 | resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" 785 | integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== 786 | dependencies: 787 | es-to-primitive "^1.2.1" 788 | function-bind "^1.1.1" 789 | has "^1.0.3" 790 | has-symbols "^1.0.1" 791 | is-callable "^1.1.5" 792 | is-regex "^1.0.5" 793 | object-inspect "^1.7.0" 794 | object-keys "^1.1.1" 795 | object.assign "^4.1.0" 796 | string.prototype.trimleft "^2.1.1" 797 | string.prototype.trimright "^2.1.1" 798 | 799 | es-to-primitive@^1.2.1: 800 | version "1.2.1" 801 | resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" 802 | integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== 803 | dependencies: 804 | is-callable "^1.1.4" 805 | is-date-object "^1.0.1" 806 | is-symbol "^1.0.2" 807 | 808 | escape-string-regexp@^1.0.5: 809 | version "1.0.5" 810 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 811 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 812 | 813 | fast-deep-equal@^3.1.1: 814 | version "3.1.1" 815 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" 816 | integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== 817 | 818 | fast-json-stable-stringify@^2.0.0: 819 | version "2.1.0" 820 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 821 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 822 | 823 | free-style@3.1.0: 824 | version "3.1.0" 825 | resolved "https://registry.yarnpkg.com/free-style/-/free-style-3.1.0.tgz#4e2996029534e6b1731611d843437b9e2f473f08" 826 | integrity sha512-vJujYSIyT30iDoaoeigNAxX4yB1RUrh+N2ZMhIElMr3BvCuGXOw7XNJMEEJkDUeamK2Rnb/IKFGKRKlTWIGRWA== 827 | 828 | fs.realpath@^1.0.0: 829 | version "1.0.0" 830 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 831 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 832 | 833 | function-bind@^1.1.1: 834 | version "1.1.1" 835 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 836 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 837 | 838 | glob@^7.1.3: 839 | version "7.1.6" 840 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 841 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 842 | dependencies: 843 | fs.realpath "^1.0.0" 844 | inflight "^1.0.4" 845 | inherits "2" 846 | minimatch "^3.0.4" 847 | once "^1.3.0" 848 | path-is-absolute "^1.0.0" 849 | 850 | gud@^1.0.0: 851 | version "1.0.0" 852 | resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" 853 | integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== 854 | 855 | has-flag@^3.0.0: 856 | version "3.0.0" 857 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 858 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 859 | 860 | has-symbols@^1.0.0, has-symbols@^1.0.1: 861 | version "1.0.1" 862 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" 863 | integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== 864 | 865 | has@^1.0.3: 866 | version "1.0.3" 867 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 868 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 869 | dependencies: 870 | function-bind "^1.1.1" 871 | 872 | htmlparser2@^4.1.0: 873 | version "4.1.0" 874 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" 875 | integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== 876 | dependencies: 877 | domelementtype "^2.0.1" 878 | domhandler "^3.0.0" 879 | domutils "^2.0.0" 880 | entities "^2.0.0" 881 | 882 | ieee754@^1.1.13: 883 | version "1.2.1" 884 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 885 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 886 | 887 | inflight@^1.0.4: 888 | version "1.0.6" 889 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 890 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 891 | dependencies: 892 | once "^1.3.0" 893 | wrappy "1" 894 | 895 | inherits@2: 896 | version "2.0.4" 897 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 898 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 899 | 900 | is-arguments@^1.0.4: 901 | version "1.0.4" 902 | resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" 903 | integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== 904 | 905 | is-callable@^1.1.4, is-callable@^1.1.5: 906 | version "1.1.5" 907 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" 908 | integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== 909 | 910 | is-date-object@^1.0.1: 911 | version "1.0.2" 912 | resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" 913 | integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== 914 | 915 | is-regex@^1.0.4, is-regex@^1.0.5: 916 | version "1.0.5" 917 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" 918 | integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== 919 | dependencies: 920 | has "^1.0.3" 921 | 922 | is-symbol@^1.0.2: 923 | version "1.0.3" 924 | resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" 925 | integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== 926 | dependencies: 927 | has-symbols "^1.0.1" 928 | 929 | "js-tokens@^3.0.0 || ^4.0.0": 930 | version "4.0.0" 931 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 932 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 933 | 934 | json-schema-traverse@^0.4.1: 935 | version "0.4.1" 936 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 937 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 938 | 939 | json5@^2.1.1: 940 | version "2.1.3" 941 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" 942 | integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== 943 | dependencies: 944 | minimist "^1.2.5" 945 | 946 | lodash.escape@^4.0.1: 947 | version "4.0.1" 948 | resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" 949 | integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg= 950 | 951 | lodash@^4.17.15: 952 | version "4.17.20" 953 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" 954 | integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== 955 | 956 | loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: 957 | version "1.4.0" 958 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 959 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 960 | dependencies: 961 | js-tokens "^3.0.0 || ^4.0.0" 962 | 963 | marked@^1.1.1: 964 | version "1.2.7" 965 | resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" 966 | integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== 967 | 968 | minimatch@^3.0.4: 969 | version "3.0.4" 970 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 971 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 972 | dependencies: 973 | brace-expansion "^1.1.7" 974 | 975 | minimist@^1.2.5, minimist@~1.2.0: 976 | version "1.2.5" 977 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 978 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 979 | 980 | moment@^2.24.0: 981 | version "2.24.0" 982 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" 983 | integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== 984 | 985 | node-fetch@^2.6.0: 986 | version "2.6.0" 987 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" 988 | integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== 989 | 990 | normalize.css@^8.0.1: 991 | version "8.0.1" 992 | resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" 993 | integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== 994 | 995 | object-assign@^4.1.1: 996 | version "4.1.1" 997 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 998 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 999 | 1000 | object-inspect@^1.7.0: 1001 | version "1.7.0" 1002 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" 1003 | integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== 1004 | 1005 | object-is@^1.0.1: 1006 | version "1.1.2" 1007 | resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" 1008 | integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== 1009 | dependencies: 1010 | define-properties "^1.1.3" 1011 | es-abstract "^1.17.5" 1012 | 1013 | object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: 1014 | version "1.1.1" 1015 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 1016 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 1017 | 1018 | object.assign@^4.1.0: 1019 | version "4.1.0" 1020 | resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" 1021 | integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== 1022 | dependencies: 1023 | define-properties "^1.1.2" 1024 | function-bind "^1.1.1" 1025 | has-symbols "^1.0.0" 1026 | object-keys "^1.0.11" 1027 | 1028 | once@^1.3.0: 1029 | version "1.4.0" 1030 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1031 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1032 | dependencies: 1033 | wrappy "1" 1034 | 1035 | parse-srcset@^1.0.2: 1036 | version "1.0.2" 1037 | resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" 1038 | integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= 1039 | 1040 | path-browserify@^1.0.0: 1041 | version "1.0.1" 1042 | resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" 1043 | integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== 1044 | 1045 | path-is-absolute@^1.0.0: 1046 | version "1.0.1" 1047 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1048 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1049 | 1050 | popper.js@^1.14.4, popper.js@^1.16.1: 1051 | version "1.16.1" 1052 | resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" 1053 | integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== 1054 | 1055 | postcss@^7.0.27: 1056 | version "7.0.35" 1057 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" 1058 | integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== 1059 | dependencies: 1060 | chalk "^2.4.2" 1061 | source-map "^0.6.1" 1062 | supports-color "^6.1.0" 1063 | 1064 | prettier@2.0.5: 1065 | version "2.0.5" 1066 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" 1067 | integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== 1068 | 1069 | prop-types@^15.6.1, prop-types@^15.6.2: 1070 | version "15.7.2" 1071 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" 1072 | integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== 1073 | dependencies: 1074 | loose-envify "^1.4.0" 1075 | object-assign "^4.1.1" 1076 | react-is "^16.8.1" 1077 | 1078 | punycode@1.3.2: 1079 | version "1.3.2" 1080 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" 1081 | integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= 1082 | 1083 | punycode@^2.1.0: 1084 | version "2.1.1" 1085 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1086 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1087 | 1088 | querystring@0.2.0: 1089 | version "0.2.0" 1090 | resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" 1091 | integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= 1092 | 1093 | querystringify@^2.1.1: 1094 | version "2.1.1" 1095 | resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" 1096 | integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== 1097 | 1098 | react-dom@^17.0.1: 1099 | version "17.0.1" 1100 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6" 1101 | integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug== 1102 | dependencies: 1103 | loose-envify "^1.1.0" 1104 | object-assign "^4.1.1" 1105 | scheduler "^0.20.1" 1106 | 1107 | react-is@^16.8.1: 1108 | version "16.13.1" 1109 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" 1110 | integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== 1111 | 1112 | react-lifecycles-compat@^3.0.4: 1113 | version "3.0.4" 1114 | resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" 1115 | integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== 1116 | 1117 | react-popper@^1.3.7: 1118 | version "1.3.7" 1119 | resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.7.tgz#f6a3471362ef1f0d10a4963673789de1baca2324" 1120 | integrity sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww== 1121 | dependencies: 1122 | "@babel/runtime" "^7.1.2" 1123 | create-react-context "^0.3.0" 1124 | deep-equal "^1.1.1" 1125 | popper.js "^1.14.4" 1126 | prop-types "^15.6.1" 1127 | typed-styles "^0.0.7" 1128 | warning "^4.0.2" 1129 | 1130 | react-transition-group@^2.9.0: 1131 | version "2.9.0" 1132 | resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" 1133 | integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== 1134 | dependencies: 1135 | dom-helpers "^3.4.0" 1136 | loose-envify "^1.4.0" 1137 | prop-types "^15.6.2" 1138 | react-lifecycles-compat "^3.0.4" 1139 | 1140 | react@^17.0.1: 1141 | version "17.0.1" 1142 | resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" 1143 | integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w== 1144 | dependencies: 1145 | loose-envify "^1.1.0" 1146 | object-assign "^4.1.1" 1147 | 1148 | regenerator-runtime@^0.13.4: 1149 | version "0.13.5" 1150 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" 1151 | integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== 1152 | 1153 | regexp.prototype.flags@^1.2.0: 1154 | version "1.3.0" 1155 | resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" 1156 | integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== 1157 | dependencies: 1158 | define-properties "^1.1.3" 1159 | es-abstract "^1.17.0-next.1" 1160 | 1161 | requires-port@^1.0.0: 1162 | version "1.0.0" 1163 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1164 | integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= 1165 | 1166 | resize-observer-polyfill@^1.5.1: 1167 | version "1.5.1" 1168 | resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" 1169 | integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== 1170 | 1171 | rimraf@3.0.2: 1172 | version "3.0.2" 1173 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1174 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1175 | dependencies: 1176 | glob "^7.1.3" 1177 | 1178 | sanitize-html@~1.27.4: 1179 | version "1.27.5" 1180 | resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.27.5.tgz#6c8149462adb23e360e1bb71cc0bae7f08c823c7" 1181 | integrity sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A== 1182 | dependencies: 1183 | htmlparser2 "^4.1.0" 1184 | lodash "^4.17.15" 1185 | parse-srcset "^1.0.2" 1186 | postcss "^7.0.27" 1187 | 1188 | scheduler@^0.20.1: 1189 | version "0.20.1" 1190 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c" 1191 | integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw== 1192 | dependencies: 1193 | loose-envify "^1.1.0" 1194 | object-assign "^4.1.1" 1195 | 1196 | source-map@^0.6.1: 1197 | version "0.6.1" 1198 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1199 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1200 | 1201 | string.prototype.trimend@^1.0.0: 1202 | version "1.0.1" 1203 | resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" 1204 | integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== 1205 | dependencies: 1206 | define-properties "^1.1.3" 1207 | es-abstract "^1.17.5" 1208 | 1209 | string.prototype.trimleft@^2.1.1: 1210 | version "2.1.2" 1211 | resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" 1212 | integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== 1213 | dependencies: 1214 | define-properties "^1.1.3" 1215 | es-abstract "^1.17.5" 1216 | string.prototype.trimstart "^1.0.0" 1217 | 1218 | string.prototype.trimright@^2.1.1: 1219 | version "2.1.2" 1220 | resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" 1221 | integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== 1222 | dependencies: 1223 | define-properties "^1.1.3" 1224 | es-abstract "^1.17.5" 1225 | string.prototype.trimend "^1.0.0" 1226 | 1227 | string.prototype.trimstart@^1.0.0: 1228 | version "1.0.1" 1229 | resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" 1230 | integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== 1231 | dependencies: 1232 | define-properties "^1.1.3" 1233 | es-abstract "^1.17.5" 1234 | 1235 | supports-color@^5.3.0: 1236 | version "5.5.0" 1237 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1238 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1239 | dependencies: 1240 | has-flag "^3.0.0" 1241 | 1242 | supports-color@^6.1.0: 1243 | version "6.1.0" 1244 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" 1245 | integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== 1246 | dependencies: 1247 | has-flag "^3.0.0" 1248 | 1249 | tslib@~1.13.0: 1250 | version "1.13.0" 1251 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" 1252 | integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== 1253 | 1254 | typed-styles@^0.0.7: 1255 | version "0.0.7" 1256 | resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" 1257 | integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== 1258 | 1259 | typescript@3.9.3: 1260 | version "3.9.3" 1261 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a" 1262 | integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ== 1263 | 1264 | typestyle@^2.0.4: 1265 | version "2.1.0" 1266 | resolved "https://registry.yarnpkg.com/typestyle/-/typestyle-2.1.0.tgz#7c5cc567de72cd8bfb686813150b92791aaa7636" 1267 | integrity sha512-6uCYPdG4xWLeEcl9O0GtNFnNGhami+irKiLsXSuvWHC/aTS7wdj49WeikWAKN+xHN3b1hm+9v0svwwgSBhCsNA== 1268 | dependencies: 1269 | csstype "2.6.9" 1270 | free-style "3.1.0" 1271 | 1272 | uri-js@^4.2.2: 1273 | version "4.2.2" 1274 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 1275 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 1276 | dependencies: 1277 | punycode "^2.1.0" 1278 | 1279 | url-parse@~1.4.7: 1280 | version "1.4.7" 1281 | resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" 1282 | integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== 1283 | dependencies: 1284 | querystringify "^2.1.1" 1285 | requires-port "^1.0.0" 1286 | 1287 | url@^0.11.0: 1288 | version "0.11.0" 1289 | resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" 1290 | integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= 1291 | dependencies: 1292 | punycode "1.3.2" 1293 | querystring "0.2.0" 1294 | 1295 | warning@^4.0.2, warning@^4.0.3: 1296 | version "4.0.3" 1297 | resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" 1298 | integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== 1299 | dependencies: 1300 | loose-envify "^1.0.0" 1301 | 1302 | wrappy@1: 1303 | version "1.0.2" 1304 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1305 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1306 | 1307 | ws@^7.2.0: 1308 | version "7.2.3" 1309 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" 1310 | integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== 1311 | -------------------------------------------------------------------------------- /jupyter_dash/__init__.py: -------------------------------------------------------------------------------- 1 | import jupyter_dash.comms 2 | from .jupyter_app import JupyterDash 3 | from .version import __version__ 4 | 5 | def _jupyter_nbextension_paths(): 6 | return [ 7 | { 8 | "section": "notebook", 9 | "src": "nbextension", 10 | "dest": "jupyter_dash", 11 | "require": "jupyter_dash/main", 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /jupyter_dash/comms.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import IPython 3 | from ipykernel.comm import Comm 4 | import nest_asyncio 5 | import time 6 | import sys 7 | 8 | _jupyter_config = {} 9 | 10 | _dash_comm = Comm(target_name='jupyter_dash') 11 | 12 | _caller = {} 13 | 14 | 15 | def _send_jupyter_config_comm_request(): 16 | # If running in an ipython kernel, 17 | # request that the front end extension send us the notebook server base URL 18 | if IPython.get_ipython() is not None: 19 | if _dash_comm.kernel is not None: 20 | _caller["parent"] = _dash_comm.kernel.get_parent() 21 | _dash_comm.send({ 22 | 'type': 'base_url_request' 23 | }) 24 | 25 | 26 | @_dash_comm.on_msg 27 | def _receive_message(msg): 28 | prev_parent = _caller.get("parent") 29 | if prev_parent and prev_parent != _dash_comm.kernel.get_parent(): 30 | _dash_comm.kernel.set_parent([prev_parent["header"]["session"]], prev_parent) 31 | del _caller["parent"] 32 | 33 | msg_data = msg.get('content').get('data') 34 | msg_type = msg_data.get('type', None) 35 | if msg_type == 'base_url_response': 36 | _jupyter_config.update(msg_data) 37 | 38 | 39 | def _jupyter_comm_response_received(): 40 | return bool(_jupyter_config) 41 | 42 | 43 | def _request_jupyter_config(timeout=2): 44 | # Heavily inspired by implementation of CaptureExecution in the 45 | if _dash_comm.kernel is None: 46 | # Not in jupyter setting 47 | return 48 | 49 | _send_jupyter_config_comm_request() 50 | 51 | # Get shell and kernel 52 | shell = IPython.get_ipython() 53 | kernel = shell.kernel 54 | 55 | # Start capturing shell events to replay later 56 | captured_events = [] 57 | 58 | def capture_event(stream, ident, parent): 59 | captured_events.append((stream, ident, parent)) 60 | 61 | kernel.shell_handlers['execute_request'] = capture_event 62 | 63 | # increment execution count to avoid collision error 64 | shell.execution_count += 1 65 | 66 | # Allow kernel to execute comms until we receive the jupyter configuration comm 67 | # response 68 | t0 = time.time() 69 | while True: 70 | if (time.time() - t0) > timeout: 71 | # give up 72 | raise EnvironmentError( 73 | "Unable to communicate with the jupyter_dash notebook or JupyterLab \n" 74 | "extension required to infer Jupyter configuration." 75 | ) 76 | if _jupyter_comm_response_received(): 77 | break 78 | 79 | if asyncio.iscoroutinefunction(kernel.do_one_iteration): 80 | loop = asyncio.get_event_loop() 81 | nest_asyncio.apply(loop) 82 | loop.run_until_complete(kernel.do_one_iteration()) 83 | else: 84 | kernel.do_one_iteration() 85 | 86 | # Stop capturing events, revert the kernel shell handler to the default 87 | # execute_request behavior 88 | kernel.shell_handlers['execute_request'] = kernel.execute_request 89 | 90 | # Replay captured events 91 | # need to flush before replaying so messages show up in current cell not 92 | # replay cells 93 | sys.stdout.flush() 94 | sys.stderr.flush() 95 | 96 | for stream, ident, parent in captured_events: 97 | # Using kernel.set_parent is the key to getting the output of the replayed 98 | # events to show up in the cells that were captured instead of the current cell 99 | kernel.set_parent(ident, parent) 100 | kernel.execute_request(stream, ident, parent) 101 | -------------------------------------------------------------------------------- /jupyter_dash/jupyter_app.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import dash 4 | import os 5 | import requests 6 | import flask.cli 7 | from IPython.core.display import HTML 8 | from retrying import retry 9 | import io 10 | import re 11 | import sys 12 | import inspect 13 | import traceback 14 | import threading 15 | import warnings 16 | import queue 17 | 18 | from IPython import get_ipython 19 | from IPython.display import IFrame, display 20 | from IPython.core.ultratb import FormattedTB 21 | from ansi2html import Ansi2HTMLConverter 22 | import uuid 23 | 24 | from werkzeug.serving import make_server 25 | 26 | from .comms import _dash_comm, _jupyter_config, _request_jupyter_config 27 | 28 | 29 | def _get_skip(error: Exception): 30 | tb = traceback.format_exception(type(error), error, error.__traceback__) 31 | skip = 0 32 | for i, line in enumerate(tb): 33 | if "%% callback invoked %%" in line: 34 | skip = i + 1 35 | break 36 | return skip 37 | 38 | 39 | class JupyterDash(dash.Dash): 40 | """A Dash subclass for developing Dash apps interactively in Jupyter. 41 | 42 | :param server_url: The base URL that the app will be served at, from the 43 | perspective of the client. If not specified, will default to the host argument 44 | passed to the ``run_server`` method. 45 | 46 | See parent docstring for additional parameters 47 | """ 48 | default_mode = 'external' 49 | default_requests_pathname_prefix = os.environ.get( 50 | "DASH_REQUESTS_PATHNAME_PREFIX", None 51 | ) 52 | default_server_url = None 53 | _in_ipython = get_ipython() is not None 54 | _in_colab = "google.colab" in sys.modules 55 | _token = str(uuid.uuid4()) 56 | 57 | _servers = {} 58 | 59 | @classmethod 60 | def infer_jupyter_proxy_config(cls): 61 | """ 62 | Infer the current Jupyter server configuration. This will detect 63 | the proper request_pathname_prefix and server_url values to use when 64 | displaying Dash apps. When the jupyter_server_proxy Python package is 65 | installed, all Dash requests will be routed through the proxy. 66 | 67 | Requirements: 68 | 69 | In the classic notebook, this method requires the `jupyter_dash` nbextension 70 | which should be installed automatically with the installation of the 71 | jupyter-dash Python package. You can see what notebook extensions are installed 72 | by running the following command: 73 | $ jupyter nbextension list 74 | 75 | In JupyterLab, this method requires the `jupyterlab-dash` labextension. This 76 | extension should be installed automatically with the installation of the 77 | jupyter-dash Python package, but JupyterLab must be allowed to rebuild before 78 | the extension is activated (JupyterLab should automatically detect the 79 | extension and produce a popup dialog asking for permission to rebuild). You can 80 | see what JupyterLab extensions are installed by running the following command: 81 | $ jupyter labextension list 82 | """ 83 | if not JupyterDash._in_ipython or JupyterDash._in_colab: 84 | # No op when not running in a Jupyter context or when in Colab 85 | return 86 | else: 87 | # Assume classic notebook or JupyterLab 88 | _request_jupyter_config() 89 | 90 | def __init__(self, name=None, server_url=None, **kwargs): 91 | """""" 92 | # Strip unsupported properties and warn 93 | if JupyterDash._in_colab: 94 | unsupported_colab_props = [ 95 | 'requests_pathname_prefix', 96 | 'routes_pathname_prefix', 97 | 'url_base_pathname' 98 | ] 99 | for prop in unsupported_colab_props: 100 | if prop in kwargs: 101 | kwargs.pop(prop) 102 | warnings.warn( 103 | "The {prop} argument is ignored when running in Colab".format( 104 | prop=prop 105 | ) 106 | ) 107 | 108 | # Call superclass constructor 109 | super(JupyterDash, self).__init__(name=name, **kwargs) 110 | 111 | if not JupyterDash._in_ipython: 112 | # Nothing else to do when not running in a Jupyter context 113 | return 114 | 115 | # See if jupyter_server_proxy is installed 116 | try: 117 | import jupyter_server_proxy 118 | self._server_proxy = True 119 | except Exception: 120 | self._server_proxy = False 121 | 122 | self._traceback = None 123 | 124 | if ('base_subpath' in _jupyter_config and self._server_proxy and 125 | JupyterDash.default_requests_pathname_prefix is None): 126 | JupyterDash.default_requests_pathname_prefix = ( 127 | _jupyter_config['base_subpath'].rstrip('/') + '/proxy/{port}/' 128 | ) 129 | 130 | if ('server_url' in _jupyter_config and self._server_proxy and 131 | JupyterDash.default_server_url is None): 132 | JupyterDash.default_server_url = _jupyter_config['server_url'] 133 | 134 | self._input_pathname_prefix = kwargs.get('requests_pathname_prefix', None) 135 | 136 | # Infer server_url 137 | if server_url is None: 138 | domain_base = os.environ.get('DASH_DOMAIN_BASE', None) 139 | if domain_base: 140 | # Dash Enterprise sets DASH_DOMAIN_BASE environment variable 141 | server_url = 'https://' + domain_base 142 | elif JupyterDash._in_colab: 143 | warnings.warn("The server_url argument is ignored when running in Colab") 144 | server_url = None 145 | 146 | self.server_url = server_url 147 | 148 | # Register route that we can use to poll to see when server is running 149 | @self.server.route('/_alive_' + JupyterDash._token, methods=['GET']) 150 | def alive(): 151 | return 'Alive' 152 | 153 | self.server.logger.disabled = True 154 | self._exception_handling_added = False 155 | 156 | def run( 157 | self, 158 | mode=None, width="100%", height=650, inline_exceptions=None, 159 | **kwargs 160 | ): 161 | """ 162 | Serve the app using flask in a background thread. You should not run this on a 163 | production server, use gunicorn/waitress instead. 164 | 165 | :param mode: Display mode. One of: 166 | ``"external"``: The URL of the app will be displayed in the notebook 167 | output cell. Clicking this URL will open the app in the default 168 | web browser. 169 | ``"inline"``: The app will be displayed inline in the notebook output cell 170 | in an iframe. 171 | ``"jupyterlab"``: The app will be displayed in a dedicate tab in the 172 | JupyterLab interface. Requires JupyterLab and the `jupyterlab-dash` 173 | extension. 174 | :param width: Width of app when displayed using mode="inline" 175 | :param height: Height of app when displayed using mode="inline" 176 | :param inline_exceptions: If True, callback exceptions are displayed inline 177 | in the the notebook output cell. Defaults to True if mode=="inline", 178 | False otherwise. 179 | :param kwargs: Additional keyword arguments to pass to the superclass 180 | ``Dash.run_server`` method. 181 | """ 182 | # Get superclass run_server method 183 | if hasattr(dash.Dash, "run"): 184 | super_run_server = super(JupyterDash, self).run 185 | else: 186 | super_run_server = super(JupyterDash, self).run_server 187 | 188 | if not JupyterDash._in_ipython: 189 | # If not in IPython context, call run run_server synchronously 190 | super_run_server(**kwargs) 191 | return 192 | 193 | # Get host and port 194 | host = kwargs.pop("host", os.getenv("HOST", "127.0.0.1")) 195 | port = int(kwargs.pop("port", os.getenv("PORT", "8050"))) 196 | 197 | # Validate / infer display mode 198 | if JupyterDash._in_colab: 199 | valid_display_values = ["inline", "external"] 200 | else: 201 | valid_display_values = ["jupyterlab", "inline", "external"] 202 | 203 | if mode is None: 204 | mode = JupyterDash.default_mode 205 | elif not isinstance(mode, str): 206 | raise ValueError( 207 | "The mode argument must be a string\n" 208 | " Received value of type {typ}: {val}".format( 209 | typ=type(mode), val=repr(mode) 210 | ) 211 | ) 212 | else: 213 | mode = mode.lower() 214 | if mode not in valid_display_values: 215 | raise ValueError( 216 | "Invalid display argument {display}\n" 217 | " Valid arguments: {valid_display_values}".format( 218 | display=repr(mode), valid_display_values=valid_display_values 219 | ) 220 | ) 221 | 222 | # Infer inline_exceptions and ui 223 | if inline_exceptions is None: 224 | inline_exceptions = mode == "inline" 225 | 226 | # Terminate any existing server using this port 227 | old_server = self._servers.get((host, port)) 228 | if old_server: 229 | old_server.shutdown() 230 | del self._servers[(host, port)] 231 | 232 | # Configure pathname prefix 233 | requests_pathname_prefix = self.config.get('requests_pathname_prefix', None) 234 | if self._input_pathname_prefix is None: 235 | requests_pathname_prefix = self.default_requests_pathname_prefix 236 | 237 | if requests_pathname_prefix is not None: 238 | requests_pathname_prefix = requests_pathname_prefix.format(port=port) 239 | else: 240 | requests_pathname_prefix = '/' 241 | # low-level setter to circumvent Dash's config locking 242 | # normally it's unsafe to alter requests_pathname_prefix this late, but 243 | # Jupyter needs some unusual behavior. 244 | dict.__setitem__(self.config, "requests_pathname_prefix", requests_pathname_prefix) 245 | 246 | # Compute server_url url 247 | if self.server_url is None: 248 | if JupyterDash.default_server_url: 249 | server_url = JupyterDash.default_server_url.rstrip('/') 250 | else: 251 | server_url = 'http://{host}:{port}'.format(host=host, port=port) 252 | else: 253 | server_url = self.server_url.rstrip('/') 254 | 255 | dashboard_url = "{server_url}{requests_pathname_prefix}".format( 256 | server_url=server_url, requests_pathname_prefix=requests_pathname_prefix 257 | ) 258 | 259 | # Default the global "debug" flag to True 260 | debug = kwargs.pop('debug', True) 261 | 262 | # Enable supported dev tools 263 | if debug: 264 | for k in [ 265 | 'dev_tools_silence_routes_logging', 266 | 'dev_tools_props_check', 267 | 'dev_tools_serve_dev_bundles', 268 | 'dev_tools_prune_errors' 269 | ]: 270 | if k not in kwargs: 271 | kwargs[k] = True 272 | 273 | # Enable dev tools by default unless app is displayed inline 274 | if 'dev_tools_ui' not in kwargs: 275 | kwargs['dev_tools_ui'] = mode != "inline" 276 | 277 | if 'dev_tools_hot_reload' not in kwargs: 278 | # Enable hot-reload by default in "external" mode. Enabling in inline or 279 | # in JupyterLab extension seems to cause Jupyter problems sometimes when 280 | # there is no active kernel. 281 | kwargs['dev_tools_hot_reload'] = mode == "external" 282 | 283 | # Set up custom callback exception handling 284 | self._config_callback_exception_handling( 285 | dev_tools_prune_errors=kwargs.get('dev_tools_prune_errors', True), 286 | inline_exceptions=inline_exceptions, 287 | ) 288 | 289 | dev_tools_args = dict( 290 | debug=debug, 291 | dev_tools_ui=kwargs.pop("dev_tools_ui", None), 292 | dev_tools_props_check=kwargs.pop("dev_tools_props_check", None), 293 | dev_tools_serve_dev_bundles=kwargs.pop("dev_tools_serve_dev_bundles", None), 294 | dev_tools_hot_reload=kwargs.pop("dev_tools_hot_reload", None), 295 | dev_tools_hot_reload_interval=kwargs.pop("dev_tools_hot_reload_interval", None), 296 | dev_tools_hot_reload_watch_interval=kwargs.pop("dev_tools_hot_reload_watch_interval", None), 297 | dev_tools_hot_reload_max_retry=kwargs.pop("dev_tools_hot_reload_max_retry", None), 298 | dev_tools_silence_routes_logging=kwargs.pop("dev_tools_silence_routes_logging", None), 299 | dev_tools_prune_errors=kwargs.pop("dev_tools_prune_errors", None), 300 | ) 301 | 302 | if len(kwargs): 303 | raise Exception(f"Invalid keyword argument: {list(kwargs.keys())}") 304 | 305 | self.enable_dev_tools(**dev_tools_args) 306 | 307 | # suppress warning banner printed to standard out 308 | flask.cli.show_server_banner = lambda *args, **kw: None 309 | 310 | # prevent partial import of orjson when it's installed and mode=jupyterlab 311 | # TODO: why do we need this? Why only in this mode? Importing here in 312 | # all modes anyway, in case there's a way it can pop up in another mode 313 | try: 314 | import orjson 315 | except ImportError: 316 | pass 317 | 318 | err_q = queue.Queue() 319 | 320 | server = make_server( 321 | host, port, self.server, 322 | threaded=True, 323 | processes=0 324 | ) 325 | logging.getLogger("werkzeug").setLevel(logging.ERROR) 326 | 327 | @retry( 328 | stop_max_attempt_number=15, 329 | wait_exponential_multiplier=100, 330 | wait_exponential_max=1000 331 | ) 332 | def run(): 333 | try: 334 | server.serve_forever() 335 | except SystemExit: 336 | pass 337 | except Exception as error: 338 | err_q.put(error) 339 | raise error 340 | 341 | thread = threading.Thread(target=run) 342 | thread.daemon = True 343 | thread.start() 344 | 345 | self._servers[(host, port)] = server 346 | 347 | # Wait for server to start up 348 | alive_url = "http://{host}:{port}/_alive_{token}".format( 349 | host=host, port=port, token=JupyterDash._token 350 | ) 351 | 352 | def _get_error(): 353 | try: 354 | err = err_q.get_nowait() 355 | if err: 356 | raise err 357 | except queue.Empty: 358 | pass 359 | 360 | # Wait for app to respond to _alive endpoint 361 | @retry( 362 | stop_max_attempt_number=15, 363 | wait_exponential_multiplier=10, 364 | wait_exponential_max=1000 365 | ) 366 | def wait_for_app(): 367 | _get_error() 368 | try: 369 | req = requests.get(alive_url) 370 | res = req.content.decode() 371 | if req.status_code != 200: 372 | raise Exception(res) 373 | 374 | if res != "Alive": 375 | url = "http://{host}:{port}".format( 376 | host=host, port=port, token=JupyterDash._token 377 | ) 378 | raise OSError( 379 | "Address '{url}' already in use.\n" 380 | " Try passing a different port to run_server.".format( 381 | url=url 382 | ) 383 | ) 384 | except requests.ConnectionError as err: 385 | _get_error() 386 | raise err 387 | 388 | try: 389 | wait_for_app() 390 | 391 | if JupyterDash._in_colab: 392 | self._display_in_colab(dashboard_url, port, mode, width, height) 393 | else: 394 | self._display_in_jupyter(dashboard_url, port, mode, width, height) 395 | except Exception as final_error: 396 | msg = str(final_error) 397 | if msg.startswith('', 473 | '' 474 | ) 475 | 476 | # Remove explicit background color so Dash dev-tools can set background 477 | # color 478 | html_str = re.sub("background-color:[^;]+;", "", html_str) 479 | 480 | return html_str, 500 481 | 482 | def run_server( 483 | self, 484 | mode=None, width="100%", height=650, inline_exceptions=None, 485 | **kwargs 486 | ): 487 | self.run( 488 | mode=mode, width=width, height=height, inline_exceptions=inline_exceptions, 489 | **kwargs 490 | ) 491 | 492 | 493 | def _custom_formatargvalues( 494 | args, varargs, varkw, locals, 495 | formatarg=str, 496 | formatvarargs=lambda name: '*' + name, 497 | formatvarkw=lambda name: '**' + name, 498 | formatvalue=lambda value: '=' + repr(value)): 499 | 500 | """Copied from inspect.formatargvalues, modified to place function 501 | arguments on separate lines""" 502 | def convert(name, locals=locals, 503 | formatarg=formatarg, formatvalue=formatvalue): 504 | return formatarg(name) + formatvalue(locals[name]) 505 | specs = [] 506 | for i in range(len(args)): 507 | specs.append(convert(args[i])) 508 | if varargs: 509 | specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) 510 | if varkw: 511 | specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) 512 | 513 | result = '(' + ', '.join(specs) + ')' 514 | 515 | if len(result) < 40: 516 | return result 517 | else: 518 | # Put each arg on a separate line 519 | return '(\n ' + ',\n '.join(specs) + '\n)' 520 | -------------------------------------------------------------------------------- /jupyter_dash/labextension/dist/jupyterlab-dash-v0.4.2.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plotly/jupyter-dash/a18b3d2b29d34f0673938be956d85bac0a38c20f/jupyter_dash/labextension/dist/jupyterlab-dash-v0.4.2.tgz -------------------------------------------------------------------------------- /jupyter_dash/labextension/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jupyterlab-dash", 3 | "version": "0.4.2", 4 | "description": "A JupyterLab extensions for rendering Plotly Dash apps", 5 | "keywords": [ 6 | "jupyter", 7 | "jupyterlab", 8 | "jupyterlab-extension" 9 | ], 10 | "homepage": "https://github.com/plotly/jupyter-dash", 11 | "bugs": { 12 | "url": "https://github.com/plotly/jupyter-dash/issues" 13 | }, 14 | "license": "MIT", 15 | "author": "Plotly", 16 | "files": [ 17 | "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", 18 | "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}" 19 | ], 20 | "main": "lib/index.js", 21 | "types": "lib/index.d.ts", 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/plotly/jupyter-dash.git" 25 | }, 26 | "scripts": { 27 | "build": "tsc", 28 | "clean": "rimraf lib", 29 | "prepare": "npm run clean && npm run build", 30 | "prettier": "prettier --write '{!(package),src/**,!(lib)/**}{.js,.jsx,.ts,.tsx,.css,.json,.md}'", 31 | "watch": "tsc -w" 32 | }, 33 | "dependencies": { 34 | "@jupyterlab/application": "^2.0.0 || ^3.0.0", 35 | "@jupyterlab/notebook": "^2.0.0 || ^3.0.0", 36 | "@jupyterlab/console": "^2.0.0 || ^3.0.0" 37 | }, 38 | "devDependencies": { 39 | "prettier": "2.0.5", 40 | "rimraf": "3.0.2", 41 | "typescript": "3.9.3" 42 | }, 43 | "jupyterlab": { 44 | "extension": true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /jupyter_dash/nbextension/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plotly/jupyter-dash/a18b3d2b29d34f0673938be956d85bac0a38c20f/jupyter_dash/nbextension/README.md -------------------------------------------------------------------------------- /jupyter_dash/nbextension/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plotly/jupyter-dash/a18b3d2b29d34f0673938be956d85bac0a38c20f/jupyter_dash/nbextension/__init__.py -------------------------------------------------------------------------------- /jupyter_dash/nbextension/description.yaml: -------------------------------------------------------------------------------- 1 | Type: Jupyter Notebook Extension 2 | Compatibility: 3.x, 4.x, 5.x, 6.x 3 | Name: Jupyter Dash 4 | Main: main.js 5 | Link: README.md 6 | Description: | 7 | Jupyer Dash support 8 | Parameters: 9 | - none 10 | -------------------------------------------------------------------------------- /jupyter_dash/nbextension/jupyter_dash.json: -------------------------------------------------------------------------------- 1 | { 2 | "load_extensions": { 3 | "jupyter_dash/main": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /jupyter_dash/nbextension/main.js: -------------------------------------------------------------------------------- 1 | // file my_extension/main.js 2 | 3 | define([ 4 | 'base/js/namespace', 5 | 'base/js/utils', 6 | ], function(Jupyter, utils){ 7 | 8 | function load_ipython_extension(){ 9 | var notebookUrl = window.location.href 10 | var baseUrl = utils.get_body_data('baseUrl'); 11 | var baseNotebooks = baseUrl + "notebooks" 12 | var n = notebookUrl.search(baseNotebooks) 13 | var jupyterServerUrl = notebookUrl.slice(0, n) 14 | 15 | var register_comm = function() { 16 | Jupyter.notebook.kernel.comm_manager.register_target('jupyter_dash', 17 | function (comm, msg) { 18 | // Register handlers for later messages: 19 | comm.on_msg(function (msg) { 20 | var msgData = msg.content.data; 21 | if (msgData.type === 'base_url_request') { 22 | comm.send({ 23 | type: 'base_url_response', 24 | server_url: jupyterServerUrl, 25 | base_subpath: baseUrl, 26 | frontend: "notebook" 27 | }); 28 | } 29 | }); 30 | }); 31 | }; 32 | 33 | Jupyter.notebook.events.on('kernel_ready.Kernel', register_comm) 34 | } 35 | 36 | return { 37 | load_ipython_extension: load_ipython_extension 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /jupyter_dash/version.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.4.2" 2 | -------------------------------------------------------------------------------- /notebooks/getting_started.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# JupyterDash\n", 8 | "The `jupyter-dash` package makes it easy to develop Plotly Dash apps from the Jupyter Notebook and JupyterLab.\n", 9 | "\n", 10 | "Just replace the standard `dash.Dash` class with the `jupyter_dash.JupyterDash` subclass." 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "from jupyter_dash import JupyterDash" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": null, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "import dash\n", 29 | "from dash import dcc\n", 30 | "from dash import html\n", 31 | "import pandas as pd" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "When running in JupyterHub or Binder, call the `infer_jupyter_config` function to detect the proxy configuration." 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "JupyterDash.infer_jupyter_proxy_config()" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "Load and preprocess data" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')\n", 64 | "available_indicators = df['Indicator Name'].unique()" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "Construct the app and callbacks" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']\n", 81 | "\n", 82 | "app = JupyterDash(__name__, external_stylesheets=external_stylesheets)\n", 83 | "\n", 84 | "# Create server variable with Flask server object for use with gunicorn\n", 85 | "server = app.server\n", 86 | "\n", 87 | "app.layout = html.Div([\n", 88 | " html.Div([\n", 89 | "\n", 90 | " html.Div([\n", 91 | " dcc.Dropdown(\n", 92 | " id='crossfilter-xaxis-column',\n", 93 | " options=[{'label': i, 'value': i} for i in available_indicators],\n", 94 | " value='Fertility rate, total (births per woman)'\n", 95 | " ),\n", 96 | " dcc.RadioItems(\n", 97 | " id='crossfilter-xaxis-type',\n", 98 | " options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],\n", 99 | " value='Linear',\n", 100 | " labelStyle={'display': 'inline-block'}\n", 101 | " )\n", 102 | " ],\n", 103 | " style={'width': '49%', 'display': 'inline-block'}),\n", 104 | "\n", 105 | " html.Div([\n", 106 | " dcc.Dropdown(\n", 107 | " id='crossfilter-yaxis-column',\n", 108 | " options=[{'label': i, 'value': i} for i in available_indicators],\n", 109 | " value='Life expectancy at birth, total (years)'\n", 110 | " ),\n", 111 | " dcc.RadioItems(\n", 112 | " id='crossfilter-yaxis-type',\n", 113 | " options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],\n", 114 | " value='Linear',\n", 115 | " labelStyle={'display': 'inline-block'}\n", 116 | " )\n", 117 | " ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})\n", 118 | " ], style={\n", 119 | " 'borderBottom': 'thin lightgrey solid',\n", 120 | " 'backgroundColor': 'rgb(250, 250, 250)',\n", 121 | " 'padding': '10px 5px'\n", 122 | " }),\n", 123 | "\n", 124 | " html.Div([\n", 125 | " dcc.Graph(\n", 126 | " id='crossfilter-indicator-scatter',\n", 127 | " hoverData={'points': [{'customdata': 'Japan'}]}\n", 128 | " )\n", 129 | " ], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}),\n", 130 | " html.Div([\n", 131 | " dcc.Graph(id='x-time-series'),\n", 132 | " dcc.Graph(id='y-time-series'),\n", 133 | " ], style={'display': 'inline-block', 'width': '49%'}),\n", 134 | "\n", 135 | " html.Div(dcc.Slider(\n", 136 | " id='crossfilter-year--slider',\n", 137 | " min=df['Year'].min(),\n", 138 | " max=df['Year'].max(),\n", 139 | " value=df['Year'].max(),\n", 140 | " marks={str(year): str(year) for year in df['Year'].unique()},\n", 141 | " step=None\n", 142 | " ), style={'width': '49%', 'padding': '0px 20px 20px 20px'})\n", 143 | "])\n", 144 | "\n", 145 | "\n", 146 | "@app.callback(\n", 147 | " dash.dependencies.Output('crossfilter-indicator-scatter', 'figure'),\n", 148 | " [dash.dependencies.Input('crossfilter-xaxis-column', 'value'),\n", 149 | " dash.dependencies.Input('crossfilter-yaxis-column', 'value'),\n", 150 | " dash.dependencies.Input('crossfilter-xaxis-type', 'value'),\n", 151 | " dash.dependencies.Input('crossfilter-yaxis-type', 'value'),\n", 152 | " dash.dependencies.Input('crossfilter-year--slider', 'value')])\n", 153 | "def update_graph(xaxis_column_name, yaxis_column_name,\n", 154 | " xaxis_type, yaxis_type,\n", 155 | " year_value):\n", 156 | " dff = df[df['Year'] == year_value]\n", 157 | "\n", 158 | " return {\n", 159 | " 'data': [dict(\n", 160 | " x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],\n", 161 | " y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],\n", 162 | " text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],\n", 163 | " customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],\n", 164 | " mode='markers',\n", 165 | " marker={\n", 166 | " 'size': 25,\n", 167 | " 'opacity': 0.7,\n", 168 | " 'color': 'orange',\n", 169 | " 'line': {'width': 2, 'color': 'purple'}\n", 170 | " }\n", 171 | " )],\n", 172 | " 'layout': dict(\n", 173 | " xaxis={\n", 174 | " 'title': xaxis_column_name,\n", 175 | " 'type': 'linear' if xaxis_type == 'Linear' else 'log'\n", 176 | " },\n", 177 | " yaxis={\n", 178 | " 'title': yaxis_column_name,\n", 179 | " 'type': 'linear' if yaxis_type == 'Linear' else 'log'\n", 180 | " },\n", 181 | " margin={'l': 40, 'b': 30, 't': 10, 'r': 0},\n", 182 | " height=450,\n", 183 | " hovermode='closest'\n", 184 | " )\n", 185 | " }\n", 186 | "\n", 187 | "\n", 188 | "def create_time_series(dff, axis_type, title):\n", 189 | " return {\n", 190 | " 'data': [dict(\n", 191 | " x=dff['Year'],\n", 192 | " y=dff['Value'],\n", 193 | " mode='lines+markers'\n", 194 | " )],\n", 195 | " 'layout': {\n", 196 | " 'height': 225,\n", 197 | " 'margin': {'l': 20, 'b': 30, 'r': 10, 't': 10},\n", 198 | " 'annotations': [{\n", 199 | " 'x': 0, 'y': 0.85, 'xanchor': 'left', 'yanchor': 'bottom',\n", 200 | " 'xref': 'paper', 'yref': 'paper', 'showarrow': False,\n", 201 | " 'align': 'left', 'bgcolor': 'rgba(255, 255, 255, 0.5)',\n", 202 | " 'text': title\n", 203 | " }],\n", 204 | " 'yaxis': {'type': 'linear' if axis_type == 'Linear' else 'log'},\n", 205 | " 'xaxis': {'showgrid': False}\n", 206 | " }\n", 207 | " }\n", 208 | "\n", 209 | "\n", 210 | "@app.callback(\n", 211 | " dash.dependencies.Output('x-time-series', 'figure'),\n", 212 | " [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),\n", 213 | " dash.dependencies.Input('crossfilter-xaxis-column', 'value'),\n", 214 | " dash.dependencies.Input('crossfilter-xaxis-type', 'value')])\n", 215 | "def update_y_timeseries(hoverData, xaxis_column_name, axis_type):\n", 216 | " country_name = hoverData['points'][0]['customdata']\n", 217 | " dff = df[df['Country Name'] == country_name]\n", 218 | " dff = dff[dff['Indicator Name'] == xaxis_column_name]\n", 219 | " title = '{}
{}'.format(country_name, xaxis_column_name)\n", 220 | " return create_time_series(dff, axis_type, title)\n", 221 | "\n", 222 | "\n", 223 | "@app.callback(\n", 224 | " dash.dependencies.Output('y-time-series', 'figure'),\n", 225 | " [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),\n", 226 | " dash.dependencies.Input('crossfilter-yaxis-column', 'value'),\n", 227 | " dash.dependencies.Input('crossfilter-yaxis-type', 'value')])\n", 228 | "def update_x_timeseries(hoverData, yaxis_column_name, axis_type):\n", 229 | " dff = df[df['Country Name'] == hoverData['points'][0]['customdata']]\n", 230 | " dff = dff[dff['Indicator Name'] == yaxis_column_name]\n", 231 | " return create_time_series(dff, axis_type, yaxis_column_name)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "Serve the app using `run_server`. Unlike the standard `Dash.run_server` method, the `JupyterDash.run_server` method doesn't block execution of the notebook. It serves the app in a background thread, making it possible to run other notebook calculations while the app is running.\n", 239 | "\n", 240 | "This makes it possible to iteratively update the app without rerunning the potentially expensive data processing steps." 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": {}, 247 | "outputs": [], 248 | "source": [ 249 | "app.run_server()" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": {}, 255 | "source": [ 256 | "By default, `run_server` displays a URL that you can click on to open the app in a browser tab. The `mode` argument to `run_server` can be used to change this behavior. Setting `mode=\"inline\"` will display the app directly in the notebook output cell." 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": null, 262 | "metadata": {}, 263 | "outputs": [], 264 | "source": [ 265 | "app.run_server(mode=\"inline\")" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "When running in JupyterLab, with the `jupyterlab-dash` extension, setting `mode=\"jupyterlab\"` will open the app in a tab in JupyterLab.\n", 273 | "\n", 274 | "```python\n", 275 | "app.run_server(mode=\"jupyterlab\")\n", 276 | "```" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [] 285 | } 286 | ], 287 | "metadata": { 288 | "jupytext": { 289 | "formats": "ipynb,py:percent" 290 | }, 291 | "kernelspec": { 292 | "display_name": "Python 3", 293 | "language": "python", 294 | "name": "python3" 295 | }, 296 | "language_info": { 297 | "codemirror_mode": { 298 | "name": "ipython", 299 | "version": 3 300 | }, 301 | "file_extension": ".py", 302 | "mimetype": "text/x-python", 303 | "name": "python", 304 | "nbconvert_exporter": "python", 305 | "pygments_lexer": "ipython3", 306 | "version": "3.7.7" 307 | } 308 | }, 309 | "nbformat": 4, 310 | "nbformat_minor": 4 311 | } 312 | -------------------------------------------------------------------------------- /notebooks/getting_started.py: -------------------------------------------------------------------------------- 1 | # --- 2 | # jupyter: 3 | # jupytext: 4 | # formats: ipynb,py:percent 5 | # text_representation: 6 | # extension: .py 7 | # format_name: percent 8 | # format_version: '1.3' 9 | # jupytext_version: 1.4.2 10 | # kernelspec: 11 | # display_name: Python 3 12 | # language: python 13 | # name: python3 14 | # --- 15 | 16 | # %% [markdown] 17 | # # JupyterDash 18 | # The `jupyter-dash` package makes it easy to develop Plotly Dash apps from the Jupyter Notebook and JupyterLab. 19 | # 20 | # Just replace the standard `dash.Dash` class with the `jupyter_dash.JupyterDash` subclass. 21 | 22 | # %% 23 | from jupyter_dash import JupyterDash 24 | 25 | # %% 26 | import dash 27 | import dash_core_components as dcc 28 | import dash_html_components as html 29 | import pandas as pd 30 | 31 | # %% [markdown] 32 | # When running in JupyterHub or Binder, call the `infer_jupyter_config` function to detect the proxy configuration. 33 | 34 | # %% 35 | JupyterDash.infer_jupyter_proxy_config() 36 | 37 | # %% [markdown] 38 | # Load and preprocess data 39 | 40 | # %% 41 | df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv') 42 | available_indicators = df['Indicator Name'].unique() 43 | 44 | # %% [markdown] 45 | # Construct the app and callbacks 46 | 47 | # %% 48 | external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] 49 | 50 | app = JupyterDash(__name__, external_stylesheets=external_stylesheets) 51 | 52 | # Create server variable with Flask server object for use with gunicorn 53 | server = app.server 54 | 55 | app.layout = html.Div([ 56 | html.Div([ 57 | 58 | html.Div([ 59 | dcc.Dropdown( 60 | id='crossfilter-xaxis-column', 61 | options=[{'label': i, 'value': i} for i in available_indicators], 62 | value='Fertility rate, total (births per woman)' 63 | ), 64 | dcc.RadioItems( 65 | id='crossfilter-xaxis-type', 66 | options=[{'label': i, 'value': i} for i in ['Linear', 'Log']], 67 | value='Linear', 68 | labelStyle={'display': 'inline-block'} 69 | ) 70 | ], 71 | style={'width': '49%', 'display': 'inline-block'}), 72 | 73 | html.Div([ 74 | dcc.Dropdown( 75 | id='crossfilter-yaxis-column', 76 | options=[{'label': i, 'value': i} for i in available_indicators], 77 | value='Life expectancy at birth, total (years)' 78 | ), 79 | dcc.RadioItems( 80 | id='crossfilter-yaxis-type', 81 | options=[{'label': i, 'value': i} for i in ['Linear', 'Log']], 82 | value='Linear', 83 | labelStyle={'display': 'inline-block'} 84 | ) 85 | ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'}) 86 | ], style={ 87 | 'borderBottom': 'thin lightgrey solid', 88 | 'backgroundColor': 'rgb(250, 250, 250)', 89 | 'padding': '10px 5px' 90 | }), 91 | 92 | html.Div([ 93 | dcc.Graph( 94 | id='crossfilter-indicator-scatter', 95 | hoverData={'points': [{'customdata': 'Japan'}]} 96 | ) 97 | ], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}), 98 | html.Div([ 99 | dcc.Graph(id='x-time-series'), 100 | dcc.Graph(id='y-time-series'), 101 | ], style={'display': 'inline-block', 'width': '49%'}), 102 | 103 | html.Div(dcc.Slider( 104 | id='crossfilter-year--slider', 105 | min=df['Year'].min(), 106 | max=df['Year'].max(), 107 | value=df['Year'].max(), 108 | marks={str(year): str(year) for year in df['Year'].unique()}, 109 | step=None 110 | ), style={'width': '49%', 'padding': '0px 20px 20px 20px'}) 111 | ]) 112 | 113 | 114 | @app.callback( 115 | dash.dependencies.Output('crossfilter-indicator-scatter', 'figure'), 116 | [dash.dependencies.Input('crossfilter-xaxis-column', 'value'), 117 | dash.dependencies.Input('crossfilter-yaxis-column', 'value'), 118 | dash.dependencies.Input('crossfilter-xaxis-type', 'value'), 119 | dash.dependencies.Input('crossfilter-yaxis-type', 'value'), 120 | dash.dependencies.Input('crossfilter-year--slider', 'value')]) 121 | def update_graph(xaxis_column_name, yaxis_column_name, 122 | xaxis_type, yaxis_type, 123 | year_value): 124 | dff = df[df['Year'] == year_value] 125 | 126 | return { 127 | 'data': [dict( 128 | x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'], 129 | y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'], 130 | text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'], 131 | customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'], 132 | mode='markers', 133 | marker={ 134 | 'size': 25, 135 | 'opacity': 0.7, 136 | 'color': 'orange', 137 | 'line': {'width': 2, 'color': 'purple'} 138 | } 139 | )], 140 | 'layout': dict( 141 | xaxis={ 142 | 'title': xaxis_column_name, 143 | 'type': 'linear' if xaxis_type == 'Linear' else 'log' 144 | }, 145 | yaxis={ 146 | 'title': yaxis_column_name, 147 | 'type': 'linear' if yaxis_type == 'Linear' else 'log' 148 | }, 149 | margin={'l': 40, 'b': 30, 't': 10, 'r': 0}, 150 | height=450, 151 | hovermode='closest' 152 | ) 153 | } 154 | 155 | 156 | def create_time_series(dff, axis_type, title): 157 | return { 158 | 'data': [dict( 159 | x=dff['Year'], 160 | y=dff['Value'], 161 | mode='lines+markers' 162 | )], 163 | 'layout': { 164 | 'height': 225, 165 | 'margin': {'l': 20, 'b': 30, 'r': 10, 't': 10}, 166 | 'annotations': [{ 167 | 'x': 0, 'y': 0.85, 'xanchor': 'left', 'yanchor': 'bottom', 168 | 'xref': 'paper', 'yref': 'paper', 'showarrow': False, 169 | 'align': 'left', 'bgcolor': 'rgba(255, 255, 255, 0.5)', 170 | 'text': title 171 | }], 172 | 'yaxis': {'type': 'linear' if axis_type == 'Linear' else 'log'}, 173 | 'xaxis': {'showgrid': False} 174 | } 175 | } 176 | 177 | 178 | @app.callback( 179 | dash.dependencies.Output('x-time-series', 'figure'), 180 | [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'), 181 | dash.dependencies.Input('crossfilter-xaxis-column', 'value'), 182 | dash.dependencies.Input('crossfilter-xaxis-type', 'value')]) 183 | def update_y_timeseries(hoverData, xaxis_column_name, axis_type): 184 | country_name = hoverData['points'][0]['customdata'] 185 | dff = df[df['Country Name'] == country_name] 186 | dff = dff[dff['Indicator Name'] == xaxis_column_name] 187 | title = '{}
{}'.format(country_name, xaxis_column_name) 188 | return create_time_series(dff, axis_type, title) 189 | 190 | 191 | @app.callback( 192 | dash.dependencies.Output('y-time-series', 'figure'), 193 | [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'), 194 | dash.dependencies.Input('crossfilter-yaxis-column', 'value'), 195 | dash.dependencies.Input('crossfilter-yaxis-type', 'value')]) 196 | def update_x_timeseries(hoverData, yaxis_column_name, axis_type): 197 | dff = df[df['Country Name'] == hoverData['points'][0]['customdata']] 198 | dff = dff[dff['Indicator Name'] == yaxis_column_name] 199 | return create_time_series(dff, axis_type, yaxis_column_name) 200 | 201 | 202 | # %% [markdown] 203 | # Serve the app using `run_server`. Unlike the standard `Dash.run_server` method, the `JupyterDash.run_server` method doesn't block execution of the notebook. It serves the app in a background thread, making it possible to run other notebook calculations while the app is running. 204 | # 205 | # This makes it possible to iteratively update the app without rerunning the potentially expensive data processing steps. 206 | 207 | # %% 208 | app.run_server() 209 | 210 | # %% [markdown] 211 | # By default, `run_server` displays a URL that you can click on to open the app in a browser tab. The `mode` argument to `run_server` can be used to change this behavior. Setting `mode="inline"` will display the app directly in the notebook output cell. 212 | 213 | # %% 214 | app.run_server(mode="inline") 215 | 216 | # %% [markdown] 217 | # When running in JupyterLab, with the `jupyterlab-dash` extension, setting `mode="jupyterlab"` will open the app in a tab in JupyterLab. 218 | # 219 | # ```python 220 | # app.run_server(mode="jupyterlab") 221 | # ``` 222 | 223 | # %% 224 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | jupyterlab>=2.0 2 | notebook>=6.0 3 | jupyter_server_proxy 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | dash 2 | requests 3 | flask 4 | retrying 5 | ipython 6 | ipykernel 7 | ansi2html 8 | nest-asyncio 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from subprocess import check_call 4 | import json 5 | import time 6 | 7 | from setuptools import setup, Command 8 | 9 | here = os.path.dirname(os.path.abspath(__file__)) 10 | is_repo = os.path.exists(os.path.join(here, ".git")) 11 | 12 | 13 | # Load __version__ using exec so that we don't import jupyter_dash module 14 | main_ns = {} 15 | exec(open("jupyter_dash/version.py").read(), main_ns) # pylint: disable=exec-used 16 | 17 | 18 | def get_labextension_version(): 19 | if is_repo: 20 | labextension_dir = os.path.join(here, "extensions", "jupyterlab") 21 | else: 22 | labextension_dir = os.path.join(here, "jupyter_dash", "labextension") 23 | 24 | package_json = os.path.join(labextension_dir, 'package.json') 25 | with open(package_json, 'rt') as f: 26 | package_data = json.load(f) 27 | 28 | labextension_version = package_data['version'] 29 | return labextension_version 30 | 31 | 32 | def js_prerelease(command): 33 | """decorator for building JavaScript extensions before command""" 34 | class DecoratedCommand(command): 35 | def run(self): 36 | self.run_command("build_js") 37 | command.run(self) 38 | return DecoratedCommand 39 | 40 | 41 | class BuildLabextension(Command): 42 | description = "Build JupyterLab extension" 43 | user_options = [] 44 | 45 | def initialize_options(self): 46 | pass 47 | 48 | def finalize_options(self): 49 | pass 50 | 51 | def run(self): 52 | if not is_repo: 53 | # Nothing to do 54 | return 55 | 56 | # Load labextension version from package.json 57 | out_labextension_dir = os.path.join(here, "jupyter_dash", "labextension") 58 | os.makedirs(out_labextension_dir, exist_ok=True) 59 | 60 | # Copy package.json to labextension directory 61 | shutil.copy( 62 | os.path.join(here, "extensions", "jupyterlab", "package.json"), 63 | out_labextension_dir 64 | ) 65 | time.sleep(0.5) 66 | in_labextension_dir = os.path.join(here, "extensions", "jupyterlab") 67 | 68 | # Build filename 69 | labextension_version = get_labextension_version() 70 | filename = "jupyterlab-dash-v{ver}.tgz".format( 71 | ver=labextension_version 72 | ) 73 | 74 | # Build and pack extension 75 | dist_path = os.path.join(out_labextension_dir, "dist") 76 | shutil.rmtree(dist_path, ignore_errors=True) 77 | os.makedirs(dist_path, exist_ok=True) 78 | 79 | check_call( 80 | ['jlpm', "install"], 81 | cwd=in_labextension_dir, 82 | ) 83 | check_call( 84 | ['jlpm', "build"], 85 | cwd=in_labextension_dir, 86 | ) 87 | check_call( 88 | ['jlpm', "pack", "--filename", dist_path + "/" + filename], 89 | cwd=in_labextension_dir, 90 | ) 91 | 92 | # Copy README to extension directory so npm finds it 93 | shutil.copy( 94 | os.path.join(here, "README.md"), 95 | os.path.join(here, "extensions", "jupyterlab", "README.md"), 96 | ) 97 | 98 | 99 | def readme(): 100 | with open(os.path.join(here, "README.md")) as f: 101 | return f.read() 102 | 103 | 104 | # Load requirements.txt 105 | with open(os.path.join(here, 'requirements.txt')) as f: 106 | requirements = [req.strip() for req in f.read().split('\n') if req.strip()] 107 | 108 | # Load requirements-dev.txt 109 | with open(os.path.join(here, 'requirements-dev.txt')) as f: 110 | dev_requirements = [req.strip() for req in f.read().split('\n') if req.strip()] 111 | 112 | 113 | setup( 114 | name='jupyter-dash', 115 | version=main_ns["__version__"], 116 | description="Dash support for the Jupyter notebook interface", 117 | long_description=readme(), 118 | long_description_content_type="text/markdown", 119 | author='Plotly', 120 | license="MIT", 121 | url="https://github.com/plotly/jupyter-dash", 122 | project_urls={"Github": "https://github.com/plotly/jupyter-dash"}, 123 | packages=['jupyter_dash'], 124 | install_requires=requirements, 125 | extras_require={ 126 | 'dev': dev_requirements 127 | }, 128 | include_package_data=True, 129 | package_data={ 130 | "jupyter_dash": [ 131 | "labextension/package.json", 132 | ], 133 | }, 134 | python_requires=">=3.5", 135 | data_files=[ 136 | # like `jupyter nbextension install --sys-prefix` 137 | ("share/jupyter/nbextensions/jupyter_dash", [ 138 | "jupyter_dash/nbextension/main.js", 139 | ]), 140 | # like `jupyter nbextension enable --sys-prefix` 141 | ("etc/jupyter/nbconfig/notebook.d", [ 142 | "jupyter_dash/nbextension/jupyter_dash.json" 143 | ]), 144 | # Place jupyterlab extension in extension directory 145 | ("share/jupyter/lab/extensions", [ 146 | "jupyter_dash/labextension/dist/jupyterlab-dash-v{ver}.tgz".format( 147 | ver=get_labextension_version() 148 | ) 149 | ]), 150 | ], 151 | cmdclass=dict( 152 | build_js=BuildLabextension, 153 | ) 154 | ) 155 | --------------------------------------------------------------------------------