From 8754a5e7e23a76bc620033c40d1259faed6408ab Mon Sep 17 00:00:00 2001 From: Samuel Gaist <samuel.gaist@idiap.ch> Date: Thu, 3 Jan 2019 11:22:56 +0100 Subject: [PATCH] [conda] Remove all js files --- conda/js/.babelrc | 33 - conda/js/.eslintrc.js | 57 - conda/js/.flowconfig | 19 - conda/js/.postcssrc | 6 - conda/js/.stylelintrc | 6 - conda/js/.tern-project | 19 - conda/js/index.html | 10 - conda/js/karma.conf.js | 55 - conda/js/main.css | 91 - conda/js/main.jsx | 18 - conda/js/package-lock.json | 17510 ---------------- conda/js/package.json | 103 - conda/js/src/components/App.jsx | 48 - conda/js/src/components/CacheInput.jsx | 198 - conda/js/src/components/CacheInput.spec.jsx | 63 - conda/js/src/components/DeleteInputBtn.jsx | 25 - .../js/src/components/DeleteInputBtn.spec.jsx | 29 - conda/js/src/components/EntityDetail.jsx | 247 - conda/js/src/components/EntityHome.jsx | 85 - conda/js/src/components/EntityList.jsx | 208 - .../EntityTemplateGenerationButton.jsx | 139 - conda/js/src/components/HomeContent.jsx | 41 - conda/js/src/components/InfoTooltip.jsx | 30 - conda/js/src/components/MainContent.jsx | 27 - conda/js/src/components/MainNav.jsx | 156 - conda/js/src/components/NewEntityModal.jsx | 537 - .../js/src/components/NewEntityModal.spec.jsx | 447 - conda/js/src/components/ParameterConsume.jsx | 88 - conda/js/src/components/ParameterCreate.jsx | 381 - .../src/components/ParameterCreate.spec.jsx | 69 - conda/js/src/components/SearchBar.jsx | 145 - conda/js/src/components/Settings.jsx | 84 - conda/js/src/components/TypedField.jsx | 75 - conda/js/src/components/ValidSchemaBadge.jsx | 30 - .../src/components/ValidSchemaBadge.spec.jsx | 207 - .../components/algorithm/AlgorithmEditor.jsx | 729 - .../algorithm/AlgorithmEditor.spec.jsx | 691 - conda/js/src/components/algorithm/index.js | 8 - .../components/database/DatabaseEditor.css | 18 - .../components/database/DatabaseEditor.jsx | 984 - .../database/DatabaseEditor.spec.jsx | 455 - conda/js/src/components/database/index.js | 8 - .../dataformat/DataformatEditor.jsx | 292 - .../dataformat/DataformatEditor.spec.jsx | 261 - conda/js/src/components/dataformat/index.js | 8 - .../experiment/ExperimentEditor.css | 3 - .../experiment/ExperimentEditor.jsx | 1398 -- .../experiment/ExperimentEditor.spec.jsx | 694 - conda/js/src/components/experiment/index.js | 8 - .../src/components/library/LibraryEditor.jsx | 188 - .../components/library/LibraryEditor.spec.jsx | 124 - conda/js/src/components/library/index.js | 8 - .../src/components/plotter/PlotterEditor.jsx | 277 - .../components/plotter/PlotterEditor.spec.jsx | 236 - conda/js/src/components/plotter/index.js | 8 - .../PlotterParameterEditor.jsx | 193 - .../PlotterParameterEditor.spec.jsx | 126 - .../src/components/plotterparameter/index.js | 8 - .../components/toolchain/GraphicalEditor.css | 72 - .../components/toolchain/GraphicalEditor.jsx | 1134 - .../toolchain/GraphicalEditorHelpModal.jsx | 239 - .../toolchain/InsertObjectModal.jsx | 399 - .../components/toolchain/RenameGroupModal.jsx | 93 - .../components/toolchain/ToolchainBlock.jsx | 308 - .../toolchain/ToolchainConnection.jsx | 134 - .../toolchain/ToolchainConnection.spec.jsx | 117 - .../components/toolchain/ToolchainEditor.css | 18 - .../components/toolchain/ToolchainEditor.jsx | 1520 -- .../toolchain/ToolchainEditor.spec.jsx | 1103 - .../components/toolchain/ToolchainModal.jsx | 522 - .../toolchain/ToolchainModal.spec.jsx | 172 - conda/js/src/components/toolchain/index.js | 10 - conda/js/src/helpers/api.js | 114 - conda/js/src/helpers/beat.js | 525 - conda/js/src/helpers/beat.spec.js | 21 - conda/js/src/helpers/index.js | 58 - conda/js/src/helpers/schema/algorithm.json | 226 - conda/js/src/helpers/schema/common.json | 78 - conda/js/src/helpers/schema/database.json | 117 - conda/js/src/helpers/schema/dataformat.json | 131 - conda/js/src/helpers/schema/execution.json | 201 - conda/js/src/helpers/schema/experiment.json | 177 - conda/js/src/helpers/schema/index.js | 44 - conda/js/src/helpers/schema/library.json | 20 - conda/js/src/helpers/schema/plotter.json | 28 - .../src/helpers/schema/plotterparameter.json | 21 - conda/js/src/helpers/schema/toolchain.json | 215 - conda/js/src/helpers/search.worker.js | 41 - conda/js/src/helpers/toolchainTypes.js | 65 - conda/js/src/store/actionTypes.js | 65 - conda/js/src/store/actions.js | 180 - conda/js/src/store/index.js | 9 - conda/js/src/store/reducers.js | 129 - conda/js/src/store/selectors.js | 102 - conda/js/src/store/store.js | 32 - conda/js/test/index.js | 32 - conda/js/test/selenium_test.js | 17 - conda/js/test/selenium_tutorial_test.js | 380 - conda/js/test/test_algs.json | 1290 -- conda/js/test/test_dbs.json | 2511 --- conda/js/test/test_dfs.json | 427 - conda/js/test/test_exps.json | 787 - conda/js/test/test_libs.json | 18 - conda/js/test/test_plotterparameters.json | 42 - conda/js/test/test_plotters.json | 341 - conda/js/test/test_tcs.json | 2934 --- conda/js/webpack.config.js | 159 - 107 files changed, 45389 deletions(-) delete mode 100644 conda/js/.babelrc delete mode 100644 conda/js/.eslintrc.js delete mode 100644 conda/js/.flowconfig delete mode 100644 conda/js/.postcssrc delete mode 100644 conda/js/.stylelintrc delete mode 100644 conda/js/.tern-project delete mode 100644 conda/js/index.html delete mode 100644 conda/js/karma.conf.js delete mode 100644 conda/js/main.css delete mode 100644 conda/js/main.jsx delete mode 100644 conda/js/package-lock.json delete mode 100644 conda/js/package.json delete mode 100644 conda/js/src/components/App.jsx delete mode 100644 conda/js/src/components/CacheInput.jsx delete mode 100644 conda/js/src/components/CacheInput.spec.jsx delete mode 100644 conda/js/src/components/DeleteInputBtn.jsx delete mode 100644 conda/js/src/components/DeleteInputBtn.spec.jsx delete mode 100644 conda/js/src/components/EntityDetail.jsx delete mode 100644 conda/js/src/components/EntityHome.jsx delete mode 100644 conda/js/src/components/EntityList.jsx delete mode 100644 conda/js/src/components/EntityTemplateGenerationButton.jsx delete mode 100644 conda/js/src/components/HomeContent.jsx delete mode 100644 conda/js/src/components/InfoTooltip.jsx delete mode 100644 conda/js/src/components/MainContent.jsx delete mode 100644 conda/js/src/components/MainNav.jsx delete mode 100644 conda/js/src/components/NewEntityModal.jsx delete mode 100644 conda/js/src/components/NewEntityModal.spec.jsx delete mode 100644 conda/js/src/components/ParameterConsume.jsx delete mode 100644 conda/js/src/components/ParameterCreate.jsx delete mode 100644 conda/js/src/components/ParameterCreate.spec.jsx delete mode 100644 conda/js/src/components/SearchBar.jsx delete mode 100644 conda/js/src/components/Settings.jsx delete mode 100644 conda/js/src/components/TypedField.jsx delete mode 100644 conda/js/src/components/ValidSchemaBadge.jsx delete mode 100644 conda/js/src/components/ValidSchemaBadge.spec.jsx delete mode 100644 conda/js/src/components/algorithm/AlgorithmEditor.jsx delete mode 100644 conda/js/src/components/algorithm/AlgorithmEditor.spec.jsx delete mode 100644 conda/js/src/components/algorithm/index.js delete mode 100644 conda/js/src/components/database/DatabaseEditor.css delete mode 100644 conda/js/src/components/database/DatabaseEditor.jsx delete mode 100644 conda/js/src/components/database/DatabaseEditor.spec.jsx delete mode 100644 conda/js/src/components/database/index.js delete mode 100644 conda/js/src/components/dataformat/DataformatEditor.jsx delete mode 100644 conda/js/src/components/dataformat/DataformatEditor.spec.jsx delete mode 100644 conda/js/src/components/dataformat/index.js delete mode 100644 conda/js/src/components/experiment/ExperimentEditor.css delete mode 100644 conda/js/src/components/experiment/ExperimentEditor.jsx delete mode 100644 conda/js/src/components/experiment/ExperimentEditor.spec.jsx delete mode 100644 conda/js/src/components/experiment/index.js delete mode 100644 conda/js/src/components/library/LibraryEditor.jsx delete mode 100644 conda/js/src/components/library/LibraryEditor.spec.jsx delete mode 100644 conda/js/src/components/library/index.js delete mode 100644 conda/js/src/components/plotter/PlotterEditor.jsx delete mode 100644 conda/js/src/components/plotter/PlotterEditor.spec.jsx delete mode 100644 conda/js/src/components/plotter/index.js delete mode 100644 conda/js/src/components/plotterparameter/PlotterParameterEditor.jsx delete mode 100644 conda/js/src/components/plotterparameter/PlotterParameterEditor.spec.jsx delete mode 100644 conda/js/src/components/plotterparameter/index.js delete mode 100644 conda/js/src/components/toolchain/GraphicalEditor.css delete mode 100644 conda/js/src/components/toolchain/GraphicalEditor.jsx delete mode 100644 conda/js/src/components/toolchain/GraphicalEditorHelpModal.jsx delete mode 100644 conda/js/src/components/toolchain/InsertObjectModal.jsx delete mode 100644 conda/js/src/components/toolchain/RenameGroupModal.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainBlock.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainConnection.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainConnection.spec.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainEditor.css delete mode 100644 conda/js/src/components/toolchain/ToolchainEditor.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainEditor.spec.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainModal.jsx delete mode 100644 conda/js/src/components/toolchain/ToolchainModal.spec.jsx delete mode 100644 conda/js/src/components/toolchain/index.js delete mode 100644 conda/js/src/helpers/api.js delete mode 100644 conda/js/src/helpers/beat.js delete mode 100644 conda/js/src/helpers/beat.spec.js delete mode 100644 conda/js/src/helpers/index.js delete mode 100644 conda/js/src/helpers/schema/algorithm.json delete mode 100644 conda/js/src/helpers/schema/common.json delete mode 100644 conda/js/src/helpers/schema/database.json delete mode 100644 conda/js/src/helpers/schema/dataformat.json delete mode 100644 conda/js/src/helpers/schema/execution.json delete mode 100644 conda/js/src/helpers/schema/experiment.json delete mode 100644 conda/js/src/helpers/schema/index.js delete mode 100644 conda/js/src/helpers/schema/library.json delete mode 100644 conda/js/src/helpers/schema/plotter.json delete mode 100644 conda/js/src/helpers/schema/plotterparameter.json delete mode 100644 conda/js/src/helpers/schema/toolchain.json delete mode 100644 conda/js/src/helpers/search.worker.js delete mode 100644 conda/js/src/helpers/toolchainTypes.js delete mode 100644 conda/js/src/store/actionTypes.js delete mode 100644 conda/js/src/store/actions.js delete mode 100644 conda/js/src/store/index.js delete mode 100644 conda/js/src/store/reducers.js delete mode 100644 conda/js/src/store/selectors.js delete mode 100644 conda/js/src/store/store.js delete mode 100644 conda/js/test/index.js delete mode 100644 conda/js/test/selenium_test.js delete mode 100644 conda/js/test/selenium_tutorial_test.js delete mode 100644 conda/js/test/test_algs.json delete mode 100644 conda/js/test/test_dbs.json delete mode 100644 conda/js/test/test_dfs.json delete mode 100644 conda/js/test/test_exps.json delete mode 100644 conda/js/test/test_libs.json delete mode 100644 conda/js/test/test_plotterparameters.json delete mode 100644 conda/js/test/test_plotters.json delete mode 100644 conda/js/test/test_tcs.json delete mode 100644 conda/js/webpack.config.js diff --git a/conda/js/.babelrc b/conda/js/.babelrc deleted file mode 100644 index c9512750..00000000 --- a/conda/js/.babelrc +++ /dev/null @@ -1,33 +0,0 @@ -{ - "plugins": [ - "@babel/plugin-syntax-flow", - "@babel/plugin-proposal-object-rest-spread", - "@babel/plugin-proposal-class-properties" - ], - "presets": [ - "@babel/preset-react", - [ - "@babel/preset-env", - { - "modules": false, - "debug": true, - "targets": { - "browsers": [ - "last 1 Firefox versions", - "last 1 Chrome versions" - ] - } - } - ], - "@babel/preset-flow" - ], - "env": { - "test": { - "plugins": [ - ] - } - }, - "ignore": [ - "node_modules" - ] -} diff --git a/conda/js/.eslintrc.js b/conda/js/.eslintrc.js deleted file mode 100644 index 57b44007..00000000 --- a/conda/js/.eslintrc.js +++ /dev/null @@ -1,57 +0,0 @@ -module.exports = { - env: { - 'browser': true, - 'worker': true, - - }, - parserOptions: { - 'parser': 'babel-eslint', - 'ecmaVersion': 8, - 'sourceType': 'module', - 'modules': true, - 'ecmaFeatures': { - 'jsx': true, - 'impliedStrict': true, - 'experimentalObjectRestSpread': true, - }, - }, - extends: [ - 'plugin:react/recommended', - 'plugin:flowtype/recommended', - ], - plugins: [ - // lints for browser support (APIs and such) - // uses browserslist tech - 'compat', - // react - 'react', - // flow type annotations - 'flowtype', - ], - rules: { - // tabs not spaces - 'indent': [ - 'error', - 'tab', - // indent for switch statements - { - 'SwitchCase': 1, - 'MemberExpression': 0 - } - ], - // we want tabs - 'no-tabs': 0, - // only unix endings - 'linebreak-style': ['error', 'unix'], - // single quotes & double quotes are the same, - // but encourage single quotes cuz its one less - // button press - 'quotes': ['error', 'single', { 'allowTemplateLiterals': true }], - // always use semi-colons at end of statements - 'semi': ['error', 'always'], - // errors from compat are real errors - 'compat/compat': 2, - // always have spaces in template strings curly braces - 'template-curly-spacing': ['error', 'always'], - } -}; diff --git a/conda/js/.flowconfig b/conda/js/.flowconfig deleted file mode 100644 index 8fcfd3c5..00000000 --- a/conda/js/.flowconfig +++ /dev/null @@ -1,19 +0,0 @@ -[ignore] -<PROJECT_ROOT>/node_modules/ -.*\.spec\.jsx - -[include] -<PROJECT_ROOT>/node_modules/react-dom/ -<PROJECT_ROOT>/node_modules/react-router-dom/ -<PROJECT_ROOT>/node_modules/reactstrap/ -<PROJECT_ROOT>/src/* - -[libs] -<PROJECT_ROOT>/flow-typed/ - -[lints] - -[options] -module.name_mapper='^@helpers' ->'<PROJECT_ROOT>/src/helpers' -module.name_mapper='^@store' ->'<PROJECT_ROOT>/src/store' -module.name_mapper='^@test' ->'<PROJECT_ROOT>/test' diff --git a/conda/js/.postcssrc b/conda/js/.postcssrc deleted file mode 100644 index e64b3871..00000000 --- a/conda/js/.postcssrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "plugins": { - "postcss-smart-import": {}, - "postcss-cssnext": {} - } -} diff --git a/conda/js/.stylelintrc b/conda/js/.stylelintrc deleted file mode 100644 index 7fd1f968..00000000 --- a/conda/js/.stylelintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "stylelint-config-standard", - "rules": { - "indentation": "tab" - } -} diff --git a/conda/js/.tern-project b/conda/js/.tern-project deleted file mode 100644 index 1c7aa90e..00000000 --- a/conda/js/.tern-project +++ /dev/null @@ -1,19 +0,0 @@ -{ - "ecmaVersion": 6, - "libs": [ - "browser", - "react" - ], - "plugins": { - "jsx": {}, - "modules": {}, - "es_modules": {}, - "webpack": { - "configPath": "./webpack.config.js" - } - }, - "loadEagerly": [ - "./src/**/*.js", - "./src/**/*.jsx" - ] -} diff --git a/conda/js/index.html b/conda/js/index.html deleted file mode 100644 index 604daab9..00000000 --- a/conda/js/index.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8"> - <title></title> - </head> - <body> - <div id="root"></div> - </body> -</html> diff --git a/conda/js/karma.conf.js b/conda/js/karma.conf.js deleted file mode 100644 index c50582ce..00000000 --- a/conda/js/karma.conf.js +++ /dev/null @@ -1,55 +0,0 @@ -// we can just use the exact same webpack config by requiring it -// however, remember to delete the original entry since we don't -// need it during tests -let webpackConfig = require('./webpack.config.js'); -delete webpackConfig.entry; - -// karma.conf.js -module.exports = function (config) { - config.set({ - browsers: [ - 'FirefoxHeadless', - //'ChromiumHeadless', - ], - customLaunchers: { - FirefoxHeadless: { - base: 'Firefox', - flags: ['-headless'] - } - }, - frameworks: ['mocha'], - // this is the entry file for all our tests. - files: [ - './test/index.js', - ], - // we will pass the entry file to webpack for bundling. - preprocessors: { - '**/*': [ 'webpack', 'sourcemap' ], - }, - reporters: [ - 'mocha', - 'coverage' - ], - - coverageReporter: { - dir: './coverage', - reporters: [ - { type: 'html', subdir: 'report-html' }, - { type: 'lcov', subdir: 'report-lcov' }, - { type: 'cobertura', subdir: '.', file: 'cobertura.txt' }, - { type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' }, - { type: 'teamcity', subdir: '.', file: 'teamcity.txt' }, - { type: 'text', subdir: '.', file: 'text.txt' }, - { type: 'text-summary', subdir: '.', file: 'text-summary.txt' }, - ] - }, - - // use the webpack config - webpack: webpackConfig, - // avoid walls of useless text - webpackMiddleware: { - stats: 'errors-only' - }, - singleRun: true, - }); -}; diff --git a/conda/js/main.css b/conda/js/main.css deleted file mode 100644 index 80775b9e..00000000 --- a/conda/js/main.css +++ /dev/null @@ -1,91 +0,0 @@ -pre { - white-space: pre-wrap; -} - -.preInline { - display: inline; -} - -/* react-contextmenu styling - * taken from react-contextmenu's example CSS https://github.com/vkbansal/react-contextmenu/blob/65df2dec9737eed4e5e1b0b8fbc1018629082f89/examples/react-contextmenu.css - * adapted to more closely conform to this repo's stylelint's settings (see .stylelintrc) - */ -.react-contextmenu { - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 16px; - color: #373a3c; - text-align: left; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 0.25rem; - outline: none; - opacity: 0; - pointer-events: none; - transition: opacity 250ms ease; -} - -.react-contextmenu.react-contextmenu--visible { - opacity: 1; - pointer-events: auto; -} - -.react-contextmenu-item { - padding: 3px 20px; - font-weight: 400; - line-height: 1.5; - color: #373a3c; - text-align: inherit; - white-space: nowrap; - background: 0 0; - border: 0; - cursor: pointer; -} - -.react-contextmenu-item.react-contextmenu-item--active, -.react-contextmenu-item.react-contextmenu-item--selected { - color: #fff; - background-color: #20a0ff; - border-color: #20a0ff; - text-decoration: none; -} - -.react-contextmenu-item.react-contextmenu-item--disabled, -.react-contextmenu-item.react-contextmenu-item--disabled:hover { - color: #878a8c; - background-color: transparent; - border-color: rgba(0, 0, 0, 0.15); -} - -.react-contextmenu-item--divider { - margin-bottom: 3px; - padding: 2px 0; - border-bottom: 1px solid rgba(0, 0, 0, 0.15); - cursor: inherit; -} - -.react-contextmenu-item--divider:hover { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.15); -} - -.react-contextmenu-item.react-contextmenu-submenu { - padding: 0; -} - -.react-contextmenu-item.react-contextmenu-submenu > .react-contextmenu-item { -} - -.react-contextmenu-item.react-contextmenu-submenu > .react-contextmenu-item::after { - content: "▶"; - display: inline-block; - position: absolute; - right: 7px; -} - -.example-multiple-targets::after { - content: attr(data-count); - display: block; -} diff --git a/conda/js/main.jsx b/conda/js/main.jsx deleted file mode 100644 index 485ab7ce..00000000 --- a/conda/js/main.jsx +++ /dev/null @@ -1,18 +0,0 @@ -// bootstrap first -import './main.css'; -import 'bootstrap/dist/css/bootstrap.min.css'; - -// rest of app -import React from 'react'; -import ReactDOM from 'react-dom'; -import { Provider } from 'react-redux'; -import App from './src/components/App.jsx'; -import store from '@store'; - -ReactDOM.render( - <Provider store={ store }> - <App/> - </Provider> - , - document.getElementById('root') -); diff --git a/conda/js/package-lock.json b/conda/js/package-lock.json deleted file mode 100644 index e42684a9..00000000 --- a/conda/js/package-lock.json +++ /dev/null @@ -1,17510 +0,0 @@ -{ - "name": "beat.editor", - "version": "0.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.0.tgz", - "integrity": "sha512-9EWmD0cQAbcXSc+31RIoYgEHx3KQ2CCSMDBhnXrShWvo45TMw+3/55KVxlhkG53kw9tl87DqINgHDgFVhZJV/Q==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.0.0", - "@babel/helpers": "^7.1.0", - "@babel/parser": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0", - "convert-source-map": "^1.1.0", - "debug": "^3.1.0", - "json5": "^0.5.0", - "lodash": "^4.17.10", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0.tgz", - "integrity": "sha512-/BM2vupkpbZXq22l1ALO7MqXJZH2k8bKVv8Y+pABFnzWdztDB/ZLveP5At21vLz5c2YtSE6p7j2FZEsqafMz5Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", - "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", - "dev": true - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-builder-react-jsx": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.0.0.tgz", - "integrity": "sha512-ebJ2JM6NAKW0fQEqN8hOLxK84RbRz9OkUhGS/Xd5u56ejMfVbayJ4+LykERZCOUM6faa6Fp3SZNX3fcT16MKHw==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "esutils": "^2.0.0" - } - }, - "@babel/helper-call-delegate": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", - "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-define-map": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", - "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", - "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", - "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", - "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-replace-supers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", - "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-wrap-function": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz", - "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helpers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.0.tgz", - "integrity": "sha512-V1jXUTNdTpBn37wqqN73U+eBpzlLHmxA4aDaghJBggmzly/FpIJMHXse9lgdzQQT4gs5jZ5NmYxOL8G3ROc29g==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.0.tgz", - "integrity": "sha512-SmjnXCuPAlai75AFtzv+KCBcJ3sDDWbIn+WytKw1k+wAtEy6phqI2RqKh/zAnw53i1NR8su3Ep/UoqaKcimuLg==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz", - "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.0.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.1.0.tgz", - "integrity": "sha512-/PCJWN+CKt5v1xcGn4vnuu13QDoV+P7NcICP44BoonAJoPSGwVkgrXihFIQGiEjjPlUDBIw1cM7wYFLARS2/hw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", - "@babel/plugin-syntax-class-properties": "^7.0.0" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz", - "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.0.0" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz", - "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz", - "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz", - "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.2.0" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz", - "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0.tgz", - "integrity": "sha512-cR12g0Qzn4sgkjrbrzWy2GE7m9vMl/sFkqZ3gIpAQdrvPDnLM8180i+ANDFIXfjHo9aqp0ccJlQ0QNZcFUbf9w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-flow": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.0.0.tgz", - "integrity": "sha512-zGcuZWiWWDa5qTZ6iAnpG0fnX/GOu49pGR5PFvkQ9GmKNaSphXQnlNXh/LG20sqWtNrx/eB6krzfEzcwvUyeFA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz", - "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0.tgz", - "integrity": "sha512-PdmL2AoPsCLWxhIr3kG2+F9v4WH06Q3z+NoGVpQgnUNGcagXHq5sB3OXxkSahKq9TLdNMN/AJzFYSOo8UKDMHg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz", - "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz", - "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz", - "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz", - "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz", - "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz", - "integrity": "sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "@babel/plugin-transform-classes": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz", - "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.1.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", - "dev": true - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz", - "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0.tgz", - "integrity": "sha512-Fr2GtF8YJSXGTyFPakPFB4ODaEKGU04bPsAllAIabwoXdFrPxL0LVXQX5dQWoxOjjgozarJcC9eWGsj0fD6Zsg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz", - "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz", - "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz", - "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-flow-strip-types": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0.tgz", - "integrity": "sha512-WhXUNb4It5a19RsgKKbQPrjmy4yWOY1KynpEbNw7bnd1QTcrT/EIl3MJvnGgpgvrKyKbqX7nUNOJfkpLOnoDKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.0.0" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz", - "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz", - "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz", - "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz", - "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz", - "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz", - "integrity": "sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz", - "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", - "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz", - "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz", - "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.1.0", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-react-display-name": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.0.0.tgz", - "integrity": "sha512-BX8xKuQTO0HzINxT6j/GiCwoJB0AOMs0HmLbEnAvcte8U8rSkNa/eSCAY+l1OA4JnCVq2jw2p6U8QQryy2fTPg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.0.0.tgz", - "integrity": "sha512-0TMP21hXsSUjIQJmu/r7RiVxeFrXRcMUigbKu0BLegJK9PkYodHstaszcig7zxXfaBji2LYUdtqIkHs+hgYkJQ==", - "dev": true, - "requires": { - "@babel/helper-builder-react-jsx": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0" - } - }, - "@babel/plugin-transform-react-jsx-self": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.0.0.tgz", - "integrity": "sha512-pymy+AK12WO4safW1HmBpwagUQRl9cevNX+82AIAtU1pIdugqcH+nuYP03Ja6B+N4gliAaKWAegIBL/ymALPHA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0" - } - }, - "@babel/plugin-transform-react-jsx-source": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.0.0.tgz", - "integrity": "sha512-OSeEpFJEH5dw/TtxTg4nijl4nHBbhqbKL94Xo/Y17WKIf2qJWeIk/QeXACF19lG1vMezkxqruwnTjVizaW7u7w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", - "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.13.3" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz", - "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz", - "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz", - "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz", - "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz", - "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz", - "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" - } - }, - "@babel/preset-env": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.1.0.tgz", - "integrity": "sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.1.0", - "@babel/plugin-proposal-json-strings": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", - "@babel/plugin-syntax-async-generators": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.1.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.1.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-dotall-regex": "^7.0.0", - "@babel/plugin-transform-duplicate-keys": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.1.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.1.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-amd": "^7.1.0", - "@babel/plugin-transform-modules-commonjs": "^7.1.0", - "@babel/plugin-transform-modules-systemjs": "^7.0.0", - "@babel/plugin-transform-modules-umd": "^7.1.0", - "@babel/plugin-transform-new-target": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.1.0", - "@babel/plugin-transform-parameters": "^7.1.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typeof-symbol": "^7.0.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "browserslist": "^4.1.0", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" - }, - "dependencies": { - "browserslist": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.1.1.tgz", - "integrity": "sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000884", - "electron-to-chromium": "^1.3.62", - "node-releases": "^1.0.0-alpha.11" - } - }, - "caniuse-lite": { - "version": "1.0.30000885", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz", - "integrity": "sha512-cXKbYwpxBLd7qHyej16JazPoUacqoVuDhvR61U7Fr5vSxMUiodzcYa1rQYRYfZ5GexV03vGZHd722vNPLjPJGQ==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.70", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.70.tgz", - "integrity": "sha512-WYMjqCnPVS5JA+XvwEnpwucJpVi2+q9cdCFpbhxgWGsCtforFBEkuP9+nCyy/wnU/0SyLcLRIeZct9ayMGcXoQ==", - "dev": true - }, - "node-releases": { - "version": "1.0.0-alpha.11", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.11.tgz", - "integrity": "sha512-CaViu+2FqTNYOYNihXa5uPS/zry92I3vPU4nCB6JB3OeZ2UGtOpF5gRwuN4+m3hbEcL47bOXyun1jX2iC+3uEQ==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - } - } - }, - "@babel/preset-flow": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.0.0.tgz", - "integrity": "sha512-bJOHrYOPqJZCkPVbG1Lot2r5OSsB+iUOaxiHdlOeB1yPWS6evswVHwvkDLZ54WTaTRIk89ds0iHmGZSnxlPejQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0" - } - }, - "@babel/preset-react": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz", - "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0" - } - }, - "@babel/template": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.0.tgz", - "integrity": "sha512-yZ948B/pJrwWGY6VxG6XRFsVTee3IQ7bihq9zFpM00Vydu6z5Xwg0C3J644kxI9WOTzd+62xcIsQ+AT1MGhqhA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/traverse": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.0.tgz", - "integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.0.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "debug": "^3.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", - "dev": true - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0.tgz", - "integrity": "sha512-5tPDap4bGKTLPtci2SUl/B7Gv8RnuJFuQoWx26RJobS0fFrz4reUA3JnwIM+HVHEmWE0C1mzKhDtTp8NsWY02Q==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.10", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", - "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==", - "dev": true - }, - "@sinonjs/commons": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.0.2.tgz", - "integrity": "sha512-WR3dlgqJP4QNrLC4iXN/5/2WaLQQ0VijOOkmflqFGVJ6wLEpbSjo7c0ZeGIdtY8Crk7xBBp87sM6+Mkerz7alw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - }, - "dependencies": { - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } - }, - "@sinonjs/formatio": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", - "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", - "dev": true, - "requires": { - "@sinonjs/samsam": "2.1.0" - }, - "dependencies": { - "@sinonjs/samsam": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", - "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", - "dev": true, - "requires": { - "array-from": "^2.1.1" - } - } - } - }, - "@sinonjs/samsam": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.1.tgz", - "integrity": "sha512-7oX6PXMulvdN37h88dvlvRyu61GYZau40fL4wEZvPEHvrjpJc3lDv6xDM5n4Z0StufUVB5nDvVZUM+jZHdMOOQ==", - "dev": true, - "requires": { - "array-from": "^2.1.1" - } - }, - "@types/node": { - "version": "10.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.10.1.tgz", - "integrity": "sha512-nzsx28VwfaIykfzMAG9TB3jxF5Nn+1/WMKnmVZc8TsB+LMIVvwUscVn7PAq+LFaY5ng5u4jp5mRROSswo76PPA==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.6.tgz", - "integrity": "sha512-8nkZS48EVsMUU0v6F1LCIOw4RYWLm2plMtbhFTjNgeXmsTNLuU3xTRtnljt9BFQB+iPbLRobkNrCWftWnNC7wQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.7.6", - "@webassemblyjs/helper-wasm-bytecode": "1.7.6", - "@webassemblyjs/wast-parser": "1.7.6", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.6.tgz", - "integrity": "sha512-VBOZvaOyBSkPZdIt5VBMg3vPWxouuM13dPXGWI1cBh3oFLNcFJ8s9YA7S9l4mPI7+Q950QqOmqj06oa83hNWBA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.6.tgz", - "integrity": "sha512-SCzhcQWHXfrfMSKcj8zHg1/kL9kb3aa5TN4plc/EREOs5Xop0ci5bdVBApbk2yfVi8aL+Ly4Qpp3/TRAUInjrg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.6.tgz", - "integrity": "sha512-1/gW5NaGsEOZ02fjnFiU8/OEEXU1uVbv2um0pQ9YVL3IHSkyk6xOwokzyqqO1qDZQUAllb+V8irtClPWntbVqw==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.6.tgz", - "integrity": "sha512-+suMJOkSn9+vEvDvgyWyrJo5vJsWSDXZmJAjtoUq4zS4eqHyXImpktvHOZwXp1XQjO5H+YQwsBgqTQEc0J/5zg==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.7.6" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.6.tgz", - "integrity": "sha512-HCS6KN3wgxUihGBW7WFzEC/o8Eyvk0d56uazusnxXthDPnkWiMv+kGi9xXswL2cvfYfeK5yiM17z2K5BVlwypw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.6.tgz", - "integrity": "sha512-e8/6GbY7OjLM+6OsN7f2krC2qYVNaSr0B0oe4lWdmq5sL++8dYDD1TFbD1TdAdWMRTYNr/Qq7ovXWzia2EbSjw==", - "dev": true, - "requires": { - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.6.tgz", - "integrity": "sha512-PzYFCb7RjjSdAOljyvLWVqd6adAOabJW+8yRT+NWhXuf1nNZWH+igFZCUK9k7Cx7CsBbzIfXjJc7u56zZgFj9Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.6.tgz", - "integrity": "sha512-3GS628ppDPSuwcYlQ7cDCGr4W2n9c4hLzvnRKeuz+lGsJSmc/ADVoYpm1ts2vlB1tGHkjtQMni+yu8mHoMlKlA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/helper-buffer": "1.7.6", - "@webassemblyjs/helper-wasm-bytecode": "1.7.6", - "@webassemblyjs/wasm-gen": "1.7.6" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.6.tgz", - "integrity": "sha512-V4cIp0ruyw+hawUHwQLn6o2mFEw4t50tk530oKsYXQhEzKR+xNGDxs/SFFuyTO7X3NzEu4usA3w5jzhl2RYyzQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.6.tgz", - "integrity": "sha512-ojdlG8WpM394lBow4ncTGJoIVZ4aAtNOWHhfAM7m7zprmkVcKK+2kK5YJ9Bmj6/ketTtOn7wGSHCtMt+LzqgYQ==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.1" - } - }, - "@webassemblyjs/utf8": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.6.tgz", - "integrity": "sha512-oId+tLxQ+AeDC34ELRYNSqJRaScB0TClUU6KQfpB8rNT6oelYlz8axsPhf6yPTg7PBJ/Z5WcXmUYiHEWgbbHJw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.6.tgz", - "integrity": "sha512-pTNjLO3o41v/Vz9VFLl+I3YLImpCSpodFW77pNoH4agn5I6GgSxXHXtvWDTvYJFty0jSeXZWLEmbaSIRUDlekg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/helper-buffer": "1.7.6", - "@webassemblyjs/helper-wasm-bytecode": "1.7.6", - "@webassemblyjs/helper-wasm-section": "1.7.6", - "@webassemblyjs/wasm-gen": "1.7.6", - "@webassemblyjs/wasm-opt": "1.7.6", - "@webassemblyjs/wasm-parser": "1.7.6", - "@webassemblyjs/wast-printer": "1.7.6" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.6.tgz", - "integrity": "sha512-mQvFJVumtmRKEUXMohwn8nSrtjJJl6oXwF3FotC5t6e2hlKMh8sIaW03Sck2MDzw9xPogZD7tdP5kjPlbH9EcQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/helper-wasm-bytecode": "1.7.6", - "@webassemblyjs/ieee754": "1.7.6", - "@webassemblyjs/leb128": "1.7.6", - "@webassemblyjs/utf8": "1.7.6" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.6.tgz", - "integrity": "sha512-go44K90fSIsDwRgtHhX14VtbdDPdK2sZQtZqUcMRvTojdozj5tLI0VVJAzLCfz51NOkFXezPeVTAYFqrZ6rI8Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/helper-buffer": "1.7.6", - "@webassemblyjs/wasm-gen": "1.7.6", - "@webassemblyjs/wasm-parser": "1.7.6" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.6.tgz", - "integrity": "sha512-t1T6TfwNY85pDA/HWPA8kB9xA4sp9ajlRg5W7EKikqrynTyFo+/qDzIpvdkOkOGjlS6d4n4SX59SPuIayR22Yg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/helper-api-error": "1.7.6", - "@webassemblyjs/helper-wasm-bytecode": "1.7.6", - "@webassemblyjs/ieee754": "1.7.6", - "@webassemblyjs/leb128": "1.7.6", - "@webassemblyjs/utf8": "1.7.6" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.6.tgz", - "integrity": "sha512-1MaWTErN0ziOsNUlLdvwS+NS1QWuI/kgJaAGAMHX8+fMJFgOJDmN/xsG4h/A1Gtf/tz5VyXQciaqHZqp2q0vfg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/floating-point-hex-parser": "1.7.6", - "@webassemblyjs/helper-api-error": "1.7.6", - "@webassemblyjs/helper-code-frame": "1.7.6", - "@webassemblyjs/helper-fsm": "1.7.6", - "@xtuc/long": "4.2.1", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.6.tgz", - "integrity": "sha512-vHdHSK1tOetvDcl1IV1OdDeGNe/NDDQ+KzuZHMtqTVP1xO/tZ/IKNpj5BaGk1OYFdsDWQqb31PIwdEyPntOWRQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/wast-parser": "1.7.6", - "@xtuc/long": "4.2.1" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", - "dev": true - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", - "dev": true, - "requires": { - "acorn": "^5.0.0" - } - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", - "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", - "dev": true - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-colors": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.0.5.tgz", - "integrity": "sha512-VVjWpkfaphxUBFarydrQ3n26zX5nIK7hcbT3/ielrvwDDyBBjuh2vuSw1P9zkPq0cfqvdw7lkYHnu+OLSfIBsg==", - "dev": true - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "any-promise": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-0.1.0.tgz", - "integrity": "sha1-gwtoCqflbzNFHUsEnzvYBESY7ic=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-flatten": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", - "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", - "dev": true - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, - "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" - } - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "array.prototype.flat": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz", - "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.10.0", - "function-bind": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - } - } - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assertion-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "ast-types": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", - "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", - "dev": true - }, - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, - "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", - "dev": true - }, - "autoprefixer": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.1.5.tgz", - "integrity": "sha512-kk4Zb6RUc58ld7gdosERHMF3DzIYJc2fp5sX46qEsGXQQy5bXsu8qyLjoxuY1NuQ/cJuCYnx99BfjwnRggrYIw==", - "dev": true, - "requires": { - "browserslist": "^4.1.0", - "caniuse-lite": "^1.0.30000884", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.2", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "browserslist": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.1.1.tgz", - "integrity": "sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000884", - "electron-to-chromium": "^1.3.62", - "node-releases": "^1.0.0-alpha.11" - } - }, - "caniuse-lite": { - "version": "1.0.30000885", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz", - "integrity": "sha512-cXKbYwpxBLd7qHyej16JazPoUacqoVuDhvR61U7Fr5vSxMUiodzcYa1rQYRYfZ5GexV03vGZHd722vNPLjPJGQ==", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "electron-to-chromium": { - "version": "1.3.70", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.70.tgz", - "integrity": "sha512-WYMjqCnPVS5JA+XvwEnpwucJpVi2+q9cdCFpbhxgWGsCtforFBEkuP9+nCyy/wnU/0SyLcLRIeZct9ayMGcXoQ==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "node-releases": { - "version": "1.0.0-alpha.11", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.11.tgz", - "integrity": "sha512-CaViu+2FqTNYOYNihXa5uPS/zry92I3vPU4nCB6JB3OeZ2UGtOpF5gRwuN4+m3hbEcL47bOXyun1jX2iC+3uEQ==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - }, - "postcss": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.2.tgz", - "integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "babel-eslint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-9.0.0.tgz", - "integrity": "sha512-itv1MwE3TMbY0QtNfeL7wzak1mV47Uy+n6HtSOO4Xd7rvmO+tsGQSgyOEEgo6Y2vHZKZphaoelNeSVj4vkLA1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "^1.0.0" - } - }, - "babel-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.2.tgz", - "integrity": "sha512-Law0PGtRV1JL8Y9Wpzc0d6EE0GD7LzXWCfaeWwboUMcBWNG6gvaWTK1/+BK7a4X5EmeJiGEuDDFxUsOa8RSWCw==", - "dev": true, - "requires": { - "find-cache-dir": "^1.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "util.promisify": "^1.0.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", - "dev": true - } - } - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "bail": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", - "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "base62": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base62/-/base62-1.2.0.tgz", - "integrity": "sha1-MeflYNyEbJ9EwaUx32UU2jVHQVc=", - "dev": true - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "binary-extensions": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", - "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", - "dev": true - }, - "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", - "dev": true - }, - "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "bootstrap": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz", - "integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==" - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.4.0.tgz", - "integrity": "sha512-aM2Gt4x9bVlCUteADBS6JP0F+2tMWKM1jQzUulVROtdFWFIcIVvY76AJbr7GDqy0eDhn+PcnpzzivGxY4qiaKQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000718", - "electron-to-chromium": "^1.3.18" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - }, - "dependencies": { - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caniuse-db": { - "version": "1.0.30000870", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000870.tgz", - "integrity": "sha1-85fNZJIsJPhdDOeAPJvVxaFXGxY=", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000741", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000741.tgz", - "integrity": "sha1-vFJrwgRua8OHN8/XfTAm7wS49GQ=", - "dev": true - }, - "ccount": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", - "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chai": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", - "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", - "dev": true, - "requires": { - "assertion-error": "^1.0.1", - "check-error": "^1.0.1", - "deep-eql": "^3.0.0", - "get-func-name": "^2.0.0", - "pathval": "^1.0.0", - "type-detect": "^4.0.0" - } - }, - "chai-enzyme": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/chai-enzyme/-/chai-enzyme-1.0.0-beta.1.tgz", - "integrity": "sha512-vWT101M7qjq6kM/29G4vHrgLM4Mj1gCnKuvOSF03s8pFVsqol4B6USoGM/aYRKqaaIHs8/AxmHjWGFplQWhIQw==", - "dev": true, - "requires": { - "html": "^1.0.0" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "character-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==", - "dev": true - }, - "character-entities-html4": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", - "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "dev": true, - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - }, - "dependencies": { - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true - } - } - }, - "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "ci-info": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.1.tgz", - "integrity": "sha512-vHDDF/bP9RYpTWtUhpJRhCFdvvp3iDWvEbuDbWgvjUrNGV1MXJrE0MPcwGtEled04m61iwdBLUIHZtDgzWS4ZQ==", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" - }, - "clean-css": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", - "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", - "dev": true, - "requires": { - "source-map": "0.5.x" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, - "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", - "dev": true - }, - "clone-regexp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz", - "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==", - "dev": true, - "requires": { - "is-regexp": "^1.0.0", - "is-supported-regexp-flag": "^1.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collapse-white-space": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", - "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - } - }, - "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", - "dev": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "colors": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", - "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", - "dev": true - }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "commoner": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", - "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", - "dev": true, - "requires": { - "commander": "^2.5.0", - "detective": "^4.3.1", - "glob": "^5.0.15", - "graceful-fs": "^4.1.2", - "iconv-lite": "^0.4.5", - "mkdirp": "^0.5.0", - "private": "^0.1.6", - "q": "^1.1.2", - "recast": "^0.11.17" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "compressible": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", - "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", - "dev": true, - "requires": { - "mime-db": ">= 1.36.0 < 2" - } - }, - "compression": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", - "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.14", - "debug": "2.6.9", - "on-headers": "~1.0.1", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - } - }, - "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", - "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", - "dev": true, - "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0", - "require-from-string": "^2.0.1" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - } - } - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "create-react-context": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz", - "integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==", - "dev": true, - "requires": { - "fbjs": "^0.8.0", - "gud": "^1.0.0" - } - }, - "cross-env": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", - "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.5", - "is-windows": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - } - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-color-function": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz", - "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=", - "dev": true, - "requires": { - "balanced-match": "0.1.0", - "color": "^0.11.0", - "debug": "^3.1.0", - "rgb": "~0.1.0" - }, - "dependencies": { - "balanced-match": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz", - "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "css-loader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.0.tgz", - "integrity": "sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash.camelcase": "^4.3.0", - "postcss": "^6.0.23", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "dev": true, - "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" - }, - "dependencies": { - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - } - } - }, - "css-unit-converter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", - "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", - "dev": true - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", - "dev": true - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, - "d3": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.7.0.tgz", - "integrity": "sha512-8KEIfx+dFm8PlbJN9PI0suazrZ41QcaAufsKE9PRcqYPWLngHIyWJZX96n6IQKePGgeSu0l7rtlueSSNq8Zc3g==", - "requires": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "d3-brush": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.6.tgz", - "integrity": "sha512-lGSiF5SoSqO5/mYGD5FAeGKKS62JdA1EV7HPrU2b5rTX4qEJJtpjaGLJngjnkewQy7UnGstnFd3168wpf5z76w==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, - "d3-color": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.2.3.tgz", - "integrity": "sha512-x37qq3ChOTLd26hnps36lexMRhNXEtVxZ4B25rL0DVdDsGQIJGB18S7y9XDwlDD6MD/ZBzITCf4JjGMM10TZkw==" - }, - "d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "requires": { - "d3-array": "^1.1.1" - } - }, - "d3-dispatch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.5.tgz", - "integrity": "sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g==" - }, - "d3-drag": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.3.tgz", - "integrity": "sha512-8S3HWCAg+ilzjJsNtWW1Mutl74Nmzhb9yU6igspilaJzeZVFktmY6oO9xOh5TDk+BM2KrNFjttZNoJJmDnkjkg==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.10.tgz", - "integrity": "sha512-vqklfpxmtO2ZER3fq/B33R/BIz3A1PV0FaZRuFM8w6jLo7sUX1BZDh73fPlr0s327rzq4H6EN1q9U+eCBCSN8g==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.5.tgz", - "integrity": "sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ==" - }, - "d3-fetch": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz", - "integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==", - "requires": { - "d3-dsv": "1" - } - }, - "d3-force": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.2.tgz", - "integrity": "sha512-p1vcHAUF1qH7yR+e8ip7Bs61AHjLeKkIn8Z2gzwU2lwEf2wkSpWdjXG0axudTHsVFnYGlMkFaEsVy2l8tAg1Gw==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.3.2.tgz", - "integrity": "sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ==" - }, - "d3-geo": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.11.1.tgz", - "integrity": "sha512-GsG7x9G9sykseLviOVSJ3h5yjw0ItLopOtuDQKUt1TRklEegCw5WAmnIpYYiCkSH/QgUMleAeE2xZK38Qb+1+Q==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz", - "integrity": "sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w==" - }, - "d3-interpolate": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.3.2.tgz", - "integrity": "sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.7.tgz", - "integrity": "sha512-q0cW1RpvA5c5ma2rch62mX8AYaiLX0+bdaSM2wxSU9tXjU4DNvkx9qiUvjkuWCj3p22UO/hlPivujqMiR9PDzA==" - }, - "d3-polygon": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.5.tgz", - "integrity": "sha512-RHhh1ZUJZfhgoqzWWuRhzQJvO7LavchhitSTHGu9oj6uuLFzYZVeBzaWTQ2qSO6bz2w55RMoOCf0MsLCDB6e0w==" - }, - "d3-quadtree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.5.tgz", - "integrity": "sha512-U2tjwDFbZ75JRAg8A+cqMvqPg1G3BE7UTJn3h8DHjY/pnsAfWdbJKgyfcy7zKjqGtLAmI0q8aDSeG1TVIKRaHQ==" - }, - "d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "d3-scale": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.1.2.tgz", - "integrity": "sha512-bESpd64ylaKzCDzvULcmHKZTlzA/6DGSVwx7QSDj/EnX9cpSevsdiwdHFYI9ouo9tNBbV3v5xztHS2uFeOzh8Q==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-scale-chromatic": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz", - "integrity": "sha512-BWTipif1CimXcYfT02LKjAyItX5gKiwxuPRgr4xM58JwlLocWbjPLI7aMEjkcoOQXMkYsmNsvv3d2yl/OKuHHw==", - "requires": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "d3-selection": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.2.tgz", - "integrity": "sha512-OoXdv1nZ7h2aKMVg3kaUFbLLK5jXUFAMLD/Tu5JA96mjf8f2a9ZUESGY+C36t8R1WFeWk/e55hy54Ml2I62CRQ==" - }, - "d3-shape": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.2.tgz", - "integrity": "sha512-hUGEozlKecFZ2bOSNt7ENex+4Tk9uc/m0TtTEHBvitCBxUNjhzm5hS2GrrVRD/ae4IylSmxGeqX5tWC2rASMlQ==", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.10.tgz", - "integrity": "sha512-hF+NTLCaJHF/JqHN5hE8HVGAXPStEq6/omumPE/SxyHVrR7/qQxusFDo0t0c/44+sCGHthC7yNGFZIEgju0P8g==" - }, - "d3-time-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.3.tgz", - "integrity": "sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.9.tgz", - "integrity": "sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg==" - }, - "d3-transition": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.3.tgz", - "integrity": "sha512-tEvo3qOXL6pZ1EzcXxFcPNxC/Ygivu5NoBY6mbzidATAeML86da+JfVIUzon3dNM6UX6zjDx+xbYDmMVtTSjuA==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, - "d3-zoom": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.3.tgz", - "integrity": "sha512-xEBSwFx5Z9T3/VrwDkMt+mr0HCzv7XjpGURJ8lWmIC8wxe32L39eWHIasEe/e7Ox8MPU4p1hvH8PKN2olLzIBg==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", - "dev": true - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - } - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "deep-equal-in-any-order": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/deep-equal-in-any-order/-/deep-equal-in-any-order-1.0.10.tgz", - "integrity": "sha512-hzh3IwlIKwT885r5b/b4bXCXxzR7S9N+Dreuoommdykcnvlg0A+pS81wMU4ZsFz98CH4KBI8eWbAfDHWl7akTg==", - "dev": true, - "requires": { - "lodash": "^4.17.10", - "sort-any": "^1.1.12" - }, - "dependencies": { - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "default-gateway": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", - "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==", - "dev": true, - "requires": { - "execa": "^0.10.0", - "ip-regex": "^2.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "^2.0.5", - "object-keys": "^1.0.8" - } - }, - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "dependency-graph": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", - "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true - }, - "detective": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", - "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", - "dev": true, - "requires": { - "acorn": "^4.0.3", - "defined": "^1.0.0" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", - "dev": true - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dev": true, - "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "requires": { - "buffer-indexof": "^1.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", - "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", - "dev": true, - "requires": { - "utila": "~0.3" - }, - "dependencies": { - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", - "dev": true - } - } - }, - "dom-helpers": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz", - "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg==" - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", - "dev": true - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.24", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz", - "integrity": "sha1-m3uIuwXOufoBahd4M8wt3jiPIbY=", - "dev": true - }, - "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", - "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "engine.io-client": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary2": "~1.0.2" - } - }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, - "envify": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.1.tgz", - "integrity": "sha1-1xIjKejfFoi6dxsSUBkXyc5cvOg=", - "dev": true, - "requires": { - "jstransform": "^11.0.3", - "through": "~2.3.4" - } - }, - "enzyme": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.6.0.tgz", - "integrity": "sha512-onsINzVLGqKIapTVfWkkw6bYvm1o4CyJ9s8POExtQhAkVa4qFDW6DGCQGRy/5bfZYk+gmUbMNyayXiWDzTkHFQ==", - "dev": true, - "requires": { - "array.prototype.flat": "^1.2.1", - "cheerio": "^1.0.0-rc.2", - "function.prototype.name": "^1.1.0", - "has": "^1.0.3", - "is-boolean-object": "^1.0.0", - "is-callable": "^1.1.4", - "is-number-object": "^1.0.3", - "is-string": "^1.0.4", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.6.0", - "object-is": "^1.0.1", - "object.assign": "^4.1.0", - "object.entries": "^1.0.4", - "object.values": "^1.0.4", - "raf": "^3.4.0", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.1.2" - }, - "dependencies": { - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - } - } - }, - "enzyme-adapter-react-16": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.5.0.tgz", - "integrity": "sha512-R2LcVvMB2UwPH763d5jDtVedAIcEj+uZjOnq0nd1sOUs6z8TDbyHDvt8VwfrS4wMt7CawoyPmH0XzC8MtEqqDw==", - "dev": true, - "requires": { - "enzyme-adapter-utils": "^1.8.0", - "function.prototype.name": "^1.1.0", - "object.assign": "^4.1.0", - "object.values": "^1.0.4", - "prop-types": "^15.6.2", - "react-is": "^16.4.2", - "react-test-renderer": "^16.0.0-0" - } - }, - "enzyme-adapter-utils": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.8.0.tgz", - "integrity": "sha512-K9U2RGr1pvWPGEAIRQRVH4UdlqzpfLsKonuHyAK6lxu46yfGsMDVlO3+YvQwQpVjVw8eviEVIOmlFAnMbIhv/w==", - "dev": true, - "requires": { - "function.prototype.name": "^1.1.0", - "object.assign": "^4.1.0", - "prop-types": "^15.6.2" - } - }, - "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", - "dev": true, - "requires": { - "prr": "~0.0.0" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.9.0.tgz", - "integrity": "sha512-kk3IJoKo7A3pWJc0OV8yZ/VEX2oSUytfekrJiqoxBlKJMFAJVJVpGdHClCCTdv+Fn2zHfpDHHIelMFhZVfef3Q==", - "dev": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, - "requires": { - "is-callable": "^1.1.1", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.1" - } - }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.6.0.tgz", - "integrity": "sha512-/eVYs9VVVboX286mBK7bbKnO1yamUy2UCRjiY6MryhQL2PaaXCExsCQ2aO83OeYRhU2eCU/FMFP+tVMoOrzNrA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.5.3", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "imurmurhash": "^0.1.4", - "inquirer": "^6.1.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.12.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.5", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^4.0.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" - } - }, - "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", - "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - } - } - }, - "eslint-plugin-compat": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-2.5.1.tgz", - "integrity": "sha1-/22OgPjF0AHqGSURVkcVuy6EtYc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "browserslist": "^4.0.0", - "caniuse-db": "^1.0.30000865", - "mdn-browser-compat-data": "^0.0.40", - "requireindex": "^1.2.0" - }, - "dependencies": { - "browserslist": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.0.1.tgz", - "integrity": "sha512-QqiiIWchEIkney3wY53/huI7ZErouNAdvOkjorUALAwRcu3tEwOV3Sh6He0DnP38mz1JjBpCBb50jQBmaYuHPw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000865", - "electron-to-chromium": "^1.3.52", - "node-releases": "^1.0.0-alpha.10" - } - }, - "caniuse-lite": { - "version": "1.0.30000865", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", - "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.52", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", - "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", - "dev": true - } - } - }, - "eslint-plugin-flowtype": { - "version": "2.50.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.1.tgz", - "integrity": "sha512-9kRxF9hfM/O6WGZcZPszOVPd2W0TLHBtceulLTsGfwMPtiCCLnCW0ssRiOOiXyqrCA20pm1iXdXm7gQeN306zQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", - "dev": true, - "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-plugin-react": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", - "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1", - "prop-types": "^15.6.2" - }, - "dependencies": { - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - } - } - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", - "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", - "dev": true, - "requires": { - "acorn": "^5.6.0", - "acorn-jsx": "^4.1.1" - }, - "dependencies": { - "acorn-jsx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", - "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", - "dev": true, - "requires": { - "acorn": "^5.0.3" - } - } - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, - "requires": { - "estraverse": "^4.1.0", - "object-assign": "^4.0.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "eventsource": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", - "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", - "dev": true, - "requires": { - "original": ">=0.0.5" - } - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "execall": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", - "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", - "dev": true, - "requires": { - "clone-regexp": "^1.0.0" - } - }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - }, - "dependencies": { - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.3", - "qs": "6.5.1", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "~1.6.15" - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - } - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" - } - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - } - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "fast-copy": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-1.2.2.tgz", - "integrity": "sha512-qgk7WyVVFNvUzEV/RRQfI7Y6SEjHI+SfmHpkSzzoMUpd4+uXQaeGxhz52/FjnaaNGWxuWXr5l4/kRPD8GPecGA==" - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", - "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.0.1", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.1", - "micromatch": "^3.1.10" - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "fastparse": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", - "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fbjs": { - "version": "0.8.17", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", - "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", - "dev": true, - "requires": { - "core-js": "^1.0.0", - "isomorphic-fetch": "^2.1.1", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - }, - "dependencies": { - "ua-parser-js": { - "version": "0.7.18", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", - "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==", - "dev": true - } - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" - } - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, - "flow-bin": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.81.0.tgz", - "integrity": "sha512-5e8oL3/5rm3G0Eet3yDCne2R/TLo5Fkn+Z5MtHd4wtz+1miLC35Sgo8XvnbTmiZ9epdTZ1q6GLmJWYh7tUlfGg==", - "dev": true - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "follow-redirects": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", - "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", - "dev": true, - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "^1.0.0" - } - }, - "fs-extra": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.0.tgz", - "integrity": "sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", - "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "is-callable": "^1.1.3" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "fuse.js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.2.1.tgz", - "integrity": "sha1-YyDLlM5W7JdVyJred1vNuwNY1CU=" - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "requires": { - "min-document": "^2.19.0", - "process": "~0.5.1" - } - }, - "global-modules-path": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz", - "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==", - "dev": true - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", - "dev": true - }, - "gonzales-pe": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", - "integrity": "sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==", - "dev": true, - "requires": { - "minimist": "1.1.x" - }, - "dependencies": { - "minimist": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", - "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=", - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "gud": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", - "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==", - "dev": true - }, - "handle-thing": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", - "dev": true - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } - } - } - }, - "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, - "requires": { - "function-bind": "^1.0.2" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "history": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", - "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", - "requires": { - "invariant": "^2.2.1", - "loose-envify": "^1.2.0", - "resolve-pathname": "^2.2.0", - "value-equal": "^0.4.0", - "warning": "^3.0.0" - }, - "dependencies": { - "warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "requires": { - "loose-envify": "^1.0.0" - } - } - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hoist-non-react-statics": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.4.tgz", - "integrity": "sha512-yklXtcYj0Pt5Dz9No8xUh7d+/7fy5XRIm+r7U/BXgwJ/VsD75EfXA8t4p9tIL0jykzo5A/sGzt1xV6oqd/gP0w==" - }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "html": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz", - "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=", - "dev": true, - "requires": { - "concat-stream": "^1.4.7" - } - }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", - "dev": true - }, - "html-minifier": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.13.tgz", - "integrity": "sha512-B7P99uf0LPQ5lslyhrAZAXE7Lk1tpiv52KVapKbeFhgqNMUI7JBd/fYLX55imu3Rz7sCTzZM6r/IBe4oT7qCjg==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.1.x", - "commander": "2.15.x", - "he": "1.1.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.3.x" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - } - } - }, - "html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", - "dev": true - }, - "html-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", - "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", - "dev": true, - "requires": { - "html-minifier": "^3.2.3", - "loader-utils": "^0.2.16", - "lodash": "^4.17.3", - "pretty-error": "^2.0.2", - "tapable": "^1.0.0", - "toposort": "^1.0.0", - "util.promisify": "1.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - } - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "^1.3.0", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-parser-js": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", - "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", - "dev": true - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", - "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", - "dev": true, - "requires": { - "http-proxy": "^1.16.2", - "is-glob": "^4.0.0", - "lodash": "^4.17.5", - "micromatch": "^3.1.9" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "husky": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz", - "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==", - "dev": true, - "requires": { - "is-ci": "^1.0.10", - "normalize-path": "^1.0.0", - "strip-indent": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true - } - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true - }, - "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, - "requires": { - "import-from": "^2.1.0" - } - }, - "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "import-lazy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz", - "integrity": "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==", - "dev": true - }, - "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", - "dev": true, - "requires": { - "pkg-dir": "^2.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "inquirer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", - "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.0", - "figures": "^2.0.0", - "lodash": "^4.17.10", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.1.0", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "internal-ip": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz", - "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==", - "dev": true, - "requires": { - "default-gateway": "^2.6.0", - "ipaddr.js": "^1.5.2" - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "is-alphabetical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==", - "dev": true - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", - "dev": true - }, - "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz", - "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=", - "dev": true - }, - "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, - "is-ci": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", - "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", - "dev": true, - "requires": { - "ci-info": "^1.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-decimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", - "dev": true - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-number-object": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz", - "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", - "dev": true - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-string": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz", - "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=", - "dev": true - }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, - "is-supported-regexp-flag": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz", - "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-whitespace-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", - "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-word-character": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", - "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isnumeric": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/isnumeric/-/isnumeric-0.2.0.tgz", - "integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "dev": true, - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - } - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "js-base64": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", - "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", - "dev": true - }, - "js-levenshtein": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.3.tgz", - "integrity": "sha512-/812MXr9RBtMObviZ8gQBhHO8MOrGj8HlEE+4ccMTElNA/6I3u39u+bhny55Lk921yn44nSZFy9naNLElL5wgQ==", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - } - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jstransform": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-11.0.3.tgz", - "integrity": "sha1-CaeJk+CuTU70SH9hVakfYZDLQiM=", - "dev": true, - "requires": { - "base62": "^1.1.0", - "commoner": "^0.10.1", - "esprima-fb": "^15001.1.0-dev-harmony-fb", - "object-assign": "^2.0.0", - "source-map": "^0.4.2" - }, - "dependencies": { - "esprima-fb": { - "version": "15001.1.0-dev-harmony-fb", - "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz", - "integrity": "sha1-MKlHMDxrjV6VW+4rmbHSMyBqaQE=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "jsx-ast-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", - "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", - "dev": true, - "requires": { - "array-includes": "^3.0.3" - } - }, - "jszip": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", - "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", - "dev": true, - "requires": { - "core-js": "~2.3.0", - "es6-promise": "~3.0.2", - "lie": "~3.1.0", - "pako": "~1.0.2", - "readable-stream": "~2.0.6" - }, - "dependencies": { - "core-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", - "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", - "dev": true - }, - "es6-promise": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", - "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "just-extend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", - "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", - "dev": true - }, - "karma": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz", - "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", - "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", - "log4js": "^3.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", - "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.2.1" - }, - "dependencies": { - "colors": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", - "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", - "dev": true - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "karma-chrome-launcher": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", - "dev": true, - "requires": { - "fs-access": "^1.0.0", - "which": "^1.2.1" - } - }, - "karma-coverage": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", - "integrity": "sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==", - "dev": true, - "requires": { - "dateformat": "^1.0.6", - "istanbul": "^0.4.0", - "lodash": "^4.17.0", - "minimatch": "^3.0.0", - "source-map": "^0.5.1" - } - }, - "karma-firefox-launcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", - "dev": true - }, - "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "karma-mocha-reporter": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", - "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz", - "integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==", - "dev": true, - "requires": { - "ansi-styles": "^3.1.0", - "escape-string-regexp": "^1.0.5", - "supports-color": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "karma-sourcemap-loader": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", - "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "karma-webpack": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", - "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", - "dev": true, - "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^2.0.6" - } - }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "known-css-properties": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.6.1.tgz", - "integrity": "sha512-nQRpMcHm1cQ6gmztdvLcIvxocznSMqH/y6XtERrWrHaymOYdDGroRqetJvJycxGEr1aakXiigDgn7JnzuXlk6A==", - "dev": true - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "dev": true, - "requires": { - "immediate": "~3.0.5" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } - }, - "lodash.tonumber": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz", - "integrity": "sha1-C5azGzVnJ5Prf1pj7nkfG56QJdk=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "log-symbols": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.1.0.tgz", - "integrity": "sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.1.0", - "escape-string-regexp": "^1.0.5", - "supports-color": "^4.0.0" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "log4js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.5.tgz", - "integrity": "sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==", - "dev": true, - "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", - "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", - "dev": true - }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "loglevel": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", - "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", - "dev": true - }, - "loglevelnext": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", - "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "dev": true, - "requires": { - "es6-symbol": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "longest-streak": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", - "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==", - "dev": true - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "requires": { - "js-tokens": "^3.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz", - "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-escapes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", - "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", - "dev": true - }, - "markdown-table": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", - "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==", - "dev": true - }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, - "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", - "dev": true - }, - "mathml-tag-names": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz", - "integrity": "sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg==", - "dev": true - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "mdast-util-compact": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.2.tgz", - "integrity": "sha512-d2WS98JSDVbpSsBfVvD9TaDMlqPRz7ohM/11G0rp5jOBb5q96RJ6YLszQ/09AAixyzh23FeIpCGqfaamEADtWg==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "mdn-browser-compat-data": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.40.tgz", - "integrity": "sha512-gxe4m/g1LVHhT8WZCk0SpGryxFqlsyHIWXta6APP8wQL2ds8iVPzqIyxCj7mO1xxB1WyeBSIh3V06Q1Dqzr/Jg==", - "dev": true, - "requires": { - "extend": "3.0.1" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge2": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", - "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - } - } - } - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", - "dev": true - }, - "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", - "dev": true - }, - "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", - "dev": true, - "requires": { - "mime-db": "~1.36.0" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", - "dev": true - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "requires": { - "dom-walk": "^0.1.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", - "integrity": "sha512-dgaCvoh6i1nosAUBKb0l0pfJ78K8+S9fluyIR2YvAeUD/QuMahnFnF3xYty5eYXMjhGSsB0DsW6A0uAZyetoAg==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "moo": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz", - "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==", - "dev": true - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - } - }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz", - "integrity": "sha512-8IUY/rUrKz2mIynUGh8k+tul1awMKEjeHHC5G3FHvvyAW6oq4mQfNp2c0BMea+sYZJvYcrrM6GmZVIle/GRXGw==", - "dev": true, - "requires": { - "moo": "^0.4.3", - "nomnom": "~1.6.2", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6", - "semver": "^5.4.1" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - }, - "neo-async": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", - "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", - "dev": true - }, - "nise": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.5.tgz", - "integrity": "sha512-OHRVvdxKgwZELf2DTgsJEIA4MOq8XWvpSUzoOXyxJ2mY0mMENWC66+70AShLR2z05B1dzrzWlUQJmJERlOUpZw==", - "dev": true, - "requires": { - "@sinonjs/formatio": "3.0.0", - "just-extend": "^3.0.0", - "lolex": "^2.3.2", - "path-to-regexp": "^1.7.0", - "text-encoding": "^0.6.4" - } - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "node-forge": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", - "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", - "dev": true - }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "node-releases": { - "version": "1.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.10.tgz", - "integrity": "sha512-BSQrRgOfN6L/MoKIa7pRUc7dHvflCXMcqyTBvphixcSsgJTuUd24vAFONuNfVsuwTyz28S1HEc9XN6ZKylk4Hg==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - }, - "nomnom": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", - "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", - "dev": true, - "requires": { - "colors": "0.5.x", - "underscore": "~1.4.4" - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "~1.0.0" - } - }, - "null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - } - } - }, - "object-inspect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", - "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", - "dev": true - }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", - "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onecolor": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.0.5.tgz", - "integrity": "sha1-Nu/zIgE3nv3xGA+0ReUajiQl+fY=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "opn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "dev": true, - "requires": { - "url-parse": "^1.4.3" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true - }, - "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", - "dev": true - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true - }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" - } - }, - "parse-entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz", - "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", - "dev": true, - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "requires": { - "isarray": "0.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pixrem": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-4.0.1.tgz", - "integrity": "sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY=", - "dev": true, - "requires": { - "browserslist": "^2.0.0", - "postcss": "^6.0.0", - "reduce-css-calc": "^1.2.7" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, - "pleeease-filters": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-4.0.0.tgz", - "integrity": "sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc=", - "dev": true, - "requires": { - "onecolor": "^3.0.4", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "popper.js": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz", - "integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY=" - }, - "portfinder": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", - "integrity": "sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==", - "dev": true, - "requires": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.2.tgz", - "integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-apply": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.8.0.tgz", - "integrity": "sha1-FOVEu7XLbxweBIhXll15rgZrE0M=", - "dev": true, - "requires": { - "babel-runtime": "^6.23.0", - "balanced-match": "^0.4.2", - "postcss": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-attribute-case-insensitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz", - "integrity": "sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q=", - "dev": true, - "requires": { - "postcss": "^6.0.0", - "postcss-selector-parser": "^2.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-cli": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-6.0.0.tgz", - "integrity": "sha512-7DuxMn1Wj6dJKbjKpZXOdAc5nl5NfPXiJbg0m/+tdObPvgk1xv4+lZgNKD3jL/kCrDRPf1jgFlmq1cHh8lBR2w==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "chokidar": "^2.0.0", - "dependency-graph": "^0.7.0", - "fs-extra": "^7.0.0", - "get-stdin": "^6.0.0", - "globby": "^8.0.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "postcss-reporter": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "read-cache": "^1.0.0", - "yargs": "^12.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, - "globby": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", - "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" - } - }, - "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", - "dev": true, - "requires": { - "execa": "^0.10.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^2.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" - } - } - } - }, - "postcss-color-function": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-function/-/postcss-color-function-4.0.1.tgz", - "integrity": "sha1-QCs/LOvD9pR+YY+2vjZU++zvZEQ=", - "dev": true, - "requires": { - "css-color-function": "~1.3.3", - "postcss": "^6.0.1", - "postcss-message-helpers": "^2.0.0", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-gray": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz", - "integrity": "sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w==", - "dev": true, - "requires": { - "color": "^2.0.1", - "postcss": "^6.0.14", - "postcss-message-helpers": "^2.0.0", - "reduce-function-call": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", - "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", - "dev": true, - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-string": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", - "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-hex-alpha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz", - "integrity": "sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U=", - "dev": true, - "requires": { - "color": "^1.0.3", - "postcss": "^6.0.1", - "postcss-message-helpers": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", - "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", - "dev": true, - "requires": { - "color-convert": "^1.8.2", - "color-string": "^1.4.0" - } - }, - "color-string": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", - "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-hsl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz", - "integrity": "sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-value-parser": "^3.3.0", - "units-css": "^0.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-hwb": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz", - "integrity": "sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4=", - "dev": true, - "requires": { - "color": "^1.0.3", - "postcss": "^6.0.1", - "postcss-message-helpers": "^2.0.0", - "reduce-function-call": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", - "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", - "dev": true, - "requires": { - "color-convert": "^1.8.2", - "color-string": "^1.4.0" - } - }, - "color-string": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", - "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-rebeccapurple": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.0.0.tgz", - "integrity": "sha1-7rrwPTY7QwC5Z5K9MIHBntZlE9M=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-rgb": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz", - "integrity": "sha1-FFOcinExSUtILg3RzCZf9lFLUmM=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-rgba-fallback": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz", - "integrity": "sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ=", - "dev": true, - "requires": { - "postcss": "^6.0.6", - "postcss-value-parser": "^3.3.0", - "rgb-hex": "^2.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-cssnext": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz", - "integrity": "sha512-awPDhI4OKetcHCr560iVCoDuP6e/vn0r6EAqdWPpAavJMvkBSZ6kDpSN4b3mB3Ti57hQMunHHM8Wvx9PeuYXtA==", - "dev": true, - "requires": { - "autoprefixer": "^7.1.1", - "caniuse-api": "^2.0.0", - "chalk": "^2.0.1", - "pixrem": "^4.0.0", - "pleeease-filters": "^4.0.0", - "postcss": "^6.0.5", - "postcss-apply": "^0.8.0", - "postcss-attribute-case-insensitive": "^2.0.0", - "postcss-calc": "^6.0.0", - "postcss-color-function": "^4.0.0", - "postcss-color-gray": "^4.0.0", - "postcss-color-hex-alpha": "^3.0.0", - "postcss-color-hsl": "^2.0.0", - "postcss-color-hwb": "^3.0.0", - "postcss-color-rebeccapurple": "^3.0.0", - "postcss-color-rgb": "^2.0.0", - "postcss-color-rgba-fallback": "^3.0.0", - "postcss-custom-media": "^6.0.0", - "postcss-custom-properties": "^6.1.0", - "postcss-custom-selectors": "^4.0.1", - "postcss-font-family-system-ui": "^3.0.0", - "postcss-font-variant": "^3.0.0", - "postcss-image-set-polyfill": "^0.3.5", - "postcss-initial": "^2.0.0", - "postcss-media-minmax": "^3.0.0", - "postcss-nesting": "^4.0.1", - "postcss-pseudo-class-any-link": "^4.0.0", - "postcss-pseudoelements": "^5.0.0", - "postcss-replace-overflow-wrap": "^2.0.0", - "postcss-selector-matches": "^3.0.1", - "postcss-selector-not": "^3.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "autoprefixer": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.5.tgz", - "integrity": "sha512-XqHfo8Ht0VU+T5P+eWEVoXza456KJ4l62BPewu3vpNf3LP9s2+zYXkXBznzYby4XeECXgG3N4i+hGvOhXErZmA==", - "dev": true, - "requires": { - "browserslist": "^2.11.1", - "caniuse-lite": "^1.0.30000791", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^6.0.16", - "postcss-value-parser": "^3.2.3" - } - }, - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000792", - "electron-to-chromium": "^1.3.30" - } - }, - "caniuse-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-2.0.0.tgz", - "integrity": "sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ=", - "dev": true, - "requires": { - "browserslist": "^2.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30000792", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz", - "integrity": "sha1-0M6pgfgRjzlhRxr7tDyaHlu/AzI=", - "dev": true - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.1.0", - "escape-string-regexp": "^1.0.5", - "supports-color": "^4.0.0" - } - }, - "electron-to-chromium": { - "version": "1.3.31", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz", - "integrity": "sha512-XE4CLbswkZgZFn34cKFy1xaX+F5LHxeDLjY1+rsK9asDzknhbrd9g/n/01/acbU25KTsUSiLKwvlLyA+6XLUOA==", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-calc": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-6.0.1.tgz", - "integrity": "sha1-PSQXG79udinUIqQ26/5t2VEfQzA=", - "dev": true, - "requires": { - "css-unit-converter": "^1.1.1", - "postcss": "^6.0.0", - "postcss-selector-parser": "^2.2.2", - "reduce-css-calc": "^2.0.0" - } - }, - "reduce-css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.4.tgz", - "integrity": "sha512-i/vWQbyd3aJRmip9OVSN9V6nIjLf/gg/ctxb0CpvHWtcRysFl/ngDBQD+rqavxdw/doScA3GMBXhzkHQ4GCzFQ==", - "dev": true, - "requires": { - "css-unit-converter": "^1.1.1", - "postcss-value-parser": "^3.3.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "postcss-custom-media": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz", - "integrity": "sha1-vlMnhBEOyylQRPtTlaGABushpzc=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-custom-properties": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", - "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "postcss": "^6.0.13" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-custom-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz", - "integrity": "sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-selector-matches": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-font-family-system-ui": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-3.0.0.tgz", - "integrity": "sha512-58G/hTxMSSKlIRpcPUjlyo6hV2MEzvcVO2m4L/T7Bb2fJTG4DYYfQjQeRvuimKQh1V1sOzCIz99g+H2aFNtlQw==", - "dev": true, - "requires": { - "postcss": "^6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-font-variant": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz", - "integrity": "sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-html": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.33.0.tgz", - "integrity": "sha512-3keDoRG0o8bJZKe/QzkOPUD3GQQvAmYhIAtsGrgTxIXB6xZnSQq3gwPjCEd2IAUtz9/Fkus70XGm6xJEZ+bAmg==", - "dev": true, - "requires": { - "htmlparser2": "^3.9.2" - } - }, - "postcss-image-set-polyfill": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz", - "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-media-query-parser": "^0.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-initial": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-2.0.0.tgz", - "integrity": "sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q=", - "dev": true, - "requires": { - "lodash.template": "^4.2.4", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-jsx": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/postcss-jsx/-/postcss-jsx-0.33.0.tgz", - "integrity": "sha512-+ZH4FyxQel2O5uYkNKBnDdW2jCwIb5HwwyFsKuEI164Vmq9Wm07nT2lj65P1qDSRXP2Ik05DrSHzY8Hmt5VP4A==", - "dev": true, - "requires": { - "@babel/core": "^7.0.0-rc.1", - "postcss-styled": ">=0.33.0" - } - }, - "postcss-less": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-2.0.0.tgz", - "integrity": "sha512-pPNsVnpCB13nBMOcl5GVh8JGmB0JGFjqkLUDzKdVpptFFKEe9wFdEzvh2j4lD2AD+7qcrUfw9Ta+oi5+Fw7jjQ==", - "dev": true, - "requires": { - "postcss": "^5.2.16" - }, - "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-load-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", - "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", - "dev": true, - "requires": { - "cosmiconfig": "^4.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "postcss-markdown": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/postcss-markdown/-/postcss-markdown-0.33.0.tgz", - "integrity": "sha512-JZtetO15t5nNpymHDbRhuiOF8yJm1btrbUBP3iL39yLTiY8oChCsnCKfQjEuHB9+85fku5MoU/bRgQ8K45klMg==", - "dev": true, - "requires": { - "remark": "^9.0.0", - "unist-util-find-all-after": "^1.0.2" - } - }, - "postcss-media-minmax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz", - "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", - "dev": true - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-modules-extract-imports": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", - "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-nesting": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.2.1.tgz", - "integrity": "sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA==", - "dev": true, - "requires": { - "postcss": "^6.0.11" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-pseudo-class-any-link": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz", - "integrity": "sha1-kVKgYT00UHIFE+iJKFS65C0O5o4=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-selector-parser": "^2.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-pseudoelements": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz", - "integrity": "sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=", - "dev": true, - "requires": { - "postcss": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-replace-overflow-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz", - "integrity": "sha1-eU22+qVPjbEAhUOSqTr0V2i04ls=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-reporter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", - "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "lodash": "^4.17.4", - "log-symbols": "^2.0.0", - "postcss": "^6.0.8" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", - "dev": true - }, - "postcss-safe-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz", - "integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.2.tgz", - "integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-sass": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.2.0.tgz", - "integrity": "sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg==", - "dev": true, - "requires": { - "gonzales-pe": "^4.0.3", - "postcss": "^6.0.6" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-scss": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.2.tgz", - "integrity": "sha1-/0XPM1S4ee6JpOtoaA9GrJuxT5Q=", - "dev": true, - "requires": { - "postcss": "^6.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-selector-matches": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz", - "integrity": "sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-selector-not": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz", - "integrity": "sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-smart-import": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/postcss-smart-import/-/postcss-smart-import-0.7.6.tgz", - "integrity": "sha512-9OpXaQ1uMMHWafUh0RWIpAKa3xxUDC2yyxicUPpGffH33nzbZG4/z+nk5Ocw5gGZ+3qkXV91iDV23Cmxf2Jhew==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "lodash": "^4.17.4", - "object-assign": "^4.1.1", - "postcss": "^6.0.14", - "postcss-sass": "^0.2.0", - "postcss-scss": "^1.0.2", - "postcss-value-parser": "^3.3.0", - "promise-each": "^2.2.0", - "read-cache": "^1.0.0", - "resolve": "^1.5.0", - "sugarss": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "sugarss": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-1.0.1.tgz", - "integrity": "sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA==", - "dev": true, - "requires": { - "postcss": "^6.0.14" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-styled": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/postcss-styled/-/postcss-styled-0.33.0.tgz", - "integrity": "sha512-ybKIBKYY6q0hADQUECW2F4fDybDFIiAfpMf06/2maxU0yp0FvMTeABrDjzSmKu+99Nj2Gsxe80Xn56FbhzIZZQ==", - "dev": true - }, - "postcss-syntax": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.33.0.tgz", - "integrity": "sha512-A9ABlaRy7KWUfG5E39GVTUoc5TXNuNTts5GzwDLwnSaVG151CSLCTcr51/m8cHi4KXcYa+5ImLyeSfBOhEYtGw==", - "dev": true - }, - "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", - "dev": true, - "requires": { - "renderkid": "^2.0.1", - "utila": "~0.4" - } - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "private": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", - "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", - "dev": true - }, - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, - "requires": { - "asap": "~2.0.3" - } - }, - "promise-each": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/promise-each/-/promise-each-2.2.0.tgz", - "integrity": "sha1-M1MXTv8mlEgQN+BOAfd6oPttG2A=", - "dev": true, - "requires": { - "any-promise": "^0.1.0" - } - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" - } - }, - "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "q": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", - "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=", - "dev": true - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", - "dev": true - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "raf": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz", - "integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==", - "dev": true, - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", - "dev": true - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "react": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/react/-/react-16.5.2.tgz", - "integrity": "sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "schedule": "^0.5.0" - } - }, - "react-contextmenu": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/react-contextmenu/-/react-contextmenu-2.9.3.tgz", - "integrity": "sha512-KFufA4xbBLyJOcWtw6fpM3nW7GcnRIbP1iv7hzJi4Wt1SN7iV62okubjFOk7GOi6Nz3QHncHIcvtX4NRiqMbmA==", - "requires": { - "classnames": "^2.2.5", - "object-assign": "^4.1.0" - } - }, - "react-dom": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.5.2.tgz", - "integrity": "sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "schedule": "^0.5.0" - } - }, - "react-hot-loader": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.3.8.tgz", - "integrity": "sha512-KJV9zR4dUUMDg0E+4ZHIrnje2O0djtqDNi+I9UbzYdpzLI8xQRS3iH39Qs/C4pKDhp5njDz7FSqMRl2P6jD77g==", - "dev": true, - "requires": { - "fast-levenshtein": "^2.0.6", - "global": "^4.3.0", - "hoist-non-react-statics": "^2.5.0", - "prop-types": "^15.6.1", - "react-lifecycles-compat": "^3.0.4", - "shallowequal": "^1.0.2" - } - }, - "react-is": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.5.2.tgz", - "integrity": "sha512-hSl7E6l25GTjNEZATqZIuWOgSnpXb3kD0DVCujmg46K5zLxsbiKaaT6VO9slkSBDPZfYs30lwfJwbOFOnoEnKQ==", - "dev": true - }, - "react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - }, - "react-popper": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.0.2.tgz", - "integrity": "sha512-vjZ94ki8sfCAg45MMi4uqnUUWdzbnYkb95sR2+HgiMaAPzQcy4DfDKYtYUOhhE+sdtkufWcUHLv09DmH2Js57w==", - "dev": true, - "requires": { - "babel-runtime": "6.x.x", - "create-react-context": "^0.2.1", - "popper.js": "^1.14.1", - "prop-types": "^15.6.1", - "typed-styles": "^0.0.5", - "warning": "^3.0.0" - }, - "dependencies": { - "warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - } - } - }, - "react-redux": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", - "integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==", - "requires": { - "hoist-non-react-statics": "^2.5.0", - "invariant": "^2.0.0", - "lodash": "^4.17.5", - "lodash-es": "^4.17.5", - "loose-envify": "^1.1.0", - "prop-types": "^15.6.0" - }, - "dependencies": { - "hoist-non-react-statics": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz", - "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w==" - }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" - }, - "lodash-es": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.5.tgz", - "integrity": "sha512-Ez3ONp3TK9gX1HYKp6IhetcVybD+2F+Yp6GS9dfH8ue6EOCEzQtQEh4K0FYWBP9qLv+lzeQAYXw+3ySfxyZqkw==" - } - } - }, - "react-router": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", - "integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==", - "requires": { - "history": "^4.7.2", - "hoist-non-react-statics": "^2.5.0", - "invariant": "^2.2.4", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.1", - "warning": "^4.0.1" - }, - "dependencies": { - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - } - } - }, - "react-router-dom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz", - "integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==", - "requires": { - "history": "^4.7.2", - "invariant": "^2.2.4", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.1", - "react-router": "^4.3.1", - "warning": "^4.0.1" - }, - "dependencies": { - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - } - } - }, - "react-test-renderer": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.5.2.tgz", - "integrity": "sha512-AGbJYbCVx1J6jdUgI4s0hNp+9LxlgzKvXl0ROA3DHTrtjAr00Po1RhDZ/eAq2VC/ww8AHgpDXULh5V2rhEqqJg==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.5.2", - "schedule": "^0.5.0" - } - }, - "react-transition-group": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz", - "integrity": "sha512-Xv5d55NkJUxUzLCImGSanK8Cl/30sgpOEMGc5m86t8+kZwrPxPCPcFqyx83kkr+5Lz5gs6djuvE5By+gce+VjA==", - "requires": { - "dom-helpers": "^3.3.1", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-lifecycles-compat": "^3.0.4" - } - }, - "reactstrap": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-6.4.0.tgz", - "integrity": "sha512-+O0pnbsheW4i6wE96KlSpIhbnZM9EJv0XUYVuFbzLElRp33WrMKvX9YTgGgJQEqHLCJYYdJBi+fGm/hTwTfsCQ==", - "requires": { - "classnames": "^2.2.3", - "lodash.isfunction": "^3.0.9", - "lodash.isobject": "^3.0.2", - "lodash.tonumber": "^4.0.3", - "prop-types": "^15.5.8", - "react-lifecycles-compat": "^3.0.4", - "react-popper": "^0.10.4", - "react-transition-group": "^2.3.1" - }, - "dependencies": { - "react-popper": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.10.4.tgz", - "integrity": "sha1-rypBXqIike3VBGeNev2opu4ylao=", - "requires": { - "popper.js": "^1.14.1", - "prop-types": "^15.6.1" - } - } - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" - } - }, - "recast": { - "version": "0.11.23", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", - "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", - "dev": true, - "requires": { - "ast-types": "0.9.6", - "esprima": "~3.1.0", - "private": "~0.1.5", - "source-map": "~0.5.0" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "dependencies": { - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - } - } - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "redux": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.0.tgz", - "integrity": "sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA==", - "requires": { - "loose-envify": "^1.1.0", - "symbol-observable": "^1.2.0" - }, - "dependencies": { - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" - } - } - }, - "redux-devtools": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/redux-devtools/-/redux-devtools-3.4.1.tgz", - "integrity": "sha1-CdNCzgq2CHvmeelTodfFMO+hE44=", - "dev": true, - "requires": { - "lodash": "^4.2.0", - "prop-types": "^15.5.7", - "redux-devtools-instrument": "^1.0.1" - } - }, - "redux-devtools-instrument": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/redux-devtools-instrument/-/redux-devtools-instrument-1.8.2.tgz", - "integrity": "sha1-XpHP5ALnkNrj/S8NI197fYSwn/4=", - "dev": true, - "requires": { - "lodash": "^4.2.0", - "symbol-observable": "^1.0.2" - } - }, - "redux-thunk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", - "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" - }, - "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", - "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - }, - "dependencies": { - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - } - } - }, - "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", - "dev": true - }, - "regenerator-transform": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", - "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, - "regex-not": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1" - } - }, - "regexpp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", - "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==", - "dev": true - }, - "regexpu-core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.2.0.tgz", - "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.4.0", - "regjsparser": "^0.3.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regjsgen": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.4.0.tgz", - "integrity": "sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==", - "dev": true - }, - "regjsparser": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.3.0.tgz", - "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remark": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", - "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", - "dev": true, - "requires": { - "remark-parse": "^5.0.0", - "remark-stringify": "^5.0.0", - "unified": "^6.0.0" - } - }, - "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "remark-stringify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", - "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "renderkid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", - "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", - "dev": true, - "requires": { - "css-select": "^1.1.0", - "dom-converter": "~0.1", - "htmlparser2": "~3.3.0", - "strip-ansi": "^3.0.0", - "utila": "~0.3" - }, - "dependencies": { - "domhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", - "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", - "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "htmlparser2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", - "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", - "dev": true, - "requires": { - "domelementtype": "1", - "domhandler": "2.1", - "domutils": "1.1", - "readable-stream": "1.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", - "dev": true - } - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "reselect": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", - "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=" - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "resolve-pathname": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", - "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rfdc": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", - "dev": true - }, - "rgb": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/rgb/-/rgb-0.1.0.tgz", - "integrity": "sha1-vieykej+/+rBvZlylyG/pA/AN7U=", - "dev": true - }, - "rgb-hex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-2.1.0.tgz", - "integrity": "sha1-x3PF/iJoolV42SU5qCp6XOU77aY=", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", - "dev": true, - "requires": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" - }, - "rxjs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.2.tgz", - "integrity": "sha512-hV7criqbR0pe7EeL3O66UYVg92IR0XsA97+9y+BWTePK9SKmEI5Qd3Zj6uPnGkNzXsBywBQWTvujPl+1Kn9Zjw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schedule": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/schedule/-/schedule-0.5.0.tgz", - "integrity": "sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw==", - "requires": { - "object-assign": "^4.1.1" - } - }, - "schema-utils": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - }, - "dependencies": { - "ajv-keywords": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", - "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", - "dev": true - } - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selenium-webdriver": { - "version": "4.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.1.tgz", - "integrity": "sha512-z88rdjHAv3jmTZ7KSGUkTvo4rGzcDGMq0oXWHNIDK96Gs31JKVdu9+FMtT4KBrVoibg8dUicJDok6GnqqttO5Q==", - "dev": true, - "requires": { - "jszip": "^3.1.3", - "rimraf": "^2.5.4", - "tmp": "0.0.30", - "xml2js": "^0.4.17" - }, - "dependencies": { - "tmp": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.1" - } - } - } - }, - "selfsigned": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.3.tgz", - "integrity": "sha512-vmZenZ+8Al3NLHkWnhBQ0x6BkML1eCP2xEi3JE+f3D9wW9fipD9NNJHYtE9XJM4TsPaHGZJIamrSI6MTg1dU2Q==", - "dev": true, - "requires": { - "node-forge": "0.7.5" - } - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", - "dev": true - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "dev": true, - "requires": { - "to-object-path": "^0.3.0" - } - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "simple-html-tokenizer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz", - "integrity": "sha1-BcLuxXn//+FFoDCsJs/qYbmA+r4=", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz", - "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=", - "dev": true - } - } - }, - "sinon": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-6.3.4.tgz", - "integrity": "sha512-NIaR56Z1mefuRBXYrf4otqBxkWiKveX+fvqs3HzFq2b07HcgpkMgIwmQM/owNjNFAHkx0kJXW+Q0mDthiuslXw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.0.2", - "@sinonjs/formatio": "^3.0.0", - "@sinonjs/samsam": "^2.1.1", - "diff": "^3.5.0", - "lodash.get": "^4.4.2", - "lolex": "^2.7.4", - "nise": "^1.4.5", - "supports-color": "^5.5.0", - "type-detect": "^4.0.8" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "snapdragon": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^2.0.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", - "dev": true, - "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, - "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", - "dev": true, - "requires": { - "faye-websocket": "^0.10.0", - "uuid": "^3.0.1" - } - }, - "sockjs-client": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz", - "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", - "dev": true, - "requires": { - "debug": "^2.6.6", - "eventsource": "0.1.6", - "faye-websocket": "~0.11.0", - "inherits": "^2.0.1", - "json3": "^3.3.2", - "url-parse": "^1.1.8" - }, - "dependencies": { - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - } - } - }, - "sort-any": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/sort-any/-/sort-any-1.1.12.tgz", - "integrity": "sha512-RaVPeOjzn5tjhAfvQstA34gPiG/HT+1MefSsG0KHIMhXjLlZREYSIkxlYaCRvdwLKNgpsgM6nvpLEY1Y0Ja9FQ==", - "dev": true, - "requires": { - "lodash": "^4.17.4" - } - }, - "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true, - "requires": { - "atob": "^2.0.0", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true, - "requires": { - "spdx-license-ids": "^1.0.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true - }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", - "dev": true - }, - "spdy": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", - "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", - "dev": true, - "requires": { - "debug": "^2.6.8", - "handle-thing": "^1.2.5", - "http-deceiver": "^1.2.7", - "safe-buffer": "^5.0.1", - "select-hose": "^2.0.0", - "spdy-transport": "^2.0.18" - } - }, - "spdy-transport": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", - "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", - "dev": true, - "requires": { - "debug": "^2.6.8", - "detect-node": "^2.0.3", - "hpack.js": "^2.1.6", - "obuf": "^1.1.1", - "readable-stream": "^2.2.9", - "safe-buffer": "^5.0.1", - "wbuf": "^1.7.2" - } - }, - "specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "state-toggle": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", - "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", - "dev": true, - "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string.prototype.trim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", - "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.0", - "function-bind": "^1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "stringify-entities": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "style-loader": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.0.tgz", - "integrity": "sha512-uCcN7XWHkqwGVt7skpInW6IGO1tG6ReyFQ1Cseh0VcN6VdcFQi62aG/2F3Y9ueA8x4IVlfaSUxpmQXQD9QrEuQ==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5" - } - }, - "style-search": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", - "dev": true - }, - "stylelint": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-9.5.0.tgz", - "integrity": "sha512-63R/DGDjMekFwS4xaHSLy26N19pT1Jsxj7u5QNcJrUWBvvPoBCYx3ObINRgsvNMoupzhV7N0PjylxrDHyh4cKQ==", - "dev": true, - "requires": { - "autoprefixer": "^9.0.0", - "balanced-match": "^1.0.0", - "chalk": "^2.4.1", - "cosmiconfig": "^5.0.0", - "debug": "^3.0.0", - "execall": "^1.0.0", - "file-entry-cache": "^2.0.0", - "get-stdin": "^6.0.0", - "globby": "^8.0.0", - "globjoin": "^0.1.4", - "html-tags": "^2.0.0", - "ignore": "^4.0.0", - "import-lazy": "^3.1.0", - "imurmurhash": "^0.1.4", - "known-css-properties": "^0.6.0", - "lodash": "^4.17.4", - "log-symbols": "^2.0.0", - "mathml-tag-names": "^2.0.1", - "meow": "^5.0.0", - "micromatch": "^2.3.11", - "normalize-selector": "^0.2.0", - "pify": "^4.0.0", - "postcss": "^7.0.0", - "postcss-html": "^0.33.0", - "postcss-jsx": "^0.33.0", - "postcss-less": "^2.0.0", - "postcss-markdown": "^0.33.0", - "postcss-media-query-parser": "^0.2.3", - "postcss-reporter": "^5.0.0", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-safe-parser": "^4.0.0", - "postcss-sass": "^0.3.0", - "postcss-scss": "^2.0.0", - "postcss-selector-parser": "^3.1.0", - "postcss-styled": "^0.33.0", - "postcss-syntax": "^0.33.0", - "postcss-value-parser": "^3.3.0", - "resolve-from": "^4.0.0", - "signal-exit": "^3.0.2", - "specificity": "^0.4.0", - "string-width": "^2.1.0", - "style-search": "^0.1.0", - "sugarss": "^2.0.0", - "svg-tags": "^1.0.0", - "table": "^4.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cosmiconfig": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.6.tgz", - "integrity": "sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ==", - "dev": true, - "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0" - } - }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, - "globby": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", - "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "dependencies": { - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", - "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0", - "yargs-parser": "^10.0.0" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "pify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.0.tgz", - "integrity": "sha512-zrSP/KDf9DH3K3VePONoCstgPiYJy9z0SCatZuTpOc7YdnWIqwkWdXOuwlr4uDc7em8QZRsFWsT/685x5InjYg==", - "dev": true - }, - "postcss": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.2.tgz", - "integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-sass": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.3.3.tgz", - "integrity": "sha512-uoRhfwZJHDRI8p2KQniTx4UwzYwKgQUhmFNJ7aysL3+tgFUfmv5TPX8UPnlE5gfrq6KHUUwPJ/nISFtzwxr7iQ==", - "dev": true, - "requires": { - "gonzales-pe": "^4.2.3", - "postcss": "^7.0.1" - } - }, - "postcss-scss": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.0.0.tgz", - "integrity": "sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", - "dev": true, - "requires": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - } - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "stylelint-config-recommended": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz", - "integrity": "sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA==", - "dev": true - }, - "stylelint-config-standard": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-18.2.0.tgz", - "integrity": "sha512-07x0TaSIzvXlbOioUU4ORkCIM07kyIuojkbSVCyFWNVgXMXYHfhnQSCkqu+oHWJf3YADAnPGWzdJ53NxkoJ7RA==", - "dev": true, - "requires": { - "stylelint-config-recommended": "^2.1.0" - } - }, - "sugarss": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz", - "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==", - "dev": true, - "requires": { - "postcss": "^7.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.2.tgz", - "integrity": "sha512-fmaUY5370keLUTx+CnwRxtGiuFTcNBLQBqr1oE3WZ/euIYmGAo0OAgOhVJ3ByDnVmOR3PK+0V9VebzfjRIUcqw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "svg-inline-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.0.tgz", - "integrity": "sha512-rynplY2eXFrdNomL1FvyTFQlP+dx0WqbzHglmNtA9M4IHRC3no2aPAl3ny9lUpJzFzFMZfWRK5YIclNU+FRePA==", - "dev": true, - "requires": { - "loader-utils": "^0.2.11", - "object-assign": "^4.0.1", - "simple-html-tokenizer": "^0.1.1" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - } - } - }, - "svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", - "dev": true - }, - "symbol-observable": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", - "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=", - "dev": true - }, - "table": { - "version": "4.0.3", - "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", - "dev": true, - "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true - }, - "tern-jsx": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tern-jsx/-/tern-jsx-1.0.3.tgz", - "integrity": "sha1-6tjJbAVO6OSo3tpb+0Z8eMbcOJA=", - "dev": true, - "requires": { - "acorn-jsx": "^3.0.0", - "resolve-from": "^2.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - } - } - }, - "terser": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.8.2.tgz", - "integrity": "sha512-FGSBXiBJe2TSXy6pWwXpY0YcEWEK35UKL64BBbxX3aHqM4Nj0RMqXvqBuoSGfyd80t8MKQ5JwYm5jRRGTSEFNg==", - "dev": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1", - "source-map-support": "~0.5.6" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz", - "integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==", - "dev": true, - "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.8.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "cacache": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.2.0.tgz", - "integrity": "sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - } - }, - "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - } - } - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "throttle-debounce": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.0.1.tgz", - "integrity": "sha512-Sr6jZBlWShsAaSXKyNXyNicOrJW/KtkDqIEwHt4wYwWA2wa/q67Luhqoujg48V8hTk60wB56tYrJJn6jc2R7VA==" - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", - "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", - "dev": true - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", - "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "regex-not": "^1.0.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } - } - }, - "toposort": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.6.tgz", - "integrity": "sha1-wxdI5V0hDv/AD9zcfW5o19e7nOw=", - "dev": true - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "trim-trailing-lines": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", - "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==", - "dev": true - }, - "trough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", - "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", - "dev": true - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", - "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=", - "dev": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "typed-styles": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.5.tgz", - "integrity": "sha512-ht+rEe5UsdEBAa3gr64+QjUOqjOLJfWLvl5HZR5Ev9uo/OnD3p43wPeFSB1hNFc13GXQF/JU1Bn0YHLUqBRIlw==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.14", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.14.tgz", - "integrity": "sha1-EQ1T+kw/MmwSEpK76skE0uAzh8o=", - "dev": true - }, - "uglify-js": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.18.tgz", - "integrity": "sha512-VhjIFv93KnTx/ntNi9yTBbfrsWnQnqUy02MT32uqU/5i2oEJ8GAEJ0AwYV206JeOmIzSjm41Ba0iXVKv6j7y9g==", - "dev": true, - "requires": { - "commander": "~2.15.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "uglifyjs-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", - "dev": true, - "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "uglify-es": "^3.3.4", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", - "dev": true, - "requires": { - "commander": "~2.13.0", - "source-map": "~0.6.1" - } - } - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "underscore": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", - "dev": true - }, - "unherit": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", - "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", - "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", - "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", - "dev": true - }, - "unified": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "unique-filename": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", - "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", - "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unist-util-find-all-after": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz", - "integrity": "sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w==", - "dev": true, - "requires": { - "unist-util-is": "^2.0.0" - } - }, - "unist-util-is": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", - "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==", - "dev": true - }, - "unist-util-remove-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", - "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "unist-util-visit": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", - "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", - "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", - "dev": true, - "requires": { - "unist-util-is": "^2.1.2" - } - }, - "units-css": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/units-css/-/units-css-0.4.0.tgz", - "integrity": "sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc=", - "dev": true, - "requires": { - "isnumeric": "^0.2.0", - "viewport-dimensions": "^0.2.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "upath": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.5.tgz", - "integrity": "sha512-qbKn90aDQ0YEwvXoLqj0oiuUYroLX2lVHZ+b+xwjozFasAOC4GneDq5+OaIG5Zj+jFmbz/uO+f7a9qxjktJQww==", - "dev": true - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", - "dev": true - }, - "url-parse": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", - "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", - "dev": true, - "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" - } - }, - "use": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "lazy-cache": "^2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - }, - "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", - "dev": true, - "requires": { - "set-getter": "^0.1.0" - } - } - } - }, - "useragent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", - "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", - "dev": true, - "requires": { - "lru-cache": "2.2.x", - "tmp": "0.0.x" - }, - "dependencies": { - "lru-cache": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", - "dev": true - } - } - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", - "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, - "requires": { - "spdx-correct": "~1.0.0", - "spdx-expression-parse": "~1.0.0" - } - }, - "value-equal": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", - "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } - }, - "vfile-location": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz", - "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==", - "dev": true - }, - "vfile-message": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", - "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - }, - "viewport-dimensions": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz", - "integrity": "sha1-3nQHR9tTh/0XJfUXXpG6x2r982w=", - "dev": true - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, - "warning": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.1.tgz", - "integrity": "sha512-rAVtTNZw+cQPjvGp1ox0XC5Q2IBFyqoqh+QII4J/oguyu83Bax1apbo2eqB8bHRS+fqYUBagys6lqUoVwKSmXQ==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webpack": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.19.1.tgz", - "integrity": "sha512-j7Q/5QqZRqIFXJvC0E59ipLV5Hf6lAnS3ezC3I4HMUybwEDikQBVad5d+IpPtmaQPQArvgUZLXIN6lWijHBn4g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.6", - "@webassemblyjs/helper-module-context": "1.7.6", - "@webassemblyjs/wasm-edit": "1.7.6", - "@webassemblyjs/wasm-parser": "1.7.6", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", - "tapable": "^1.1.0", - "uglifyjs-webpack-plugin": "^1.2.4", - "watchpack": "^1.5.0", - "webpack-sources": "^1.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "tapable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", - "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", - "dev": true - } - } - }, - "webpack-cli": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.0.tgz", - "integrity": "sha512-p5NeKDtYwjZozUWq6kGNs9w+Gtw/CPvyuXjXn2HMdz8Tie+krjEg8oAtonvIyITZdvpF7XG9xDHwscLr2c+ugQ==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.0.0", - "global-modules-path": "^2.1.0", - "import-local": "^1.0.0", - "inquirer": "^6.0.0", - "interpret": "^1.1.0", - "loader-utils": "^1.1.0", - "supports-color": "^5.4.0", - "v8-compile-cache": "^2.0.0", - "yargs": "^12.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.5.0.tgz", - "integrity": "sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "external-editor": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.0.tgz", - "integrity": "sha512-mpkfj0FEdxrIhOC04zk85X7StNtr0yXnG7zCb+8ikO8OJi2jsHh5YGoknNTyXgsbHOf1WOOcVU3kPFWT2WgCkQ==", - "dev": true, - "requires": { - "chardet": "^0.5.0", - "iconv-lite": "^0.4.22", - "tmp": "^0.0.33" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inquirer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.0.0.tgz", - "integrity": "sha512-tISQWRwtcAgrz+SHPhTH7d3e73k31gsOy6i1csonLc0u1dVK/wYvuOnFeiWqC5OXFIYbmrIFInef31wbT8MEJg==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.0", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.1.0", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "rxjs": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", - "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, - "yargs": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.1.tgz", - "integrity": "sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^2.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" - } - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", - "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" - }, - "dependencies": { - "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", - "dev": true - } - } - }, - "webpack-dev-server": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.8.tgz", - "integrity": "sha512-c+tcJtDqnPdxCAzEEZKdIPmg3i5i7cAHe+B+0xFNK0BlCc2HF/unYccbU7xTgfGc5xxhCztCQzFmsqim+KhI+A==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.0.0", - "compression": "^1.5.2", - "connect-history-api-fallback": "^1.3.0", - "debug": "^3.1.0", - "del": "^3.0.0", - "express": "^4.16.2", - "html-entities": "^1.2.0", - "http-proxy-middleware": "~0.18.0", - "import-local": "^2.0.0", - "internal-ip": "^3.0.1", - "ip": "^1.1.5", - "killable": "^1.0.0", - "loglevel": "^1.4.1", - "opn": "^5.1.0", - "portfinder": "^1.0.9", - "schema-utils": "^1.0.0", - "selfsigned": "^1.9.1", - "serve-index": "^1.7.2", - "sockjs": "0.3.19", - "sockjs-client": "1.1.5", - "spdy": "^3.4.1", - "strip-ansi": "^3.0.0", - "supports-color": "^5.1.0", - "webpack-dev-middleware": "3.2.0", - "webpack-log": "^2.0.0", - "yargs": "12.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" - } - }, - "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", - "dev": true, - "requires": { - "execa": "^0.10.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "url-join": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", - "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", - "dev": true - }, - "webpack-dev-middleware": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.2.0.tgz", - "integrity": "sha512-YJLMF/96TpKXaEQwaLEo+Z4NDK8aV133ROF6xp9pe3gQoS7sxfpXh4Rv9eC+8vCvWfmDjRQaMSlRPbO+9G6jgA==", - "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.3.1", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^4.0.0", - "webpack-log": "^2.0.0" - } - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, - "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^2.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" - } - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "webpack-log": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", - "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "loglevelnext": "^1.0.1", - "uuid": "^3.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "webpack-sources": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz", - "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "webpack-visualizer-plugin": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/webpack-visualizer-plugin/-/webpack-visualizer-plugin-0.1.11.tgz", - "integrity": "sha1-uHcK2GtPZSYSxosbeCJT+vn4o04=", - "dev": true, - "requires": { - "d3": "^3.5.6", - "mkdirp": "^0.5.1", - "react": "^0.14.0", - "react-dom": "^0.14.0" - }, - "dependencies": { - "d3": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", - "integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=", - "dev": true - }, - "fbjs": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.6.1.tgz", - "integrity": "sha1-lja3cF9bqWhNRLcveDISVK/IYPc=", - "dev": true, - "requires": { - "core-js": "^1.0.0", - "loose-envify": "^1.0.0", - "promise": "^7.0.3", - "ua-parser-js": "^0.7.9", - "whatwg-fetch": "^0.9.0" - } - }, - "react": { - "version": "0.14.9", - "resolved": "https://registry.npmjs.org/react/-/react-0.14.9.tgz", - "integrity": "sha1-kRCmSXxJ1EuhwO3TF67CnC4NkdE=", - "dev": true, - "requires": { - "envify": "^3.0.0", - "fbjs": "^0.6.1" - } - }, - "react-dom": { - "version": "0.14.9", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-0.14.9.tgz", - "integrity": "sha1-BQZKPc8PsYgKOyv8nVjFXY2fYpM=", - "dev": true - }, - "whatwg-fetch": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz", - "integrity": "sha1-DjaExsuZlbQ+/J3wPkw2XZX9nMA=", - "dev": true - } - } - }, - "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, - "requires": { - "http-parser-js": ">=0.4.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true - }, - "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", - "dev": true - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", - "dev": true, - "requires": { - "errno": "~0.1.7" - }, - "dependencies": { - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - } - } - }, - "worker-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", - "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", - "dev": true, - "requires": { - "loader-utils": "^1.0.0", - "schema-utils": "^0.4.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - } - } - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - } - } -} diff --git a/conda/js/package.json b/conda/js/package.json deleted file mode 100644 index 402eacec..00000000 --- a/conda/js/package.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "name": "beat.editor", - "version": "0.0.0", - "description": "A local editor for BEAT objects, including a graphical toolchain editor and a simple web server.", - "main": "index.js", - "scripts": { - "start": "cross-env NODE_ENV=debug webpack-dev-server --hot", - "prebuild": "rimraf ../../beat/editor/js", - "build": "cross-env NODE_ENV=production webpack", - "test-start": "cross-env BABEL_ENV=test NODE_ENV=test karma start --no-single-run", - "test": "cross-env BABEL_ENV=test NODE_ENV=test karma start", - "lint": "eslint --ext .js,.jsx src && eslint test && stylelint 'src/**/*.jsx, src/**/*.css, src/**/*.html' && npm run flow", - "lint:fix": "eslint --ext .js,.jsx src --fix && eslint test --fix", - "flow": "flow", - "prepush": "npm test" - }, - "browserslist": [ - "last 2 Chrome versions", - "last 2 Firefox versions", - "last 1 Safari versions" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "@babel/core": "^7.1.0", - "@babel/plugin-proposal-class-properties": "^7.1.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.0.0", - "@babel/preset-env": "^7.1.0", - "@babel/preset-flow": "^7.0.0", - "@babel/preset-react": "^7.0.0", - "babel-eslint": "^9.0.0", - "babel-loader": "^8.0.2", - "chai": "^4.1.2", - "chai-enzyme": "^1.0.0-beta.1", - "cross-env": "^5.2.0", - "css-loader": "^1.0.0", - "deep-equal-in-any-order": "^1.0.10", - "enzyme": "^3.6.0", - "enzyme-adapter-react-16": "^1.5.0", - "eslint": "^5.6.0", - "eslint-plugin-compat": "^2.5.1", - "eslint-plugin-flowtype": "^2.50.1", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-react": "^7.11.1", - "flow-bin": "^0.81.0", - "html-webpack-plugin": "^3.2.0", - "husky": "^0.14.3", - "karma": "^3.0.0", - "karma-chrome-launcher": "^2.2.0", - "karma-coverage": "^1.1.2", - "karma-firefox-launcher": "^1.1.0", - "karma-mocha": "^1.3.0", - "karma-mocha-reporter": "^2.2.5", - "karma-sourcemap-loader": "^0.3.7", - "karma-webpack": "^3.0.5", - "mocha": "^5.2.0", - "postcss": "^7.0.2", - "postcss-cli": "^6.0.0", - "postcss-cssnext": "^3.1.0", - "postcss-loader": "^3.0.0", - "postcss-smart-import": "^0.7.6", - "react-hot-loader": "^4.3.8", - "react-popper": "^1.0.2", - "react-test-renderer": "^16.5.2", - "redux-devtools": "^3.4.1", - "rimraf": "^2.6.2", - "selenium-webdriver": "^4.0.0-alpha.1", - "sinon": "^6.3.4", - "style-loader": "^0.23.0", - "stylelint": "^9.5.0", - "stylelint-config-standard": "^18.2.0", - "svg-inline-loader": "^0.8.0", - "tern-jsx": "^1.0.3", - "terser-webpack-plugin": "^1.1.0", - "webpack": "^4.19.1", - "webpack-cli": "^3.1.0", - "webpack-dev-server": "^3.1.8", - "webpack-visualizer-plugin": "^0.1.11", - "worker-loader": "^2.0.0" - }, - "dependencies": { - "ajv": "^6.5.3", - "bootstrap": "^4.1.3", - "classnames": "^2.2.6", - "d3": "^5.7.0", - "fast-copy": "^1.2.2", - "fast-levenshtein": "^2.0.6", - "fuse.js": "^3.2.1", - "prop-types": "^15.6.2", - "react": "^16.5.2", - "react-contextmenu": "^2.9.3", - "react-dom": "^16.5.2", - "react-redux": "^5.0.7", - "react-router-dom": "^4.3.1", - "react-transition-group": "^2.4.0", - "reactstrap": "^6.4.0", - "redux": "^4.0.0", - "redux-thunk": "^2.3.0", - "reselect": "^3.0.1", - "throttle-debounce": "^2.0.1" - } -} diff --git a/conda/js/src/components/App.jsx b/conda/js/src/components/App.jsx deleted file mode 100644 index 2c6805b6..00000000 --- a/conda/js/src/components/App.jsx +++ /dev/null @@ -1,48 +0,0 @@ -// @flow -import React from 'react'; -import { - Container, - Row, - Col, -} from 'reactstrap'; - -import { - HashRouter as Router, - Route, - Switch, -} from 'react-router-dom'; -import { hot } from 'react-hot-loader'; - -import MainNav from './MainNav.jsx'; -import MainContent from './MainContent.jsx'; -import HomeContent from './HomeContent.jsx'; - -type Props = { -}; - -type State = { -}; - -class App extends React.PureComponent<Props, State> { - constructor(props: Props){ - super(props); - } - - render () { - return ( - <Router> - <Container> - <Route component={MainNav} /> - <Switch> - <Route path='/:entity' component={MainContent} /> - <Route> - <HomeContent /> - </Route> - </Switch> - </Container> - </Router> - ); - } -} - -export default hot(module)(App); diff --git a/conda/js/src/components/CacheInput.jsx b/conda/js/src/components/CacheInput.jsx deleted file mode 100644 index 265c161a..00000000 --- a/conda/js/src/components/CacheInput.jsx +++ /dev/null @@ -1,198 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Input, - Alert, - InputGroup, - InputGroupAddon, - UncontrolledTooltip, - Tooltip, -} from 'reactstrap'; - -import { rxField } from '@helpers/beat'; - -type Props = { - // consumer-supplied func for validating input - // if the func finds the input isnt valid, it should return a react.node of text for the error message - validateFunc?: (string) => (true | React.Node), - // if the current input in the CacheInput instance is valid, this func will be called with that value - onChange: (any) => any, - // the current value for this cacheinput - value: string, - // for edge cases - children?: React.Node, - // many fields in the beat editor are restricted to a certain "slugified" format - // if this cacheinput needs that, use this flag - fieldTest?: boolean, - // update delay in ms, defaults to 500 - // basically just simple throttling to keep from overwhelming complex updates in the parent - delay?: number, - // danger color highlight - invalid?: boolean, -}; - -type State = { - // the current string in the CacheInput input field, - // which may or may not be valid - cache: string, - // whether the cache is valid - valid: boolean, - // a text-like react node that represents an error message - invalidityText?: React.Node, - // the delay to use (default 500) - msDelay: number, -}; - -// test for the "fieldTest" flag, with a nice error message -const fieldTestResults = (input: string): true | React.Node => { - return (rxField.test(input) || - <span> - The field name must be at least one character and consisting of only of alphanumeric ASCII characters, `_`, and `-`. - </span> - ); -}; - -// top-level validity func with some edgecase checking -// validateFunc arg lets you also check using a user-defined validate func -const isValid = (input: string, currVal: string, validateFunc: (string) => true | React.Node, fieldTest: boolean): true | React.Node => { - if(input === currVal) - return true; - - if(fieldTest){ - const res = fieldTestResults(input); - if(res !== true) - return res; - } - - const funcRes = validateFunc(input); - - return funcRes; -}; - -// Provides a bootstrap-styled wrapper around <input /> that caches the raw user input until a valid input is provided. -// Also throttles the onChange event to prevent many parent state updates in a short time -class CacheInput extends React.Component<Props, State>{ - constructor(props: Props){ - super(props); - } - - state = { - cache: this.props.value, - valid: false, - invalidityText: undefined, - // default of 500ms delay - msDelay: this.props.delay !== undefined ? this.props.delay : 500, - }; - - // check validation as soon as it mounts - componentDidMount () { - this.updateValidity(this.state.cache); - } - - // if the parent's model (the props) changes, reset input - componentDidUpdate = (prevProps: Props) => { - if(this.props.value !== prevProps.value){ - this.setState({ - cache: (this.props.value), - }); - this.clearTimer(); - } - } - - // gets the validity info of an input string given a curr val - updateValidity = (input: string, currVal?: string = this.props.value) => { - const func = this.props.validateFunc || (() => true); - const validRes = isValid(input, currVal, func, this.props.fieldTest || false); - this.setState({ - valid: validRes === true, - invalidityText: validRes !== true ? validRes : undefined - }); - - return validRes === true; - } - - // the user can pass any props they want onto the inner <Input /> element - // some props shouldn't be passed though - getInputProps = () => { - const inputProps = { ...this.props }; - delete inputProps['validateFunc']; - delete inputProps['children']; - delete inputProps['fieldTest']; - delete inputProps['delay']; - return inputProps; - } - - // throttle timer ref - onChangeTimer = null; - // clears the throttle timer - clearTimer = () => { - if(this.onChangeTimer) - clearTimeout(this.onChangeTimer); - } - - // called whenever the user changes the raw input with the raw input event - // for perf reasons it really focuses on returning when possible - change = (e: any) => { - this.clearTimer(); - const newInput = e.target.value; - // no need to update the state if the value is the same - if(newInput === this.state.cache) - return; - const newValid = this.updateValidity(newInput); - this.setState({ - cache: newInput, - }); - // no need to update props if value is the same - if(newInput === this.props.value) - return; - if(newValid && this.props.onChange){ - if(this.state.msDelay === 0){ - this.props.onChange(e); - } else { - // by default in react events have a "persist" method - // that lets you keep it around for a bit longer than normal - // in testing environments the event persists by default - if(e.persist) - e.persist(); - this.onChangeTimer = setTimeout(() => { - this.props.onChange(e); - }, this.state.msDelay); - } - } - } - - // the Tooltips are annoying in test environments and need a react ref - target = null - - render () { - // either if invalid or if the consuming component set it - const dangerColor = !this.state.valid || this.props.invalid; - return ( - <InputGroup> - { this.props.children } - <Input - type='text' - {...this.getInputProps()} - value={this.state.cache} - onChange={this.change} - valid={!dangerColor} - invalid={dangerColor} - /> - { !this.state.valid && - <div ref={target => {this.target = target;}} className='input-group-append'> - <span className='input-group-text'> - <strong className='text-danger'>!</strong> - </span> - </div> - } - { !this.state.valid && - <UncontrolledTooltip target={() => this.target}> - { this.state.invalidityText } - </UncontrolledTooltip> - } - </InputGroup> - ); - } -} - -export default CacheInput; diff --git a/conda/js/src/components/CacheInput.spec.jsx b/conda/js/src/components/CacheInput.spec.jsx deleted file mode 100644 index 6e0d055d..00000000 --- a/conda/js/src/components/CacheInput.spec.jsx +++ /dev/null @@ -1,63 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import C from './CacheInput.jsx'; - -describe('<CacheInput />', () => { - let wrapper; - const validateFunc = sinon.spy(); - const onChange = sinon.spy(); - const fieldTest = true; - const children = <span>child</span>; - const value = 'value'; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - it(`has 2 required props`, () => { - wrapper = mount( - <C - onChange={onChange} - value={value} - /> - ); - - expect(wrapper).to.have.props( - ['onChange', 'value'] - ).deep.equal( - [onChange, value] - ); - - expect(wrapper).to.not.have.props( - ['validateFunc', 'fieldTest', 'children'] - ); - }); - - it(`can take up to 5 props`, () => { - const validateFunc = sinon.spy(); - const onChange = sinon.spy(); - const fieldTest = true; - const children = <span>child</span>; - const value = 'value'; - wrapper = mount( - <C - validateFunc={validateFunc} - onChange={onChange} - fieldTest={fieldTest} - value={value} - >{ children }</C> - ); - - expect(wrapper).to.have.props( - ['validateFunc', 'onChange', 'fieldTest', 'value', 'children'] - ).deep.equal( - [validateFunc, onChange, fieldTest, value, children] - ); - }); -}); diff --git a/conda/js/src/components/DeleteInputBtn.jsx b/conda/js/src/components/DeleteInputBtn.jsx deleted file mode 100644 index bec3cd7e..00000000 --- a/conda/js/src/components/DeleteInputBtn.jsx +++ /dev/null @@ -1,25 +0,0 @@ -//@flow -import * as React from 'react'; -import { - InputGroupAddon, - Button, -} from 'reactstrap'; - -type Props = { - deleteFunc: (any) => any, -} - -// super simple wrapper for a button that attaches to an input -// styled like a Delete button -const DeleteInputBtn = ({ deleteFunc }: Props) => ( - <InputGroupAddon addonType='prepend'> - <Button - color='danger' - onClick={(e) => deleteFunc(e)} - > - X - </Button> - </InputGroupAddon> -); - -export default DeleteInputBtn; diff --git a/conda/js/src/components/DeleteInputBtn.spec.jsx b/conda/js/src/components/DeleteInputBtn.spec.jsx deleted file mode 100644 index 371aa2bd..00000000 --- a/conda/js/src/components/DeleteInputBtn.spec.jsx +++ /dev/null @@ -1,29 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '../../test'; - -import C from './DeleteInputBtn.jsx'; - -describe('<DeleteInputBtn />', () => { - let wrapper; - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - it('takes a "deleteFunc" prop', () => { - const deleteFunc = sinon.spy(); - wrapper = mount(<C deleteFunc={deleteFunc} />); - expect(wrapper).to.have.prop('deleteFunc', deleteFunc); - }); - - it('calls the deleteFunc when clicked', () => { - const deleteFunc = sinon.spy(); - wrapper = mount(<C deleteFunc={deleteFunc} />); - wrapper.find('button').simulate('click'); - expect(deleteFunc.calledOnce).to.equal(true); - }); -}); diff --git a/conda/js/src/components/EntityDetail.jsx b/conda/js/src/components/EntityDetail.jsx deleted file mode 100644 index 5a00148c..00000000 --- a/conda/js/src/components/EntityDetail.jsx +++ /dev/null @@ -1,247 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - TabContent, - TabPane, - Nav, - NavItem, - NavLink, - Input, - InputGroupAddon, - InputGroup, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import cn from 'classnames'; - -import * as Actions from '@store/actions.js'; -import * as Selectors from '@store/selectors.js'; - -import { - Route, - Link -} from 'react-router-dom'; - -import type { BeatObject, BeatEntity } from '@helpers/beat'; -import { getDefaultEntityObject, pluralize } from '@helpers/beat'; -import { genModuleApiFuncs } from '@helpers/api'; -import ValidSchemaBadge from './ValidSchemaBadge.jsx'; - -import DataformatEditorContainer from './dataformat'; -import AlgorithmEditorContainer from './algorithm'; -import LibraryEditorContainer from './library'; -import DatabaseEditorContainer from './database'; -import ExperimentEditorContainer from './experiment'; -import ToolchainEditorContainer from './toolchain'; -import PlotterEditorContainer from './plotter'; -import PlotterparameterEditorContainer from './plotterparameter'; - -type Props = { - // the match object from react-router - // used to find which object to render - match: any, - // the history object from react-router - // used to push new history to - history: any, - // gets the object based on the current URL - getEntityObject: () => BeatObject, - // gets the object's index # in the Redux array based on the current URL - getEntityIndex: () => number, - // updates the current object - updateFunc: (BeatObject) => any, - // the current BEAT entity being show - entity: BeatEntity, - // the absolute path to the user's prefix folder - prefix: string, -}; - -// 3 tabs so far: editor, docs, raw json -type Tab = '0' | '1' | '2'; - -type State = { - // which tab is active - activeTab: Tab, -}; - -// wrapper for editors -// doesnt really do much now besides the raw json tab -export class EntityDetail extends React.Component<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - activeTab: '0', - } - - switchToTab = (tab: Tab) => { - this.setState({ - activeTab: tab - }); - } - - saveChanges = (newObj: BeatObject) => { - this.props.updateFunc(newObj); - const put = genModuleApiFuncs(this.props.entity).put; - return put([newObj]); - } - - render () { - const name = this.props.match.params.name; - const obj = this.props.getEntityObject(); - const index = this.props.getEntityIndex(); - let expName; - if(this.props.entity === 'experiment'){ - const segs = name.split('/'); - const usern = segs.shift(); - const expn = segs.pop(); - const tcn = segs.join('/'); - expName = <span>{ usern }/<Link to={`/toolchain/${ tcn }`}>{ tcn }</Link>/{ expn }</span> - } - return ( - <Container> - <Row className='mb-1'> - <Col> - {/* title line (name & validation info) */} - <h4 className='text-center'> - <span style={{'textTransform': 'capitalize'}}> - { this.props.entity } - </span> - {' '} - <pre style={{display: 'inline'}}> - { expName || name } - </pre> - <ValidSchemaBadge entity={this.props.entity} obj={obj} /> - </h4> - {/* path line */} - <InputGroup> - <InputGroupAddon addonType='prepend'>Path:</InputGroupAddon> - <Input - readOnly - width='80' - value={`${ this.props.prefix }/${ pluralize(this.props.entity) }/${ name }`} - /> - </InputGroup> - </Col> - </Row> - <Row> - <Col sm='12'> - <Nav tabs className='nav-fill'> - <NavItem> - <NavLink - className={cn({ active: this.state.activeTab === '0' })} - onClick={() => this.switchToTab('0')} - > - Editor - </NavLink> - </NavItem> - <NavItem> - <NavLink - className={cn({ active: this.state.activeTab === '1' })} - onClick={() => this.switchToTab('1')} - > - Raw JSON - </NavLink> - </NavItem> - </Nav> - <TabContent activeTab={this.state.activeTab} className='mt-2'> - {/* Uses the appropriate editor, could probably be done nicer */} - <TabPane tabId='0'> - { - this.props.entity === 'algorithm' && - <AlgorithmEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'dataformat' && - <DataformatEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'library' && - <LibraryEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'database' && - <DatabaseEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'experiment' && - <ExperimentEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'toolchain' && - <ToolchainEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'plotter' && - <PlotterEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - { - this.props.entity === 'plotterparameter' && - <PlotterparameterEditorContainer - saveFunc={this.saveChanges} - index={index} - /> - } - </TabPane> - <TabPane tabId='1'> - <pre>{ JSON.stringify(obj, null, 4) }</pre> - </TabPane> - </TabContent> - </Col> - </Row> - </Container> - ); - } -} - -const mapStateToProps = (state, ownProps) => { - // which beat entity is currently active: 'algorithm', 'plotter', 'database', etc. - const entity = ownProps.match.params.entity; - // the name of the object ("atnt/1", "plot/isoroc/1", "user/tc/test/1/exp", etc.) - const name = ownProps.match.params.name; - const obj = { - // uses a selector based off the entity and finds the obj given the name - // if the obj doesnt exist (huge edge case) just return a default obj to not break everything - getEntityObject: (): BeatObject => Selectors[`${ entity }Get`](state).find(o => o.name === name) || getDefaultEntityObject(), - getEntityIndex: (): number => Selectors[`${ entity }Get`](state).findIndex(o => o.name === name), - entity, - prefix: Selectors.settingsGet(state).prefix, - }; - - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - dispatch(Actions[`${ ownProps.match.params.entity }Update`](ownProps.match.params.name, obj)); - ownProps.history.push(`/${ ownProps.match.params.entity }/${ obj.name }`); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(EntityDetail); diff --git a/conda/js/src/components/EntityHome.jsx b/conda/js/src/components/EntityHome.jsx deleted file mode 100644 index 49d8f97c..00000000 --- a/conda/js/src/components/EntityHome.jsx +++ /dev/null @@ -1,85 +0,0 @@ -// @flow -import React from 'react'; -import { - Container, - Row, - Col, - ListGroup, - ListGroupItem, - Button, - ButtonGroup, - Card, - CardHeader, - CardBody, -} from 'reactstrap'; - -import { - Switch, - Route, -} from 'react-router-dom'; - -import type { BeatEntity } from '@helpers/beat.js'; -import { pluralize } from '@helpers/beat.js'; - -import EntityListContainer from './EntityList.jsx'; -import NewEntityModal from './NewEntityModal.jsx'; -import EntityDetailContainer from './EntityDetail.jsx'; -import SearchBar from './SearchBar.jsx'; - -type Props = { - entity: BeatEntity, -}; - -type State = { - newOpen: boolean, -}; - -class EntityHome extends React.Component<Props, State> { - constructor(props: Props) { - super(props); - } - - state = { - newOpen: false, - } - - toggleNew = () => this.setState({ newOpen: !this.state.newOpen }); - - render () { - return ( - <Switch> - <Route exact path={'/:entity/:name+'} component={EntityDetailContainer} /> - <Route> - <Container> - <Row className='mb-3'> - <Col> - <div className='d-flex'> - <h3>{ pluralize(this.props.entity) }</h3> - <SearchBar - entity={this.props.entity} - /> - <div className='ml-auto'> - <Button outline color='success' onClick={this.toggleNew}>New</Button> - <NewEntityModal - toggle={this.toggleNew} - isOpen={this.state.newOpen} - entity={this.props.entity} - nameOrVersion={true} - /> - </div> - </div> - </Col> - </Row> - <Row> - <Col> - <EntityListContainer entity={this.props.entity} /> - </Col> - </Row> - </Container> - </Route> - </Switch> - ); - } -} - -export default EntityHome; diff --git a/conda/js/src/components/EntityList.jsx b/conda/js/src/components/EntityList.jsx deleted file mode 100644 index f804d3c3..00000000 --- a/conda/js/src/components/EntityList.jsx +++ /dev/null @@ -1,208 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - ListGroup, - ListGroupItem, - Button, - ButtonGroup, - Card, - CardHeader, - CardBody, - Badge, - Modal, ModalHeader, ModalBody, ModalFooter, -} from 'reactstrap'; - -import { - Route, - Link -} from 'react-router-dom'; - -import { connect } from 'react-redux'; - -import * as Selectors from '@store/selectors'; -import * as Actions from '@store/actions'; - -import { BEAT_ENTITIES, getTcFromExpName } from '@helpers/beat'; -import type { BeatEntity, BeatObject } from '@helpers/beat'; - -import ValidSchemaBadge from './ValidSchemaBadge.jsx'; - -import NewEntityModal from './NewEntityModal.jsx'; - -type ElProps = { - data: BeatObject, - entity: BeatEntity, - copyFunc: () => any, - deleteFunc: () => any, - versionFunc?: () => any, -}; - -const El = ({ data, entity, copyFunc, deleteFunc, versionFunc }: ElProps) => ( - <ListGroupItem className='d-flex align-items-center'> - <span> - <Link to={`/${ entity }/${ data.name }`}> - { data.name } - </Link> - <ValidSchemaBadge entity={entity} obj={data} /> - <small> { data.contents['description'] || data.contents['#description'] }</small> - </span> - - <div className='ml-auto'> - { versionFunc && <Button outline color='success' onClick={() => versionFunc()}>New Version</Button> }{' '} - <Button outline color='success' onClick={() => copyFunc()}>Clone</Button>{' '} - <Button outline color='danger' onClick={() => deleteFunc()}>Delete</Button> - </div> - </ListGroupItem> -); - -type Props = { - entity: BeatEntity, - data: BeatObject[], - // deleting toolchains should show the exps that will be deleted in the popup - experiments: BeatObject[], - deleteFunc: (BeatObject, ?BeatEntity) => () => any, -}; - -type State = { - newModalOpen: boolean, - copyObj: {}, - deleteModalData: false | BeatObject, - nameOrVersion: boolean, -}; - -export class EntityList extends React.Component<Props, State> { - constructor (props: Props) { - super(props); - } - - state = { - newModalOpen: false, - copyObj: {}, - deleteModalData: false, - nameOrVersion: false, - } - - toggleDeleteModal = (e: false | BeatObject = false) => this.setState({ deleteModalData: e || false }); - - toggleModal = () => this.setState({ newModalOpen: !this.state.newModalOpen }); - - copyFunc = (obj: BeatObject) => this.setState({ copyObj: obj, newModalOpen: true, nameOrVersion: true }); - - versionFunc = (obj: BeatObject) => this.setState({ copyObj: obj, newModalOpen: true, nameOrVersion: false }); - - render () { - // name to be deleted if any - const deleteName = this.state.deleteModalData ? this.state.deleteModalData.name : ''; - - // need to find which objects can be versioned (which objects have no newer versions) - let versionableNames; - if(this.props.entity === 'experiment') - versionableNames = []; - else { - const getNameAndVersion = name => { - const segs = name.split('/'); - const n = segs.slice(0, -1).join('/'); - const version = Number.parseInt(segs[segs.length - 1]); - return [n, version]; - }; - // sort the names so that all versions of an object are together, - // and the versions are sorted from first to laste - const sortedNames = this.props.data.map(d => d.name).sort(); - const nameAndVersions = sortedNames.map(n => getNameAndVersion(n)); - // find the complete names of the highest versions of each obj - // since we sorted we just find the last version of each obj - versionableNames = sortedNames.filter((n, i) => { - if(i === sortedNames.length - 1) - return true; - if(nameAndVersions[i + 1][0] === nameAndVersions[i][0]) - return false; - return true; - }); - } - - return ( - <React.Fragment> - <ListGroup> - <NewEntityModal - toggle={this.toggleModal} - isOpen={this.state.newModalOpen} - entity={this.props.entity} - copyObj={this.state.copyObj} - nameOrVersion={this.state.nameOrVersion} - /> - { this.props.data.map((d, i) => - <El - key={i} - data={d} - entity={this.props.entity} - copyFunc={() => this.copyFunc(d)} - versionFunc={versionableNames.includes(d.name) ? () => this.versionFunc(d) : undefined} - deleteFunc={() => this.toggleDeleteModal(d)} - />) - } - </ListGroup> - <Modal - toggle={() => this.toggleDeleteModal()} - isOpen={this.state.deleteModalData !== false} - > - <ModalHeader toggle={() => this.toggleDeleteModal()}>Confirm Deletion</ModalHeader> - <ModalBody> - Are you sure you want to permanently delete{' '} - <pre className='preInline'> - { deleteName } - </pre>? - This will delete the object from your BEAT prefix as well as the web app. - { - this.props.entity === 'toolchain' && - <React.Fragment> - <p>Deleting this toolchain will also delete the following experiments that depend on it:</p> - <ListGroup> - { - this.props.experiments - .filter(e => getTcFromExpName(e.name) === deleteName) - .map((e, i) => <ListGroupItem key={i}>{ e.name }</ListGroupItem>) - } - </ListGroup> - </React.Fragment> - } - </ModalBody> - <ModalFooter> - <Button color='danger' - onClick={async () => { - if(this.state.deleteModalData){ - if(this.props.entity === 'toolchain'){ - await Promise.all( - this.props.experiments - .filter(e => getTcFromExpName(e.name) === deleteName) - .map((e) => this.props.deleteFunc(e, 'experiment')) - ); - } - await this.props.deleteFunc(this.state.deleteModalData); - } - this.toggleDeleteModal(); - }} - >Delete</Button> - <Button color='secondary' - autoFocus - onClick={() => this.toggleDeleteModal()} - >Cancel</Button> - </ModalFooter> - </Modal> - </React.Fragment> - ); - } -} - -const mapStateToProps = (state, ownProps) => ({ - data: Selectors[`${ ownProps.entity }Get`](state), - experiments: Selectors.experimentGet(state), -}); - -const mapDispatchToProps = (dispatch, ownProps) => ({ - deleteFunc: (obj, entity = ownProps.entity) => dispatch(Actions.deleteObject(entity, obj)()), -}); - -export default connect(mapStateToProps, mapDispatchToProps)(EntityList); diff --git a/conda/js/src/components/EntityTemplateGenerationButton.jsx b/conda/js/src/components/EntityTemplateGenerationButton.jsx deleted file mode 100644 index e74ae2e6..00000000 --- a/conda/js/src/components/EntityTemplateGenerationButton.jsx +++ /dev/null @@ -1,139 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Button, - Modal, - ModalBody, - ModalHeader, - ModalFooter, -} from 'reactstrap'; -import { - generateDatabaseTemplate, - generateAlgorithmTemplate, - generateLibraryTemplate, - generatePlotterTemplate, -} from '@helpers/api'; -import { copyObj } from '@helpers'; -import type { BeatEntity, BeatObject } from '@helpers/beat'; -import { pluralize } from '@helpers/beat'; - -type Props = { - data: BeatObject, - entity: BeatEntity, -}; - -type State = { - infoOpen: boolean, - confirmOpen: boolean, -}; - -export default class EntityTemplateGenerationButton extends React.Component<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - infoOpen: false, - confirmOpen: false, - } - - toggleInfo = (val: boolean = !this.state.infoOpen) => { - this.setState({ infoOpen: val }); - } - - toggleConfirm = (val: boolean = !this.state.confirmOpen) => { - this.setState({ confirmOpen: val }); - } - - click = async (confirm: boolean) => { - let uses; - let res; - switch(this.props.entity){ - case('database'): - if(!this.props.data.contents.protocols) - throw new Error(`Bad database object, no protocols field: ${ this.props.data.contents }`); - // need to find all the views - let views = Array.from(new Set( - this.props.data.contents.protocols - .map(p => p.sets.map(s => s.view)) - .reduce((a, vs) => [...a, ...vs], []) - )); - res = await generateDatabaseTemplate(this.props.data.name, confirm, views); - break; - case('algorithm'): - // find if the alg has parameters - // find the used libraries - if(!this.props.data.contents.parameters) - throw new Error(`Bad alg object, no params field: ${ this.props.data.contents }`); - res = await generateAlgorithmTemplate(this.props.data.name, confirm, this.props.data.contents); - break; - case('library'): - // find the used libraries - uses = copyObj(this.props.data.contents.uses); - res = await generateLibraryTemplate(this.props.data.name, confirm, uses); - break; - case('plotter'): - // find the used libraries and parameters - uses = copyObj(this.props.data.contents.parameters); - res = await generatePlotterTemplate(this.props.data.name, confirm, this.props.data.contents); - break; - default: - throw new Error(`Cannot generate template for entity "${ this.props.entity }"`); - } - - // inspect the result - if(res === false){ - // the python file already existed, ask for confirmation to overwrite - this.toggleConfirm(true); - } else { - // its fine - this.toggleInfo(true); - } - } - - render = () => { - return ( - <React.Fragment> - <Button outline - color='danger' - className='mx-auto' - onClick={e => this.click(false)} - title={`Some types of objects (databases, algorithms, and libraries) need Python files to be used in experiments. You may generate a template Python file to provide a starting point for development.`} - > - Generate Python File - </Button> - <br /> - <Modal color='info' isOpen={this.state.infoOpen} toggle={e => this.toggleInfo(false)}> - <ModalHeader toggle={e => this.toggleInfo(false)}> - Information about the template file - </ModalHeader> - <ModalBody> - <p> - You have generated a template Python file to provide a starting point for development for this object. - </p> - The template { this.props.entity } Python file for this object can be found in the path: - <pre className='preInline'> - /your/beat/prefix/{ pluralize(this.props.entity) }/{ this.props.data.name }.py - </pre> - </ModalBody> - </Modal> - <Modal color='info' isOpen={this.state.confirmOpen} toggle={e => this.toggleConfirm(false)}> - <ModalHeader toggle={e => this.toggleConfirm(false)}> - Confirm Overwrite - </ModalHeader> - <ModalBody> - The generated Python file will overwrite the Python file that already exists at: - <pre className='preInline'> - /your/beat/prefix/{ pluralize(this.props.entity) }/{ this.props.data.name }.py - </pre> - Are you sure you want to overwrite this file? - </ModalBody> - <ModalFooter> - <Button color="primary" onClick={e => { this.toggleConfirm(false); this.click(true); }}>Overwrite</Button>{' '} - <Button color="secondary" onClick={e => this.toggleConfirm(false)}>Cancel</Button> - </ModalFooter> - </Modal> - </React.Fragment> - ); - } -}; diff --git a/conda/js/src/components/HomeContent.jsx b/conda/js/src/components/HomeContent.jsx deleted file mode 100644 index 7a846beb..00000000 --- a/conda/js/src/components/HomeContent.jsx +++ /dev/null @@ -1,41 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, -} from 'reactstrap'; - -const HomeContent = () => ( - <Container> - <Row> - <Col sm='12'> - <p> - Welcome to the BEAT editor! - </p> - <p> - Please make sure your prefix is set to a path to a valid BEAT prefix (usually created by the {' '}<a href='https://gitlab.idiap.ch/beat/beat.cmdline'>BEAT cli</a>). - </p> - <h4>Platform overview</h4> - <p> - There are eight different primary entities within the BEAT platform: - </p> - <ul> - <li>Databases</li> - <li>Libraries</li> - <li>Dataformats</li> - <li>Algorithms</li> - <li>Toolchains</li> - <li>Experiments</li> - <li>Plotters</li> - <li>Plotterparameters</li> - </ul> - <p> - This web app edits the metadata of objects of all seven of these entities, but does not support editing code or documentation (e.g. editing Python or RST files). - </p> - </Col> - </Row> - </Container> -); - -export default HomeContent; diff --git a/conda/js/src/components/InfoTooltip.jsx b/conda/js/src/components/InfoTooltip.jsx deleted file mode 100644 index 36ba6805..00000000 --- a/conda/js/src/components/InfoTooltip.jsx +++ /dev/null @@ -1,30 +0,0 @@ -// @flow -import * as React from 'react'; -import { - UncontrolledTooltip, -} from 'reactstrap'; - -type Props = { - id: string, - info: string, - children: React.Node, -}; - -export class InfoTooltip extends React.PureComponent<Props> { - constructor(props: Props) { - super(props); - } - - target = null - - render = () => ( - <React.Fragment> - <span id={this.props.id} ref={el => this.target = el }>{ this.props.children }<sup>ℹ</sup></span> - <UncontrolledTooltip target={() => this.target}> - { this.props.info } - </UncontrolledTooltip> - </React.Fragment> - ); -} - -export default InfoTooltip; diff --git a/conda/js/src/components/MainContent.jsx b/conda/js/src/components/MainContent.jsx deleted file mode 100644 index 05159886..00000000 --- a/conda/js/src/components/MainContent.jsx +++ /dev/null @@ -1,27 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, -} from 'reactstrap'; - - -import { - Route, - Switch, -} from 'react-router-dom'; - -import EntityHome from './EntityHome.jsx'; - -type Props = { - match: any, -}; - -const MainContent = ({ match }: Props) => ( - <div> - <EntityHome entity={match.params.entity} /> - </div> -); - -export default MainContent; diff --git a/conda/js/src/components/MainNav.jsx b/conda/js/src/components/MainNav.jsx deleted file mode 100644 index ae70bbb3..00000000 --- a/conda/js/src/components/MainNav.jsx +++ /dev/null @@ -1,156 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Button, - Navbar, - NavbarBrand, - Nav, - NavItem, - NavLink, -} from 'reactstrap'; - -import { - Route, - Link, - NavLink as RLink, -} from 'react-router-dom'; - -import { connect } from 'react-redux'; - -import * as Selectors from '@store/selectors'; -import { clearUnsaved } from '@store/actions'; - -import { BEAT_ENTITIES, pluralize } from '@helpers/beat'; -import { genModuleApiFuncs } from '@helpers/api'; -import type { BeatEntity, BeatSettings } from '@helpers/beat'; - -import Settings from './Settings.jsx'; - -type Props = { - database: BeatEntity[], - library: BeatEntity[], - dataformat: BeatEntity[], - algorithm: BeatEntity[], - toolchain: BeatEntity[], - experiment: BeatEntity[], - plotter: BeatEntity[], - plotterparameter: BeatEntity[], - settings: BeatSettings, - unsavedChanges: boolean, - clearUnsaved: () => any, -}; - -type State = { - settingsOpen: boolean, - isSaving: boolean, -}; - -const saveAll = async (allLists: Props) => { - await Promise.all( - BEAT_ENTITIES - //.filter(e => Array.isArray(allLists[e])) - .map(e => { - const put = genModuleApiFuncs(e).put; - return put(allLists[e]); - }) - ); -}; - -export class MainNav extends React.Component<Props, State> { - constructor(props: Props) { - super(props); - } - - state = { - settingsOpen: false, - isSaving: false, - } - - toggle = () => { - this.setState({ - settingsOpen: !this.state.settingsOpen - }); - } - - saveAllData = async () => { - try { - this.setState({ - isSaving: true - }); - const res = await saveAll(this.props); - this.setState({ - isSaving: false - }); - this.props.clearUnsaved(); - } catch (e) { - - } - } - - render() { - return ( - <Navbar color="faded" light expand> - <NavbarBrand href="/#/">beat.editor</NavbarBrand> - <Nav className="mr-auto" navbar> - { - BEAT_ENTITIES - .map((e, i) => { - return ( - <NavItem key={i}> - <NavLink tag={RLink} to={`/${ (e: any) }`}>{ pluralize(e) }</NavLink> - </NavItem> - ); - }) - } - </Nav> - <Nav className="ml-auto" navbar> - { - // right now we have no settings so there's no need to offer the user this modal - /* - <NavItem className='mr-1'> - <Button outline onClick={this.toggle}>Settings</Button> - <Settings - isOpen={this.state.settingsOpen} - toggle={this.toggle} - /> - </NavItem> - */ - } - { - // Dont need a 'save all' button anymore - /* - <NavItem> - <Button outline color={this.props.unsavedChanges ? 'primary' : 'secondary'} - disabled={this.state.isSaving} - onClick={this.saveAllData} - title={this.props.unsavedChanges ? 'There may be unsaved changes on the web app. Click to save changes.' : 'There are no changes detected.'} - > - Save All - </Button> - </NavItem> - */ - } - </Nav> - </Navbar> - ); - } -} - -const mapStateToProps = state => ({ - database: Selectors.databaseGet(state), - library: Selectors.libraryGet(state), - dataformat: Selectors.dataformatGet(state), - algorithm: Selectors.algorithmGet(state), - toolchain: Selectors.toolchainGet(state), - experiment: Selectors.experimentGet(state), - plotter: Selectors.plotterGet(state), - plotterparameter: Selectors.plotterparameterGet(state), - settings: Selectors.settingsGet(state), - unsavedChanges: Selectors.unsavedGet(state), -}); - -const mapDispatchToProps = (dispatch, ownProps) => ({ - clearUnsaved: () => dispatch(clearUnsaved()), -}); - -export default connect(mapStateToProps, mapDispatchToProps)(MainNav); diff --git a/conda/js/src/components/NewEntityModal.jsx b/conda/js/src/components/NewEntityModal.jsx deleted file mode 100644 index a1ce167a..00000000 --- a/conda/js/src/components/NewEntityModal.jsx +++ /dev/null @@ -1,537 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Button, - Form, FormGroup, Label, Input, - Modal, ModalHeader, ModalBody, ModalFooter, - FormText, - Col, - Badge, - Row, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import { generateNewKey } from '@helpers'; -import { BEAT_ENTITIES, nameValidator, nameSegmentsForEntity, getTcFromExpName } from '@helpers/beat'; -import type { BeatEntity, BeatObject } from '@helpers/beat'; -import CacheInput from './CacheInput.jsx'; - -import * as Selectors from '@store/selectors.js'; -import * as Actions from '@store/actions'; - -import { getValidDatabaseObj } from '@helpers/beat'; -import { getValidDataformatObj } from '@helpers/beat'; -import { getValidLibraryObj } from '@helpers/beat'; -import { getValidAlgorithmObj } from '@helpers/beat'; -import { getValidToolchainObj } from '@helpers/beat'; -import { getValidExperimentObj } from '@helpers/beat'; -import { getValidPlotterObj } from '@helpers/beat'; -import { getValidPlotterparameterObj } from '@helpers/beat'; - -const getObjs = { - database: getValidDatabaseObj, - dataformat: getValidDataformatObj, - library: getValidLibraryObj, - algorithm: getValidAlgorithmObj, - toolchain: getValidToolchainObj, - experiment: getValidExperimentObj, - plotter: getValidPlotterObj, - plotterparameter: getValidPlotterparameterObj, -}; - -type Props = { - isOpen: boolean, - toggle: () => mixed, - entity: BeatEntity, - copyObj?: BeatObject, - create: (string, BeatObject[], BeatObject[], ?BeatObject) => mixed, - data: BeatObject[], - toolchains: BeatObject[], - algorithms: BeatObject[], - // if true, the name is being changed but the version is stuck at 1 (for copying or creating new) - // if false, the name is stuck and the version is incremented (for making a new version) - nameOrVersion: boolean, -}; - -type State = { - nameSegs: string[], - numSegs: number, -}; - -const getStartNameSegs = (copyObj?: BeatObject, existingNames: string[], entity: BeatEntity, nameOrVersion: boolean) => { - const autoVersion = entity !== 'experiment'; - if(copyObj){ - const newName = copyObj.name || ''; - const segs = newName.split('/'); - if(autoVersion){ - const version = Number.parseInt(segs[segs.length - 1]); - segs[segs.length - 1] = `${ nameOrVersion ? 1 : version + 1 }`; - } - return segs; - } else { - const len = nameSegmentsForEntity(entity); - return Array.apply(null, Array(len)).map((u, i) => i === len - 1 && autoVersion ? '1' : ''); - } -}; - -export class NewEntityModal extends React.Component<Props, State> { - constructor(props: Props) { - super(props); - } - - state = { - nameSegs: getStartNameSegs(this.props.copyObj, this.props.data.map(d => d.name), this.props.entity, this.props.nameOrVersion), - numSegs: nameSegmentsForEntity(this.props.entity), - } - - componentDidUpdate = (prevProps: Props) => { - if(this.props !== prevProps){ - this.setState({ - nameSegs: getStartNameSegs(this.props.copyObj, this.props.data.map(d => d.name), this.props.entity, this.props.nameOrVersion), - numSegs: nameSegmentsForEntity(this.props.entity), - }); - } - } - - titleStr = () => `New ${ this.props.entity }: "${ this.getNameString() }"`; - - submit = (name: string) => { - if(!this.nameIsValid()) - return; - - this.props.create(name, this.props.algorithms, this.props.toolchains, this.props.copyObj); - this.props.toggle(); - } - - getNameString = (lastSeg?: string) => { - let segs = [...this.state.nameSegs]; - if(lastSeg) - segs[segs.length - 1] = lastSeg; - return segs.join('/'); - } - - validatorFunc = () => nameValidator(this.props.entity, this.props.data.map(d => d.name)); - - nameIsValid = (str: string = this.getNameString()): true | React.Node => { - const err = `Please provide a unique and valid ${ this.props.entity } name`; - ; - const isValid = this.validatorFunc()(str); - return isValid || err; - } - - handleInput = (...segs: Array<?string>) => { - const newSegs = Array.apply(null, Array(this.state.numSegs)) - .map((u, i) => segs[i] || this.state.nameSegs[i] || ''); - this.setState({ - nameSegs: newSegs, - }); - } - - render () { - const nameValidity = this.nameIsValid(); - const nameOrVersion = this.props.nameOrVersion; - return ( - <Modal isOpen={this.props.isOpen} toggle={this.props.toggle} size='lg'> - <ModalHeader toggle={this.props.toggle}> - { this.titleStr() } - {' '} - <Badge - color={`${ nameValidity === true ? 'success' : 'danger' }`} - title={nameValidity === true ? undefined : nameValidity} - > - {`${ nameValidity === true ? 'Valid Name' : 'Invalid Name' }`} - </Badge> - </ModalHeader> - <ModalBody> - <Form> - <FormGroup row> - {/* database */} - { this.props.entity === 'database' && - <React.Fragment> - <Col sm={6}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New database name...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={6}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Database version...`} - value={this.state.nameSegs[1]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - {/* library */} - { this.props.entity === 'library' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Library user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New library name...`} - value={this.state.nameSegs[1]} - onChange={(e) => this.handleInput(undefined, e.target.value)} - fieldTest - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Library version...`} - value={this.state.nameSegs[2]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - {/* dataformat */} - { this.props.entity === 'dataformat' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Dataformat user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New dataformat name...`} - value={this.state.nameSegs[1]} - onChange={(e) => this.handleInput(undefined, e.target.value)} - fieldTest - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Dataformat version...`} - value={this.state.nameSegs[2]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - {/* algorithm */} - { this.props.entity === 'algorithm' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Algorithm user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New algorithm name...`} - value={this.state.nameSegs[1]} - onChange={(e) => this.handleInput(undefined, e.target.value)} - fieldTest - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Algorithm version...`} - value={this.state.nameSegs[2]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - {/* toolchain */} - { this.props.entity === 'toolchain' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Toolchain user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New toolchain name...`} - value={this.state.nameSegs[1]} - onChange={(e) => this.handleInput(undefined, e.target.value)} - fieldTest - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Toolchain version...`} - value={this.state.nameSegs[2]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - {/* experiment */} - { this.props.entity === 'experiment' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Experiment user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - /> - </Col> - <Col sm={4}> - <Label>Toolchain</Label> - <Input - type='select' - name='toolchain' - placeholder={`Experiment toolchain name...`} - value={this.state.nameSegs.slice(1, 4).filter(s => s !== '').join('/')} - onChange={(e) => this.handleInput(undefined, ...e.target.value.split('/'))} - > - <option value=''>Toolchain...</option> - { - this.props.toolchains.map((tc, i) => - <option key={i} value={tc.name}>{ tc.name}</option> - ) - } - </Input> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Experiment name...`} - value={this.state.nameSegs[4]} - onChange={(e) => this.handleInput(undefined, undefined, undefined, undefined, e.target.value)} - fieldTest - autoFocus - /> - </Col> - </React.Fragment> - } - {/* plotter */} - { this.props.entity === 'plotter' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Plotter user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New plotter name...`} - value={this.state.nameSegs[1]} - onChange={(e) => this.handleInput(undefined, e.target.value)} - fieldTest - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Plotter version...`} - value={this.state.nameSegs[2]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - {/* plotterparameter */} - { this.props.entity === 'plotterparameter' && - <React.Fragment> - <Col sm={4}> - <Label>User</Label> - <CacheInput - delay={0} - type='text' - name='user' - placeholder={`Plotterparameter user...`} - value={this.state.nameSegs[0]} - onChange={(e) => this.handleInput(e.target.value)} - fieldTest - autoFocus - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Name</Label> - <CacheInput - delay={0} - type='text' - name='name' - placeholder={`New plotterparameter name...`} - value={this.state.nameSegs[1]} - onChange={(e) => this.handleInput(undefined, e.target.value)} - fieldTest - disabled={!nameOrVersion} - /> - </Col> - <Col sm={4}> - <Label>Version</Label> - <CacheInput - delay={0} - type='text' - name='version' - placeholder={`Plotterparameter version...`} - value={this.state.nameSegs[2]} - validateFunc={(str) => `${ Number.parseInt(str) }` === str} - onChange={(e) => this.handleInput(undefined, undefined, e.target.value)} - disabled - /> - </Col> - </React.Fragment> - } - </FormGroup> - </Form> - </ModalBody> - <ModalFooter> - <Button - color="primary" - disabled={nameValidity !== true} - onClick={() => this.submit(this.getNameString())} - >Create</Button>{' '} - <Button color="secondary" onClick={this.props.toggle}>Cancel</Button> - </ModalFooter> - </Modal> - ); - } -} - -const mapStateToProps = (state, ownProps) => ({ - data: Selectors[`${ ownProps.entity }Get`](state), - toolchains: Selectors.toolchainGet(state), - algorithms: Selectors.algorithmGet(state), - plotters: Selectors.plotterGet(state), -}); - -const mapDispatchToProps = (dispatch, ownProps) => ({ - create: (name: string, algorithms: BeatObject[], toolchains: BeatObject[], copyObj?: any = {}) => { - let newObj; - if(ownProps.entity === 'experiment'){ - const tcName = getTcFromExpName(name); - const tc = toolchains.find(o => o.name === tcName); - newObj = getObjs[ownProps.entity]({ ...copyObj, name }, tc, algorithms); - } else { - newObj = getObjs[ownProps.entity]({ ...copyObj, name }); - } - - return dispatch(Actions.createObject(ownProps.entity, newObj, copyObj.name)()); - } -}); - -export default connect(mapStateToProps, mapDispatchToProps)(NewEntityModal); diff --git a/conda/js/src/components/NewEntityModal.spec.jsx b/conda/js/src/components/NewEntityModal.spec.jsx deleted file mode 100644 index ac8f5ba9..00000000 --- a/conda/js/src/components/NewEntityModal.spec.jsx +++ /dev/null @@ -1,447 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; - -import { NewEntityModal as C } from './NewEntityModal.jsx'; -import test_dbs from '@test/test_dbs.json'; -import test_dfs from '@test/test_dfs.json'; -import test_libs from '@test/test_libs.json'; -import test_algs from '@test/test_algs.json'; -import test_tcs from '@test/test_tcs.json'; -import test_exps from '@test/test_exps.json'; - -type Props = { - isOpen: boolean, - toggle: () => mixed, - entity: BeatEntity, - copyObj?: BeatObject, - create: (string, BeatObject[], BeatObject[], ?BeatObject) => mixed, - data: BeatObject[], - toolchains: BeatObject[], - algorithms: BeatObject[], - // if true, the name is being changed but the version is stuck at 1 (for copying or creating new) - // if false, the name is stuck and the version is incremented (for making a new version) - nameOrVersion: boolean, -}; - -describe('<NewEntityModal />', () => { - let wrapper; - const entities = [ - 'database', - 'dataformat', - 'library', - 'algorithm', - 'toolchain', - 'experiment', - 'plotter', - 'plotterparameter', - ]; - const isOpen = true; - const create = sinon.spy(); - const toggle = sinon.spy(); - - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - it(`has 9 required props and is missing 1 optional`, () => { - const entity = 'database'; - const nameOrVersion = true; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - /> - ); - - expect(wrapper).to.have.props( - ['isOpen', 'toggle', 'create', 'entity', 'data', 'algorithms', 'toolchains', 'nameOrVersion'] - ).deep.equal( - [isOpen, toggle, create, entity, test_dbs, test_algs, test_tcs, nameOrVersion] - ); - - expect(wrapper).to.not.have.props( - ['copyObj'] - ); - }); - - it(`has all 10 props`, () => { - const entity = 'database'; - const nameOrVersion = true; - const copyObj = test_dbs[0]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper).to.have.props( - ['isOpen', 'toggle', 'create', 'entity', 'data', 'algorithms', 'toolchains', 'nameOrVersion', 'copyObj'] - ).deep.equal( - [isOpen, toggle, create, entity, test_dbs, test_algs, test_tcs, nameOrVersion, copyObj] - ); - }); - - describe('for databases', () => { - const entity = 'database'; - it(`properly handles creating a new object`, () => { - const nameOrVersion = true; - const copyObj = undefined; - const newNameSegs = ['', `1`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(2); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(false); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - }); - - it(`properly handles copying`, () => { - const nameOrVersion = true; - const copyObj = test_dbs[0]; - const oldNameSegs = copyObj.name.split('/'); - const copyVersion = Number.parseInt(oldNameSegs.slice(-1)[0]); - const newNameSegs = [...oldNameSegs.slice(0, -1), `1`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(2); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(false); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - }); - - it(`properly handles creating a new version`, () => { - const nameOrVersion = false; - const copyObj = test_dbs[0]; - const oldNameSegs = copyObj.name.split('/'); - const copyVersion = Number.parseInt(oldNameSegs.slice(-1)[0]); - const newNameSegs = [...oldNameSegs.slice(0, -1), `${ copyVersion + 1 }`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(2); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(true); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - }); - }); - - describe('for databases', () => { - const entity = 'database'; - it(`properly handles creating a new object`, () => { - const nameOrVersion = true; - const copyObj = undefined; - const newNameSegs = ['', `1`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(2); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(false); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - }); - - it(`properly handles copying`, () => { - const nameOrVersion = true; - const copyObj = test_dbs[0]; - const oldNameSegs = copyObj.name.split('/'); - const copyVersion = Number.parseInt(oldNameSegs.slice(-1)[0]); - const newNameSegs = [...oldNameSegs.slice(0, -1), `1`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(2); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(false); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - }); - - it(`properly handles creating a new version`, () => { - const nameOrVersion = false; - const copyObj = test_dbs[0]; - const oldNameSegs = copyObj.name.split('/'); - const copyVersion = Number.parseInt(oldNameSegs.slice(-1)[0]); - const newNameSegs = [...oldNameSegs.slice(0, -1), `${ copyVersion + 1 }`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(2); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(true); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - }); - }); - - describe('for algorithms', () => { - const entity = 'algorithm'; - it(`properly handles creating a new object`, () => { - const nameOrVersion = true; - const copyObj = undefined; - const newNameSegs = ['', '', `1`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_algs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(3); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(3); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(false); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(false); - expect(inputs.get(2).props.value).to.equal(newNameSegs[2]); - expect(inputs.get(2).props.disabled).to.equal(true); - }); - - it(`properly handles copying`, () => { - const nameOrVersion = true; - const copyObj = test_algs[0]; - const oldNameSegs = copyObj.name.split('/'); - const copyVersion = Number.parseInt(oldNameSegs.slice(-1)[0]); - const newNameSegs = [...oldNameSegs.slice(0, -1), `1`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(3); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(3); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(false); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(false); - expect(inputs.get(2).props.value).to.equal(newNameSegs[2]); - expect(inputs.get(2).props.disabled).to.equal(true); - }); - - it(`properly handles creating a new version`, () => { - const nameOrVersion = false; - const copyObj = test_algs[0]; - const oldNameSegs = copyObj.name.split('/'); - const copyVersion = Number.parseInt(oldNameSegs.slice(-1)[0]); - const newNameSegs = [...oldNameSegs.slice(0, -1), `${ copyVersion + 1 }`]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_dbs} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(3); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - expect(inputs).to.have.length(3); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.equal(true); - expect(inputs.get(1).props.value).to.equal(newNameSegs[1]); - expect(inputs.get(1).props.disabled).to.equal(true); - expect(inputs.get(2).props.value).to.equal(newNameSegs[2]); - expect(inputs.get(2).props.disabled).to.equal(true); - }); - }); - - describe('for experiments', () => { - const entity = 'experiment'; - it(`properly handles creating a new object`, () => { - const nameOrVersion = true; - const copyObj = undefined; - const newNameSegs = ['', '', '', '', '']; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_exps} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(5); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - const select = wrapper.find('select'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.be.undefined; - expect(select.get(0).props.value).to.equal(''); - expect(select.get(0).props.disabled).to.be.undefined; - expect(inputs.get(1).props.value).to.equal(newNameSegs[4]); - expect(inputs.get(1).props.disabled).to.be.undefined; - }); - - it(`properly handles copying`, () => { - const nameOrVersion = true; - const copyObj = test_exps[0]; - const oldNameSegs = copyObj.name.split('/'); - const newNameSegs = [...oldNameSegs]; - wrapper = mount( - <C - isOpen={isOpen} - toggle={toggle} - create={create} - entity={entity} - data={test_exps} - algorithms={test_algs} - toolchains={test_tcs} - nameOrVersion={nameOrVersion} - copyObj={copyObj} - /> - ); - - expect(wrapper.state('numSegs')).to.equal(5); - expect(wrapper.state('nameSegs')).to.deep.equal(newNameSegs); - const inputs = wrapper.find('input'); - const select = wrapper.find('select'); - expect(inputs).to.have.length(2); - expect(inputs.get(0).props.value).to.equal(newNameSegs[0]); - expect(inputs.get(0).props.disabled).to.be.undefined; - expect(select.get(0).props.value).to.equal(newNameSegs.slice(1, 4).join('/')); - expect(select.get(0).props.disabled).to.be.undefined; - expect(inputs.get(1).props.value).to.equal(newNameSegs[4]); - expect(inputs.get(1).props.disabled).to.be.undefined; - }); - }); -}); diff --git a/conda/js/src/components/ParameterConsume.jsx b/conda/js/src/components/ParameterConsume.jsx deleted file mode 100644 index 128b6d9b..00000000 --- a/conda/js/src/components/ParameterConsume.jsx +++ /dev/null @@ -1,88 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Label, Input, -} from 'reactstrap'; - -import { expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat'; -import type { ParameterValue } from '@helpers/beat'; - -type Props = { - parameter: any, - updateFunc: (ParameterValue) => any, - currVal?: ParameterValue, -}; - -// given a parameter obj, its current value, and an update function, -// return an input for the specific type of parameter -const ParameterConsume = ({ parameter, updateFunc, currVal }: Props) => { - if((parameter === null || parameter === undefined) || !parameter.hasOwnProperty('type')) - return ''; - - const parseVal = (v: ParameterValue): ParameterValue => { - if(v === true || v === false) - return v; - if(parameter.type.includes('float')) - return Number.parseFloat(`${ v }`); - if(parameter.type.includes('int')) - return Number.parseInt(`${ v }`); - return v; - }; - - const pVal = currVal === undefined ? getDefaultParameterValue(parameter) : currVal; - if(parameter.hasOwnProperty('choice')) - return ( - <Input - type='select' - className='custom-select' - value={pVal} - onChange={e => updateFunc(parseVal(e.target.value))} - > - { parameter.choice.map((c, i) => <option key={i} value={c}>{c}</option>) } - </Input> - ); - if(parameter.hasOwnProperty('range')) - return ( - <Input - type='number' - min={parameter.range[0]} - max={parameter.range[1]} - value={pVal} - onChange={e => updateFunc(parseVal(e.target.value))} - /> - ); - if(parameter.type === 'bool') - return ( - <Label> - <Input - className='ml-0' - type='checkbox' - checked={pVal} - onChange={e => updateFunc(parseVal(e.target.checked))} - /> - </Label> - ); - if(parameter.type === 'string') - return ( - <Input - type='text' - value={pVal} - onChange={e => updateFunc(parseVal(e.target.value))} - /> - ); - else { - const step = parameter.type.includes('float') ? 'any' : 1; - return ( - <Input - type='number' - min={-1000000} - max={1000000} - step={step} - value={pVal} - onChange={e => updateFunc(parseVal(e.target.value))} - /> - ); - } -}; - -export default ParameterConsume; diff --git a/conda/js/src/components/ParameterCreate.jsx b/conda/js/src/components/ParameterCreate.jsx deleted file mode 100644 index 7ae95a89..00000000 --- a/conda/js/src/components/ParameterCreate.jsx +++ /dev/null @@ -1,381 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Row, - Col, - Button, - FormGroup, - Label, Input, - UncontrolledDropdown, DropdownToggle, DropdownMenu, - InputGroup, InputGroupAddon, -} from 'reactstrap'; - -import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES } from '@helpers/beat'; - -import TypedField from './TypedField.jsx'; - -type Props = { - name: string, - param: any, - params: any[], - updateParameter: (name: string | null, parameter: any | null, oldName: ?string) => any, -}; - -type State = { - choiceCache: string -}; - -export default class ParameterCreate extends React.Component<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - choiceCache: '', - } - - shouldComponentUpdate = (nextProps: Props, nextState: State) => { - // basically PureComponent but not checking updateParameter func which wont change by itself - // props check - if(nextProps.name !== this.props.name || nextProps.param !== this.props.param || nextProps.params !== this.props.params) - return true; - // state check - if(nextState.choiceCache !== this.state.choiceCache) - return true; - return false; - } - - render = () => { - const name = this.props.name; - const param = this.props.param; - const params = this.props.params; - const updateParameter = this.props.updateParameter; - - let new_param = false; - if (param.type == 'bool') - { - if(typeof(param.default) == 'string') - { - new_param = true; - } - else - { - new_param = false; - } - } - - return ( - <React.Fragment> - <TypedField - placeholder='Parameter name...' - name={name} - type={param.type} - types={BUILTIN_TYPES.filter(d => !d.startsWith('complex'))} - existingFields={params.map(([n, v]) => n)} - nameUpdateFunc={str => updateParameter(str, param, name)} - typeUpdateFunc={(str) => { - const newParam = { - ...param, - type: str - }; - - switch(newParam.type){ - case 'string': - delete newParam['range']; - break; - case 'bool': - delete newParam['range']; - delete newParam['choice']; - break; - default: - break; - } - - updateParameter(name, newParam); - }} - deleteFunc={() => { - updateParameter(null, null, name); - }} - - > - <Col> - <Input - type='text' - placeholder='Description' - value={param[name] || param.description || ''} - onChange={(e) => updateParameter(name, { - ...param, - description: e.target.value - })} - /> - </Col> - </TypedField> - <FormGroup row className='ml-3'> - { - param.type !== 'bool' && - <Col sm='4'> - <Label>Restrict to...</Label> - <FormGroup check> - <Row> - <Col> - <Label check> - <Input - type='checkbox' - checked={Array.isArray(param.choice)} - onChange={e => { - const b = e.target.checked; - const newParam = {...param}; - if(b){ - delete newParam['range']; - newParam['choice'] = []; - } else { - delete newParam['choice']; - } - - updateParameter(name, newParam); - }} - />{' '} - Choices - </Label> - </Col> - { - param.type !== 'string' && - <Col> - <Label check className='ml-3'> - <Input - type='checkbox' - checked={Array.isArray(param.range)} - onChange={e => { - const b = e.target.checked; - const newParam = {...param}; - if(b){ - delete newParam['choice']; - newParam['range'] = [0, 1]; - } else { - delete newParam['range']; - } - - updateParameter(name, newParam); - }} - />{' '} - Range - </Label> - </Col> - } - </Row> - </FormGroup> - </Col> - } - { - Array.isArray(param.choice) && - <Col sm='auto'> - <Label> - Choices - </Label> - <UncontrolledDropdown> - <DropdownToggle caret> - Choices List - </DropdownToggle> - <DropdownMenu className='p-0'> - { - param.choice - .map((c, j) => - <InputGroup key={j}> - <Input - defaultValue={c} - className='border-top-0 border-left-0 border-right-0 rounded-0' - onSubmit={e => { - e.preventDefault(); - }} - onChange={e => { - updateParameter( - name, - { - ...param, - choice: param.choice.map((c, k) => k === j ? e.target.value : c) - }); - }} - /> - <InputGroupAddon addonType='append'> - <Button - className='border-top-0 border-left-0 border-right-0 rounded-0' - color='danger' - onClick={e => { - updateParameter(name, - { - ...param, - choice: param.choice.filter((c, k) => k !== j) - } - ); - }} - > - x - </Button> - </InputGroupAddon> - </InputGroup> - ) - } - <Input - placeholder='New Choice...' - className='border-top-0 border-left-0 border-right-0 rounded-0' - value={this.state.choiceCache} - onSubmit={e => { - e.preventDefault(); - }} - onBlur={e => { - if(this.state.choiceCache.length > 0) - updateParameter(name, - { - ...param, - choice: [ - ...param.choice, - this.state.choiceCache - ] - }); - this.setState({ choiceCache: '' }); - }} - onChange={e => { - this.setState({ choiceCache: e.target.value }); - }} - onKeyPress={e => { - if(e.key === 'Enter'){ - if(this.state.choiceCache.length > 0) - updateParameter(name, - { - ...param, - choice: [ - ...param.choice, - this.state.choiceCache - ] - } - ); - this.setState({ choiceCache: '' }); - } - }} - /> - </DropdownMenu> - </UncontrolledDropdown> - </Col> - } - { - Array.isArray(param.range) && - <Col sm='4'> - <Label> - Range - </Label> - <FormGroup row> - <Col> - <InputGroup> - <InputGroupAddon>Min</InputGroupAddon> - <Input - type='number' - step={param.type.startsWith('float') ? 'any' : '1'} - value={param.range[0]} - onChange={e => { - const num = e.target.value; - const newParam = { - ...param, - range: [ - num, - param.range[1], - ] - }; - updateParameter( - name, - newParam - ); - }} - required - /> - </InputGroup> - </Col> - <Col> - <InputGroup> - <InputGroupAddon>Max</InputGroupAddon> - <Input - type='number' - step={param.type.startsWith('float') ? 'any' : '1'} - value={param.range[1]} - required - onChange={e => { - const num = e.target.value; - const newParam = { - ...param, - range: [ - param.range[0], - num, - ] - }; - updateParameter( - name, - newParam - ); - }} - /> - </InputGroup> - </Col> - </FormGroup> - </Col> - } - { param.type !== 'bool' && - <Col> - <Label for={`default${ name }`}> - Default - </Label> - <Input - name={`default${ name }`} - type='text' - placeholder='Default' - value={param.default} - onChange={(e) => updateParameter(name, { - ...param, - default: e.target.value - })} - /> - </Col> - || - <Col sm='auto'> - <Label> - Default - </Label> - <FormGroup check> - <Row> - <Col> - <Label check> - <Input - name={`default${ name }`} - type='radio' - checked={param.default && !new_param} - value={true} - onChange={(e) => updateParameter(name, { - ...param, - default: JSON.parse(e.target.value) - })} - /> - True - </Label> - </Col> - <Col> - <Label check className='ml-1'> - <Input - name={`default${ name }`} - type='radio' - checked={!param.default && !new_param} - value={false} - onChange={(e) => updateParameter(name, { - ...param, - default: JSON.parse(e.target.value) - })} - /> - False - </Label> - </Col> - </Row> - </FormGroup> - </Col> - } - </FormGroup> - </React.Fragment> - ); - } -} diff --git a/conda/js/src/components/ParameterCreate.spec.jsx b/conda/js/src/components/ParameterCreate.spec.jsx deleted file mode 100644 index 8d2d6e25..00000000 --- a/conda/js/src/components/ParameterCreate.spec.jsx +++ /dev/null @@ -1,69 +0,0 @@ -//// @flow -//import React from 'react'; -//import { expect } from 'chai'; -//import { mount } from 'enzyme'; -//import sinon from 'sinon'; -//import { spies } from '@test'; -// -//import C from './ParameterCreate.jsx'; -// -//describe.only('<ParameterCreate />', () => { -// let wrapper; -// const name = 'parameter'; -// // shortcut for a func to update just the parameter obj, not the name -// const _updateParameter = (name, p, oldName) => { -// wrapper.setProps({ -// param: p, -// }); -// }; -// const params = []; -// -// afterEach(() => { -// if(wrapper && wrapper.unmount) -// wrapper.unmount(); -// }); -// -// it(`saves the default value of a boolean parameter`, () => { -// let param = { -// type: '', -// default: '', -// description: '', -// }; -// const updateParameter = sinon.spy(_updateParameter); -// -// wrapper = mount( -// <C -// name={name} -// param={param} -// params={params} -// updateParameter={updateParameter} -// /> -// ); -// -// // sanity checks -// expect(wrapper.find('TypedField')).to.have.prop('name', name); -// -// wrapper.find('Input.custom-select').prop('onChange')( { target: { value: 'bool' }}); -// wrapper.update(); -// console.log(wrapper.props().param); -// expect(wrapper.props().param).to.deep.equal( -// { -// type: 'bool', -// default: '', -// description: '', -// } -// ); -// -// // wrapper.find('input[type="radio"]').at(0).simulate('change', { target: { checked: 'true' }});; -// wrapper.find('input[type="radio"]').at(0).simulate('change', { target: { value: 'true' }});; -// wrapper.update(); -// expect(updateParameter.args[0]).to.deep.equal([ -// name, -// { -// type: 'bool', -// default: 'true', -// description: '', -// } -// ]); -// }); -//}); diff --git a/conda/js/src/components/SearchBar.jsx b/conda/js/src/components/SearchBar.jsx deleted file mode 100644 index dc8e433f..00000000 --- a/conda/js/src/components/SearchBar.jsx +++ /dev/null @@ -1,145 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - Badge, - Dropdown, DropdownMenu, DropdownItem, DropdownToggle, - Input, - Button, -} from 'reactstrap'; - -import { Link } from 'react-router-dom'; - -import { connect } from 'react-redux'; - -import * as Selectors from '@store/selectors.js'; - -import { pluralize } from '@helpers/beat'; -import type { BeatEntity, BeatObject } from '@helpers/beat'; - -import SearchWorker from '@helpers/search.worker.js'; - -type Props = { - entity: BeatEntity, - data: BeatObject[], -}; - -type State = { - searchResults: BeatObject[], - resultsOpen: boolean, -}; - -class SearchBar extends React.PureComponent<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - searchResults: [], - resultsOpen: false, - } - - searchWorker = null; - - componentDidMount = () => { - this.searchWorker = new SearchWorker(); - this.searchWorker.onmessage = (m) => { - this.setState(prevState => ({ - searchResults: m.data.slice(0, 5), - resultsOpen: m.data.length > 0, - })); - }; - this.updateFuseInstance(); - } - - componentDidUpdate = (prevProps: Props) => { - if(this.props.data !== prevProps.data){ - this.updateFuseInstance(this.props.data); - } - } - - updateFuseInstance = (data: BeatObject[] = this.props.data) => { - if(!this.searchWorker) - throw new Error(`searchWorker is not instantiated!`); - this.searchWorker.postMessage( - { - type: 'dataChanged', - payload: { - data, - options: { - shouldSort: true, - tokenize: true, - threshold: 0.6, - location: 0, - distance: 100, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: ['name', 'contents.description', 'contents.#description'], - } - } - } - ); - } - - search = (str: string) => { - if(!this.searchWorker) - throw new Error(`searchWorker is not instantiated!`); - this.searchWorker.postMessage( - { - type: 'search', - payload: str - } - ); - } - - toggleResults = (val: boolean = !this.state.resultsOpen) => { - this.setState({ resultsOpen: val }); - }; - - render = () => { - return ( - <Dropdown - isOpen={this.state.resultsOpen} - toggle={e => this.toggleResults(false)} - style={{flex: 1}} - className='ml-2 mr-2' - > - <DropdownToggle - tag='span' - > - <Input - onChange={e => { - this.search(e.target.value); - }} - placeholder={`Search ${ pluralize(this.props.entity) }...`} - /> - </DropdownToggle> - <DropdownMenu> - { - this.state.searchResults.map((r, i) => - <DropdownItem - tag={Link} - to={`/${ this.props.entity }/${ r.name }`} - key={i} - > - { r.name } - {' '} - <small className='text-muted'> - { r.contents.description || r.contents['#description'] || '' } - </small> - </DropdownItem> - ) - } - </DropdownMenu> - </Dropdown> - ); - } -} - -const mapStateToProps = (state, ownProps) => ({ - data: Selectors[`${ ownProps.entity }Get`](state), -}); - -export default connect(mapStateToProps)(SearchBar); diff --git a/conda/js/src/components/Settings.jsx b/conda/js/src/components/Settings.jsx deleted file mode 100644 index c7d047c8..00000000 --- a/conda/js/src/components/Settings.jsx +++ /dev/null @@ -1,84 +0,0 @@ -// @flow -import React from 'react'; -import { - Button, - Form, FormGroup, Label, Input, - Modal, ModalHeader, ModalBody, ModalFooter, -} from 'reactstrap'; - -import { connect } from 'react-redux'; -import * as Actions from '@store/actions.js'; - -import * as Selectors from '@store/selectors'; - -import { genModuleApiFuncs } from '@helpers/api'; -import type { BeatSettings } from '@helpers/beat'; - -type Props = { - isOpen: boolean, - toggle: () => mixed, - settings: BeatSettings, - updateSettings: (obj: BeatSettings) => any, - fetchAllObjects: () => any, -}; - -export class Settings extends React.PureComponent<Props> { - constructor(props: Props){ - super(props); - } - - save = async () => { - await genModuleApiFuncs('settings').put(this.props.settings); - await this.props.fetchAllObjects(); - } - - render = () => { - const {isOpen, toggle, settings} = this.props; - return ( - <Modal isOpen={isOpen} toggle={toggle} autoFocus={true}> - <ModalHeader toggle={toggle}>Settings</ModalHeader> - <ModalBody> - <Form> - { - Object.entries(settings).map(([name, val], i) => - <FormGroup key={i}> - <Label>{ name }</Label> - <Input - autoFocus - value={val} - onChange={e => { - this.props.updateSettings({ - ...settings, - [name]: e.target.value, - }); - }} - /> - </FormGroup> - ) - } - </Form> - <a href='https://gitlab.idiap.ch/jdiefenbaugh/beat.editor'>Github</a> - </ModalBody> - <ModalFooter> - <Button color="primary" onClick={this.save}>Write Settings to server</Button> - <Button color="secondary" onClick={toggle}>Close</Button> - </ModalFooter> - </Modal> - ); - } -} - -const mapStateToProps = state => ({ - settings: Selectors.settingsGet(state), -}); - -const mapDispatchToProps = (dispatch, ownProps) => ({ - updateSettings: (obj) => { - dispatch(Actions.settingsUpdate(obj)); - }, - fetchAllObjects: () => { - dispatch(Actions.fetchAllObjects()); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Settings); diff --git a/conda/js/src/components/TypedField.jsx b/conda/js/src/components/TypedField.jsx deleted file mode 100644 index 277b9264..00000000 --- a/conda/js/src/components/TypedField.jsx +++ /dev/null @@ -1,75 +0,0 @@ -// @flow -import * as React from 'react'; - -import { - Col, - Input, - FormGroup, -} from 'reactstrap'; - -import ValidSchemaBadge from './ValidSchemaBadge.jsx'; -import DeleteInputBtn from './DeleteInputBtn.jsx'; -import CacheInput from './CacheInput.jsx'; - -type Props = { - name: string, - type: string, - types: string[], - typeTitles?: string[], - existingFields: string[], - nameUpdateFunc: (string) => any, - typeUpdateFunc: (string) => any, - nameValidateFunc?: (string) => boolean | React.Node, - deleteFunc: (any) => any, - children?: React.Node, - placeholder?: string, -}; - -export const DupErr = ({ }: {}) => <span> Each field must have a unique name </span>; - -class TypedField extends React.PureComponent<Props> { - constructor(props: Props){ - super(props); - } - - render = () => ( - <FormGroup row> - <Col sm='6'> - <CacheInput - type='text' - placeholder={this.props.placeholder || 'Name...'} - value={this.props.name} - onChange={(e) => this.props.nameUpdateFunc(e.target.value)} - validateFunc={(str) => { - if(this.props.existingFields.includes(str)) - return <DupErr />; - if(this.props.nameValidateFunc) - return this.props.nameValidateFunc(str); - return true; - }} - fieldTest - > - <DeleteInputBtn deleteFunc={this.props.deleteFunc} /> - </CacheInput> - </Col> - <Col> - <Input - type='select' - className='custom-select' - value={this.props.type} - onChange={e => this.props.typeUpdateFunc(e.target.value)} - > - <option disabled value=''>Type...</option> - { - this.props.types.map((t, i) => ( - <option key={i} value={t}>{Array.isArray(this.props.typeTitles) ? this.props.typeTitles[i] : (t === 'object' ? 'dict' : t)}</option> - )) - } - </Input> - </Col> - { this.props.children } - </FormGroup> - ); -} - -export default TypedField; diff --git a/conda/js/src/components/ValidSchemaBadge.jsx b/conda/js/src/components/ValidSchemaBadge.jsx deleted file mode 100644 index 585e8659..00000000 --- a/conda/js/src/components/ValidSchemaBadge.jsx +++ /dev/null @@ -1,30 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Badge, -} from 'reactstrap'; - -import Validate, { VALIDATORS } from '@helpers/schema'; -import type { BeatObject, BeatEntity } from '@helpers/beat'; - -type Props = { - entity: BeatEntity, - obj: BeatObject, -}; - -const ValidSchemaBadge = (props: Props) => { - const errs = Validate(VALIDATORS[props.entity], props.obj); - const isValid = !errs; - - if(!isValid){ - //console.log(errs); - } - - return ( - <Badge className='ml-1' color={isValid ? 'success' : 'danger'}> - {isValid ? 'Valid' : 'Invalid'} - </Badge> - ); -}; - -export default ValidSchemaBadge; diff --git a/conda/js/src/components/ValidSchemaBadge.spec.jsx b/conda/js/src/components/ValidSchemaBadge.spec.jsx deleted file mode 100644 index 866e1f3b..00000000 --- a/conda/js/src/components/ValidSchemaBadge.spec.jsx +++ /dev/null @@ -1,207 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '../../test'; - -import C from './ValidSchemaBadge.jsx'; - -import testAlgs from '@test/test_algs.json'; -import testLibs from '@test/test_libs.json'; -import testDfs from '@test/test_dfs.json'; -import testDbs from '@test/test_dbs.json'; - -describe('<ValidSchemaBadge />', () => { - let wrapper; - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('should accept', () => { - describe('database', () => { - const dbs = [ - { - name: 'test/test/1', - contents: { - 'root_folder': '/testing', - description: 'this is the basic test case for database schema validation', - protocols: [ - { - name: 'protocol_1', - template: 'template_1', - sets: [ - { - name: 'set_1', - view: 'view_1', - template: 'set_template_1', - parameters: { - param1: 'i dont know what these are' - }, - outputs: { - output_1: 'a/specific_dataformat/1', - } - } - ] - } - ] - } - } - ].concat(testDbs); - - dbs.forEach(function(db) { - it(`${ db.name }`, () => { - wrapper = mount(<C entity='database' obj={db} />); - expect(wrapper.find('Badge')).to.have.prop('color', 'success'); - }); - }); - }); - - describe('algorithm', () => { - const algs = [ - { - name: 'test/non-analyzer-alg/1', - contents: { - language: 'python', - description: 'A basic algorithm as a sanity test for the AlgorithmEditor', - groups: [ - { - name: 'group_1', - inputs: { - 'input_1': { type: 'test/df/1' }, - }, - outputs: { - 'output_1': { type: 'test/df/2' }, - }, - } - ], - uses: { - 'library_1': 'a/lib/1', - }, - parameters: { - 'parameter_1': { - type: 'string', - choice: [ - 'choice_1', - 'choice_2', - 'choice_3', - ], - default: 'choice_1', - } - }, - // non-analyzer - splittable: false, - } - } - ].concat(testAlgs); - - algs.forEach(function(alg) { - it(`${ alg.name }`, () => { - wrapper = mount(<C entity='algorithm' obj={alg} />); - expect(wrapper.find('Badge')).to.have.prop('color', 'success'); - }); - }); - }); - - describe('dataformat', () => { - const dfs = [ - { - name: 'test/df/1', - contents: { - 'field_1': 'string', - } - } - ].concat(testDfs); - - dfs.forEach(function(df) { - it(`${ df.name }`, () => { - wrapper = mount(<C entity='dataformat' obj={df} />); - expect(wrapper.find('Badge')).to.have.prop('color', 'success'); - }); - }); - }); - describe('library', () => { - const libs = [ - { - name: 'test/lib/1', - contents: { - language: 'python', - } - } - ].concat(testLibs); - - libs.forEach(function(lib) { - it(`${ lib.name }`, () => { - wrapper = mount(<C entity='library' obj={lib} />); - expect(wrapper.find('Badge')).to.have.prop('color', 'success'); - }); - }); - }); - }); - - describe('should reject', () => { - describe('database', () => { - const dbs = [ - { - name: 'test/test/1', - contents: { - 'root_folder': '/testing', - description: 'this is the basic test case for database schema validation', - protocols: [ - { - name: 'protocol_1', - template: 'template_1', - sets: [ - { - name: 'set_1', - view: 'view_1', - template: 'set_template_1', - parameters: { - param1: 'i dont know what these are' - }, - outputs: { - output_1: 'a/wrong/output', - } - } - ] - } - ] - } - }, - { - name: 'test/test/1', - contents: { - description: 'this is the basic test case for database schema validation', - protocols: [ - { - name: 'protocol_1', - template: 'template_1', - sets: [ - { - name: 'set_1', - view: 'view_1', - template: 'set_template_1', - parameters: { - param1: 'i dont know what these are' - }, - outputs: { - output_1: 'a/wrong/output', - } - } - ] - } - ] - } - } - ]; - - dbs.forEach(function(db) { - it(`${ db.name }`, () => { - wrapper = mount(<C entity='database' obj={db} />); - expect(wrapper.find('Badge')).to.have.prop('color', 'danger'); - }); - }); - }); - }); -}); diff --git a/conda/js/src/components/algorithm/AlgorithmEditor.jsx b/conda/js/src/components/algorithm/AlgorithmEditor.jsx deleted file mode 100644 index 2318f550..00000000 --- a/conda/js/src/components/algorithm/AlgorithmEditor.jsx +++ /dev/null @@ -1,729 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Row, - Col, - Button, - Form, FormGroup, - Label, Input, - Card, CardHeader, CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, - Alert, - UncontrolledDropdown, DropdownToggle, DropdownMenu, - InputGroup, InputGroupAddon, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import cn from 'classnames'; - -import { changeObjFieldName, generateNewKey, copyObj } from '@helpers'; -import { algorithmValidator, BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidAlgorithmObj as getValidObj } from '@helpers/beat'; -import type { AlgorithmValidatorObject, BeatObject } from '@helpers/beat'; - -import * as Selectors from '@store/selectors.js'; - -import * as Actions from '@store/actions.js'; -import CacheInput from '../CacheInput.jsx'; -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; -import TemplateButton from '../EntityTemplateGenerationButton.jsx'; -import InfoTooltip from '../InfoTooltip.jsx'; -import ParameterCreate from '../ParameterCreate.jsx'; - -type Props = { - data: BeatObject, - algorithms: BeatObject[], - libraries: BeatObject[], - dataformats: BeatObject[], - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, -}; - -type State = { - // which tab the user is viewing (endpoints, params, etc.) - activeTab: string, - // algorithm-specific validity checking (alerts for common errors & warnings) - validity: AlgorithmValidatorObject, - // parameters can restrict their values to individual choices - // this string represents a choice that is being edited - choiceCache: string, -}; - -// represents an input or output value -// inputs/outputs are just an object with a "type" field -type IOEntry = {| - type: string, -|}; - -// represents a collection of inputs/outputs -type IOObject = { - [string]: IOEntry, -}; - -// represents a group/endpoint, optionally with outputs -type Group = { - name: string, - inputs: IOObject, - outputs?: IOObject, -}; - -export class AlgorithmEditor extends React.Component<Props, State> { - constructor(props: Props) { - //console.log(`Creating AlgDetail`); - super(props); - } - - state = { - activeTab: '0', - validity: algorithmValidator(this.props.data, this.props.algorithms), - choiceCache: '', - } - - // if the data changes behind the scenes, update the editor with these changes - componentDidUpdate = (prevProps: Props) => { - if(this.props !== prevProps){ - this.setState({ - validity: this.getValidity(this.props.data, this.props.algorithms), - }); - } - } - - // get the result types (analyzer result types are restricted to a subset of all available types) - getResultDfs = (): string[] => ANALYZER_RESULT_TYPES.concat(this.props.dataformats.filter(d => d.name.startsWith('plot')).map(d => d.name)) - - // returns a validity object based on the given algorithm cache and list of all algorithms - getValidity = (cache: BeatObject = this.props.data, algs: BeatObject[] = this.props.algorithms): AlgorithmValidatorObject => { - return algorithmValidator(cache, algs.filter(o => o !== this.props.data)); - } - - // much like getValidity but just returns a bool - // doesnt worry about warnings, just errors - isValid = (cache: BeatObject): boolean => { - const isValid = Object.entries(this.getValidity(cache)) - .filter(([name, bool]) => name !== (this.isAnalyzer() ? 'endpoint0OutputExists' : 'result0Exists')) - .reduce((bool, [name, b]): boolean => (!!b) && bool, true) - ; - - return isValid; - } - - // change the tab - tabTo = (tab: string) => { if(this.state.activeTab !== tab) this.setState({ activeTab: tab }); } - - // is the algorithm an analyzer? - // theres no flag set, so instead check for the existence of a 'splittable' field which only normal algorithms have - isAnalyzer = (): boolean => { return !Object.keys(this.props.data.contents).includes('splittable'); } - - // helper to change a value in the "contents" subobject of an algorithm - // (this is where the vast majority of change happens) - changeContentsVal = (field: string, val: any) => { - const newCache = { - ...this.props.data, - contents: { - ...this.props.data.contents, - [field]: val - } - }; - - this.props.updateFunc(newCache); - } - - // updates an old group object to a new group object - updateGroup = (oldGroup: Group, newGroup: Group) => { - const gIdx = this.props.data.contents.groups.findIndex(g => JSON.stringify(g) === JSON.stringify(oldGroup)); - const newGroups = copyObj(this.props.data.contents.groups); - newGroups[gIdx] = newGroup; - this.changeContentsVal('groups', newGroups); - } - - // 4 different functions: - // creates a parameter (provide name & value) - // updates a parameter (provide name & value) - // renames a parameter (provide name & value & the old name) - // deletes a parameter (provide null as name, value is optional, the name) - updateParameter = (name: null | string, value: any, oldName: ?string) => { - const params = copyObj(this.props.data.contents.parameters); - if(oldName) - delete params[oldName]; - if(name !== null) - params[name] = value; - this.changeContentsVal('parameters', params); - } - - // updates a result given the result name and the value obj - updateResult = (name: string, res: any) => { - const rs = this.props.data.contents.results; - rs[name] = res; - this.changeContentsVal('results', rs); - } - - // toggles the algorithm to an analyzer algorithm - changeToAnalyzer = () => { - const contents = copyObj(this.props.data.contents); - contents.groups = contents.groups.map(g => { - delete g['outputs']; - return g; - }); - contents.results = {}; - delete contents['splittable']; - - const newCache = { - ...this.props.data, - contents - }; - - this.props.updateFunc(newCache); - } - - // toggles the algorithm to a normal algorithm - changeToNormal = () => { - const contents = copyObj(this.props.data.contents); - delete contents.results; - if(contents.groups.length > 0) - contents.groups[0].outputs = {}; - contents.splittable = false; - - const newCache = { - ...this.props.data, - contents - }; - - this.props.updateFunc(newCache); - } - - // generates a func from a given group & type that takes an input/output name - // and deletes it from the group - deleteIO = (group: Group, type: 'inputs' | 'outputs') => (name: string) => { - if(!group[type]) - return; - delete group[type][name]; - this.updateGroup(group, { ...group }); - } - - // rendergs the endpoints tab - renderEndpoints = () => ( - <TabPane tabId='0'> - { - // loop through all groups in the alg - this.props.data.contents.groups.map((group: Group, i, groups: Group[]) => { - // func to update an input/output - // lets you change the name and/or the type - const ioUpdate = (subObj: 'inputs' | 'outputs') => (oldName: string, newName: string, newObj: IOEntry) => { - const changedObj = changeObjFieldName(group[subObj], oldName, newName); - changedObj[newName] = newObj; - this.updateGroup(group, - { - ...group, - [subObj]: changedObj - } - ); - }; - - const inputsUpdate = ioUpdate('inputs'); - const outputsUpdate = ioUpdate('outputs'); - - return ( - <Row key={i} className='mb-2' id={`endpoint${ i }`}> - <Col sm='12'> - <Card> - { groups.length > 1 && - <CardHeader> - Group { i } - </CardHeader> - } - <CardBody> - { Object.keys(group.inputs).length === 0 && i !== 0 && - <Alert color='warning'> - In general, an endpoint group should have at least 1 input. - </Alert> - } - <Row> - <Col sm={group.outputs ? '6' : '12'}> - { - (Object.entries(group.inputs): [string, any][]) - .map(([name, ioObj], i, gEntries) => - <TypedField - className='algInput' - key={i} - name={name} - type={ioObj.type} - types={this.props.dataformats.map(d => d.name)} - existingFields={gEntries.map(([n, v]) => n)} - nameUpdateFunc={str => inputsUpdate(name, str, ioObj)} - typeUpdateFunc={str => inputsUpdate( - name, - name, - { type: str } - )} - deleteFunc={() => this.deleteIO(group, 'inputs')(name)} - /> - ) - } - <Button outline block - id='newInputBtn' - onClick={(e) => { - const newKey = generateNewKey('input', Object.keys(group.inputs)); - this.updateGroup( - group, - { - ...group, - inputs: { - ...group.inputs, - [newKey]: { type: '' } - } - } - ); - }} - > - New Input - </Button> - </Col> - { group.outputs && ( - <Col sm='6'> - { - (Object.entries(group.outputs): [string, any][]) - .map(([name, ioObj], i, gEntries) => - <TypedField - className='algOutput' - key={i} - name={name} - type={ioObj.type} - types={this.props.dataformats.map(d => d.name)} - existingFields={gEntries.map(([n, v]) => n)} - nameUpdateFunc={str => outputsUpdate(name, str, ioObj)} - typeUpdateFunc={str => outputsUpdate( - name, - name, - { type: str } - )} - deleteFunc={() => this.deleteIO(group, 'outputs')(name)} - /> - ) - } - <Button outline block - id='newOutputBtn' - onClick={(e) => { - const newKey = generateNewKey('output', Object.keys(group.outputs)); - this.updateGroup( - group, - { - ...group, - outputs: { - ...group.outputs, - [newKey]: { type: '' } - } - } - ); - }} - > - New Output - </Button> - </Col> - )} - </Row> - </CardBody> - { i !== 0 && - <Button block color='danger' outline - onClick={() => this.changeContentsVal( - 'groups', - groups - .filter(g => g.name !== group.name) - )} - > - Delete Group - </Button> - } - </Card> - </Col> - </Row> - ); - }) - } - <Button block - id='newGroupBtn' - onClick={(e) => { - const newGroupName = generateNewKey('group', this.props.data.contents.groups.map(g => g.name)); - const newGroup = { - name: newGroupName, - inputs: {}, - }; - if(!this.isAnalyzer() && this.props.data.contents.groups.length === 0) - newGroup.outputs = {}; - - this.changeContentsVal( - 'groups', - [... this.props.data.contents.groups, newGroup ] - ); - }} - > - New Group - </Button> - </TabPane> - ); - - // renders the parameters tab - renderParameters = () => { - return ( - <TabPane tabId='1'> - { - // loop through all the parameters - (Object.entries(this.props.data.contents.parameters): [string, any][]).map(([name, param], i, params) => ( - <Row key={i} className='mb-2'> - <Col sm='12'> - <ParameterCreate - name={name} - param={param} - params={params} - updateParameter={this.updateParameter} - /> - </Col> - </Row> - )) - } - <Button outline block - id='newParameterBtn' - onClick={() => { - const newKey = generateNewKey('parameter', Object.keys(this.props.data.contents.parameters || {})); - this.changeContentsVal('parameters', - { - ...(this.props.data.contents.parameters || {}), - [newKey]: { - type: '', - default: '', - description: '', - } - } - ); - }} - > - New Parameter - </Button> - </TabPane> - ); - } - - // renders the libraries tab - renderLibraries = () => ( - <TabPane tabId='2'> - <Row> - <Col sm='12'> - { - // loop through all the used libs - (Object.entries(this.props.data.contents.uses): [string, any][]) - .map(([name, lib], i, lEntries) => ( - <TypedField - key={i} - name={name} - type={lib} - types={this.props.libraries.map(l => l.name)} - existingFields={lEntries.map(([n, v]) => n)} - nameUpdateFunc={str => { - // update the alias - this.changeContentsVal('uses', - changeObjFieldName( - this.props.data.contents.uses, - name, - str - ) - ); - }} - typeUpdateFunc={str => { - // update the chosen library for the alias - const libs = { - ...this.props.data.contents.uses, - [name]: str - }; - this.changeContentsVal('uses', libs); - }} - deleteFunc={() => { - const libs = { ...this.props.data.contents.uses }; - delete libs[name]; - this.changeContentsVal('uses', libs); - }} - /> - )) - } - </Col> - </Row> - <Button outline block - id='newLibraryBtn' - onClick={() => { - const newKey = generateNewKey('library', Object.keys(this.props.data.contents.uses)); - this.changeContentsVal('uses', - { - ...this.props.data.contents.uses, - [newKey]: '' - } - ); - }} - > - New Library - </Button> - </TabPane> - ); - - // renders the results tab (only if the alg is an analyzer) - renderResults = () => ( - <TabPane tabId='3'> - { - // loop through results - (Object.entries(this.props.data.contents.results): [string, any][]) - .map(([name, result], i, rEntries) => ( - <TypedField - key={i} - name={name} - type={result.type} - types={this.getResultDfs()} - existingFields={rEntries.map(([n, v]) => n)} - nameUpdateFunc={str => this.changeContentsVal( - 'results', - changeObjFieldName( - this.props.data.contents.results, - name, - str - ) - )} - typeUpdateFunc={str => this.updateResult(name, - { - ...result, - type: str - } - )} - deleteFunc={() => { - const newRes = { - ...this.props.data.contents.results - }; - delete newRes[name]; - this.changeContentsVal( - 'results', - newRes - ); - }} - > - <Col> - {/* display by default checkbox */} - <Label check> - <Input - type='checkbox' - value={result.display ? true : false} - onChange={(e) => this.changeContentsVal( - 'results', - { ...this.props.data.contents.results, - [name] : { - ...result, - display: e.target.checked - } - }) - } - /> - {' '} - <span>Display By Default</span> - </Label> - </Col> - </TypedField> - )) - } - <Button outline block - id='newResultBtn' - onClick={() => { - const newKey = generateNewKey('result', Object.keys(this.props.data.contents.results)); - this.changeContentsVal( - 'results', - {...this.props.data.contents.results, - [newKey]: { - display: false, - type: '' - } - } - ); - }} - > - New Result - </Button> - </TabPane> - ); - - render = () => ( - <div> - {/* header content (save button & template gen button) */} - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='algorithm' obj={this.props.data} />) - </Button> - <TemplateButton - data={this.props.data} - entity={'algorithm'} - /> - </div> - {/* simple universal stuff - description, what type of alg, if its splittable */} - <Form> - <React.Fragment> - <FormGroup tag='fieldset'> - <FormGroup> - <Label for='algDesc'>Short Description</Label> - <Input - type='text' - name='desc' - id='algDesc' - placeholder='Algorithm description...' - value={this.props.data.contents.description} - onChange={(e) => this.changeContentsVal('description', e.target.value)} - /> - </FormGroup> - <FormGroup check> - <Label check> - <Input - id='algAnalyzer' - type='checkbox' - checked={this.isAnalyzer()} - onChange={e => e.target.checked ? this.changeToAnalyzer() : this.changeToNormal()} - />{' '} - <InfoTooltip - id='analyzerTooltip' - info={`Checking this option makes this algorithm an "analyzer". Analyzers are made to analyze the experiment's performance (and other characteristics). Experiments must have 1 and only analyzer at the end of the experiment's toolchain. These types of algorithms produce evalution data for the user, such as plots, scores, and statistics.`} - > - Analyser - </InfoTooltip> - </Label> - </FormGroup> - { !this.isAnalyzer() && - <FormGroup check> - <Label check> - <Input - id='algSplittable' - type='checkbox' - checked={this.props.data.contents.splittable ? true : false} - onChange={e => this.changeContentsVal('splittable', e.target.checked)} - />{' '} - <InfoTooltip - id='splittableTooltip' - info={`A non-analyzer algorithm may be decided to be "splittable". Being splittable means that multiple instances of the algorithm may be ran in parallel on different bits of input. Non-splittable algorithms usually have some sort of aggregation/cross-input activity. Most algorithms will be splittable, but it is much easier to debug an algorithm with it being non-splittable.`} - > - Splittable - </InfoTooltip> - </Label> - </FormGroup> - } - </FormGroup> - {/* most errors/warnings from the current AlgorithmValidator object are displayed here */} - { - (!this.isAnalyzer() || this.getValidity().result0Exists) || - <Alert color='danger'> - You need at least 1 result from an Analyzer. - </Alert> - } - { - this.getValidity().endpoint0Exists || - <Alert color='danger'> - You need at least 1 endpoint group. - </Alert> - } - { - (this.isAnalyzer() || this.getValidity().endpoint0OutputExists) || - <Alert color='danger'> - You must have at least 1 output - in the first endpoint group. - </Alert> - } - { - this.getValidity().endpoint0InputExists || - <Alert color='danger'> - You need at least 1 input in the first endpoint group. - </Alert> - } - {/* all the tabs: endpoints, params, libs, results */} - <Nav tabs className='mt-3 mb-3'> - <NavItem> - <NavLink - className={cn({ active: this.state.activeTab === '0' })} - onClick={() => this.tabTo('0')} - > - <InfoTooltip - id='endpointTooltip' - info={`Endpoints are groups of inputs & outputs. An algorithm can have multiple endpoints (and must have at least 1), but each endpoint must have at least 1 input. If the algorithm is an analyzer, no groups can have outputs. If it is not an analyzer, only the first endpoint can have outputs, and at least 1 output is required.`} - > - Endpoints - </InfoTooltip> - </NavLink> - </NavItem> - <NavItem> - <NavLink - className={cn({ active: this.state.activeTab === '1' })} - onClick={() => this.tabTo('1')} - > - <InfoTooltip - id='parametersTooltip' - info={`Parameters are completely optional, allowing for users to change the functionality of the block when configuring an experiment. Parameters lend themselves to building reusable and flexible blocks. For example, a parameter could allow configuring the number of components in PCA, or choosing kernels/kernel parameters for an SVM.`} - > - Parameters - </InfoTooltip> - </NavLink> - </NavItem> - <NavItem> - <NavLink - className={cn({ active: this.state.activeTab === '2' })} - onClick={() => this.tabTo('2')} - > - <InfoTooltip - id='libraryTooltip' - info={`Libraries provide DRYness to code development for objects in the BEAT platform. Libraries are groups of functions under a given namespace. You may use libraries by adding it to your algorithm and referencing the namespace in your algorithm by the nickname you provide here.`} - > - Libraries - </InfoTooltip> - </NavLink> - </NavItem> - { this.isAnalyzer() && - <NavItem> - <NavLink - className={cn({ active: this.state.activeTab === '3' })} - onClick={() => this.tabTo('3')} - > - <InfoTooltip - id='resultsTooltip' - info={`Results are only for analyzer algorithms. They are similar to outputs in normal algorithms, but provide evaluation information on the whole experiment instead of output data to be processed by another block. Examples are plot data (for example, data for an ROC curve), scores, and statistics.`} - > - Results - </InfoTooltip> - </NavLink> - </NavItem> - } - </Nav> - <TabContent className='mb-3' activeTab={this.state.activeTab}> - { this.renderEndpoints() } - { this.renderParameters() } - { this.renderLibraries() } - { this.props.data.contents.results && this.renderResults() } - </TabContent> - </React.Fragment> - </Form> - </div> - ); -} - -const mapStateToProps = (state, ownProps) => { - const algs = Selectors.algorithmGet(state); - const obj = { - algorithms: algs, - libraries: Selectors.libraryGet(state), - dataformats: Selectors.dataformatGet(state), - data: algs[ownProps.index] || getValidObj() - }; - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`algorithmUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(AlgorithmEditor); diff --git a/conda/js/src/components/algorithm/AlgorithmEditor.spec.jsx b/conda/js/src/components/algorithm/AlgorithmEditor.spec.jsx deleted file mode 100644 index 446093ad..00000000 --- a/conda/js/src/components/algorithm/AlgorithmEditor.spec.jsx +++ /dev/null @@ -1,691 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import { AlgorithmEditor as C } from '.'; -import { getValidAlgorithmObj as getValidObj } from '@helpers/beat'; - -import testAlgs from '@test/test_algs.json'; -import testDfs from '@test/test_dfs.json'; -import testLibs from '@test/test_libs.json'; - -const libs = []; -const dfs = []; - -describe('<AlgorithmEditor />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const algs = [ - { - name: 'test/non-analyzer-alg/1', - contents: { - language: 'python', - description: 'A basic algorithm as a sanity test for the AlgorithmEditor', - groups: [ - { - name: 'group_1', - inputs: { - 'input_1': { type: 'test/df/1' }, - }, - outputs: { - 'output_1': { type: 'test/df/2' }, - }, - } - ], - uses: { - 'library_1': 'a/lib/1', - }, - parameters: { - 'parameter_1': { - type: 'string', - choice: [ - 'choice_1', - 'choice_2', - 'choice_3', - ], - default: 'choice_1', - } - }, - // non-analyzer - splittable: false, - } - - } - ].concat(testAlgs.map(a => getValidObj(a))); - - algs.forEach(function(alg){ - const saveFunc = () => {}; - const updateFunc = () => {}; - it(`${ alg.name }`, () => { - wrapper = mount( - <C - data={getValidObj(alg)} - algorithms={algs} - dataformats={dfs} - libraries={libs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ).deep.equal( - [alg, algs, dfs, libs, saveFunc, updateFunc] - ); - }); - }); - }); - - describe('creates', () => { - it('user/integers_echo/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const algName = 'user/integers_echo/1'; - wrapper = mount( - <C - data={getValidObj({name: algName, contents: {}})} - algorithms={[]} - dataformats={testDfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', algName); - - wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.property('splittable', true); - - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1); - expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs'); - - expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group'); - - wrapper.find('button#newInputBtn').simulate('click'); - expect(updateFunc.callCount).to.equal(2); - wrapper.find('button#newOutputBtn').simulate('click'); - expect(updateFunc.callCount).to.equal(3); - - wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }}); - expect(updateFunc.callCount).to.equal(4); - wrapper.find('.algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }}); - expect(updateFunc.callCount).to.equal(5); - - const ioType = 'system/integer/1'; - wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }}); - expect(updateFunc.callCount).to.equal(6); - wrapper.find('.algOutput select').prop('onChange')( { target: { value: ioType }}); - expect(updateFunc.callCount).to.equal(7); - - expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType }); - expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType }); - - expect(wrapper.props().data.contents).to.deep.equal({ - description: '', - 'groups': [ - { - 'inputs': { - 'in_data': { - 'type': 'system/integer/1' - } - }, - 'name': 'group', - 'outputs': { - 'out_data': { - 'type': 'system/integer/1' - } - } - } - ], - parameters: {}, - uses: {}, - 'splittable': true, - 'language': 'python' - }); - }); - - it('user/integers_add/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const algName = 'user/integers_add/1'; - wrapper = mount( - <C - data={getValidObj({name: algName, contents: {}})} - algorithms={[]} - dataformats={testDfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', algName); - - wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }}); - expect(wrapper.props().data.contents).to.have.property('splittable', true); - - expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1); - expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs'); - - expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group'); - - wrapper.find('button#newInputBtn').simulate('click'); - wrapper.find('button#newOutputBtn').simulate('click'); - - wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }}); - wrapper.find('.algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }}); - - const ioType = 'system/integer/1'; - wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }}); - wrapper.find('.algOutput select').prop('onChange')( { target: { value: ioType }}); - - expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType }); - expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType }); - - wrapper.find('a') - .findWhere(w => { - const html = w.html(); - return html && html.includes('Parameters'); - }) - .at(0) - .simulate('click'); - - wrapper.find('button#newParameterBtn').simulate('click'); - - wrapper.find('CacheInput[placeholder="Parameter name..."]').prop('onChange')( { target: { value: 'offset' }}); - wrapper.find('[tabId="1"] select').prop('onChange')( { target: { value: 'int32' }}); - wrapper.find('input[placeholder="Default"]').simulate('change', { target: { value: '1' }}); - - expect(wrapper.props().data.contents.parameters).to.have.deep.property('offset', { - 'default': '1', - 'type': 'int32', - 'description': '', - }); - - wrapper.find('a') - .findWhere(w => { - const html = w.html(); - return html && html.includes('Libraries'); - }) - .at(0) - .simulate('click'); - - wrapper.find('button#newLibraryBtn').simulate('click'); - - wrapper.find('[tabId="2"] CacheInput[type="text"]').prop('onChange')( { target: { value: 'lib' }}); - wrapper.find('[tabId="2"] select').prop('onChange')( { target: { value: 'user/thelib/1' }}); - - expect(wrapper.props().data.contents.uses).to.have.property('lib', 'user/thelib/1'); - - expect(wrapper.props().data.contents).to.deep.equal({ - description: '', - 'groups': [ - { - 'inputs': { - 'in_data': { - 'type': 'system/integer/1' - } - }, - 'name': 'group', - 'outputs': { - 'out_data': { - 'type': 'system/integer/1' - } - } - } - ], - 'parameters': { - 'offset': { - 'default': '1', - 'type': 'int32', - description: '', - } - }, - 'uses': { - 'lib': 'user/thelib/1' - }, - 'splittable': true, - 'language': 'python' - }); - }); - - it('user/integers_echo_analyzer/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const algName = 'user/integer_echo_analyzer/1'; - wrapper = mount( - <C - data={getValidObj({name: algName, contents: {}})} - algorithms={[]} - dataformats={testDfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', algName); - - wrapper.find('#algAnalyzer input').prop('onChange')( { target: { checked: true }}); - expect(wrapper.props().data.contents).to.have.property('results'); - - expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1); - expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[0]).to.not.have.property('outputs'); - - expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group'); - - wrapper.find('button#newInputBtn').simulate('click'); - - wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }}); - - const ioType = 'system/integer/1'; - wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }}); - - expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType }); - - wrapper.find('a') - .findWhere(w => { - const html = w.html(); - return html && html.includes('Results'); - }) - .at(0) - .simulate('click'); - - wrapper.find('button#newResultBtn').simulate('click'); - wrapper.find('button#newResultBtn').simulate('click'); - wrapper.find('button#newResultBtn').simulate('click'); - wrapper.find('button#newResultBtn').simulate('click'); - - wrapper.find('[tabId="3"] CacheInput[type="text"]').at(0).prop('onChange')( { target: { value: 'roc' }}); - wrapper.find('[tabId="3"] select').at(0).prop('onChange')( { target: { value: 'plot/isoroc/1' }}); - - wrapper.find('[tabId="3"] CacheInput[type="text"]').at(1).prop('onChange')( { target: { value: 'plot' }}); - wrapper.find('[tabId="3"] select').at(1).prop('onChange')( { target: { value: 'plot/scatter/1' }}); - - wrapper.find('[tabId="3"] CacheInput[type="text"]').at(2).prop('onChange')( { target: { value: 'out_data' }}); - wrapper.find('[tabId="3"] select').at(2).prop('onChange')( { target: { value: 'int32' }}); - - wrapper.find('[tabId="3"] CacheInput[type="text"]').at(3).prop('onChange')( { target: { value: 'bar_plot' }}); - wrapper.find('[tabId="3"] select').at(3).prop('onChange')( { target: { value: 'plot/bar/1' }}); - - expect(wrapper.props().data.contents.results).to.deep.equal({ - 'roc': { - 'type': 'plot/isoroc/1', - 'display': false - }, - 'plot': { - 'type': 'plot/scatter/1', - 'display': false - }, - 'out_data': { - 'type': 'int32', - 'display': false - }, - 'bar_plot': { - 'type': 'plot/bar/1', - 'display': false - } - }); - - expect(wrapper.props().data.contents).to.deep.equal({ - description: '', - 'groups': [ - { - 'inputs': { - 'in_data': { - 'type': 'system/integer/1' - } - }, - 'name': 'group' - } - ], - parameters: {}, - uses: {}, - 'language': 'python', - 'results': { - 'roc': { - 'type': 'plot/isoroc/1', - 'display': false - }, - 'plot': { - 'type': 'plot/scatter/1', - 'display': false - }, - 'out_data': { - 'type': 'int32', - 'display': false - }, - 'bar_plot': { - 'type': 'plot/bar/1', - 'display': false - } - } - }); - }); - - it('user/integers_echo_ignore/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const algName = 'user/integers_echo/1'; - wrapper = mount( - <C - data={getValidObj({name: algName, contents: {}})} - algorithms={[]} - dataformats={testDfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', algName); - - wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }}); - expect(wrapper.props().data.contents).to.have.property('splittable', true); - - wrapper.find('button#newGroupBtn').simulate('click'); - - expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(2); - expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs'); - expect(wrapper.props().data.contents.groups[1]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[1]).to.not.have.property('outputs'); - - // Group 1 - expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group'); - - wrapper.find('#endpoint0 button#newInputBtn').simulate('click'); - wrapper.find('#endpoint0 button#newOutputBtn').simulate('click'); - - wrapper.find('#endpoint0 .algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }}); - wrapper.find('#endpoint0 .algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }}); - - const ioType = 'system/integer/1'; - wrapper.find('#endpoint0 .algInput select').prop('onChange')( { target: { value: ioType }}); - wrapper.find('#endpoint0 .algOutput select').prop('onChange')( { target: { value: ioType }}); - - expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType }); - expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType }); - - // Group 2 - expect(wrapper.props().data.contents.groups[1]).to.have.property('name', 'group0'); - - wrapper.find('#endpoint1 button#newInputBtn').simulate('click'); - - wrapper.find('#endpoint1 .algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data2' }}); - wrapper.find('#endpoint1 .algInput select').prop('onChange')( { target: { value: ioType }}); - expect(wrapper.props().data.contents.groups[1].inputs).to.have.deep.property('in_data2', { type: ioType }); - - expect(wrapper.props().data.contents).to.be.deep.equal({ - description: '', - 'groups': [ - { - 'inputs': { - 'in_data': { - 'type': 'system/integer/1' - } - }, - 'name': 'group', - 'outputs': { - 'out_data': { - 'type': 'system/integer/1' - } - } - }, - { - 'inputs': { - 'in_data2': { - 'type': 'system/integer/1' - } - }, - 'name': 'group0' - } - ], - parameters: {}, - uses: {}, - 'splittable': true, - 'language': 'python' - }); - }); - - it('system/integers_echo_sleep/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const algName = 'user/integers_echo_sleep/1'; - wrapper = mount( - <C - data={getValidObj({name: algName, contents: {}})} - algorithms={[]} - dataformats={testDfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', algName); - - wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }}); - expect(wrapper.props().data.contents).to.have.property('splittable', true); - - expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1); - expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs'); - - expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group'); - - wrapper.find('button#newInputBtn').simulate('click'); - wrapper.find('button#newOutputBtn').simulate('click'); - - wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }}); - wrapper.find('.algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }}); - - const ioType = 'system/integer/1'; - wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }}); - wrapper.find('.algOutput select').prop('onChange')( { target: { value: ioType }}); - - expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType }); - expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType }); - - wrapper.find('a') - .findWhere(w => { - const html = w.html(); - return html && html.includes('Parameters'); - }) - .at(0) - .simulate('click'); - - wrapper.find('button#newParameterBtn').simulate('click'); - - wrapper.find('CacheInput[placeholder="Parameter name..."]').prop('onChange')( { target: { value: 'delay' }}); - wrapper.find('[tabId="1"] select').prop('onChange')( { target: { value: 'uint32' }}); - wrapper.find('input[placeholder="Default"]').simulate('change', { target: { value: '30' }}); - wrapper.find('input[placeholder="Description"]').simulate('change', { target: { value: 'Time to sleep in seconds' }}); - - expect(wrapper.props().data.contents.parameters).to.have.deep.property('delay', { - 'default': '30', - 'type': 'uint32', - 'description': 'Time to sleep in seconds', - }); - - expect(wrapper.props().data.contents).to.be.deep.equal({ - description: '', - uses: {}, - 'language': 'python', - 'splittable': true, - 'groups': [ - { - 'name': 'group', - 'inputs': { - 'in_data': { - 'type': 'system/integer/1' - } - }, - 'outputs': { - 'out_data': { - 'type': 'system/integer/1' - } - } - } - ], - 'parameters': { - 'delay': { - 'default': '30', - 'type': 'uint32', - 'description': 'Time to sleep in seconds' - } - } - }); - }); - - it('user/integers_mean_analyzer/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const algName = 'user/integers_mean_analyzer/1'; - wrapper = mount( - <C - data={getValidObj({name: algName, contents: {}})} - algorithms={[]} - dataformats={testDfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', algName); - - wrapper.find('#algAnalyzer input').prop('onChange')( { target: { checked: true }}); - expect(wrapper.props().data.contents).to.have.property('results'); - - expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1); - expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs'); - expect(wrapper.props().data.contents.groups[0]).to.not.have.property('outputs'); - - expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group'); - - wrapper.find('button#newInputBtn').simulate('click'); - - wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }}); - - const ioType = 'system/integer/1'; - wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }}); - - expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType }); - - wrapper.find('a') - .findWhere(w => { - const html = w.html(); - return html && html.includes('Results'); - }) - .at(0) - .simulate('click'); - - wrapper.find('button#newResultBtn').simulate('click'); - wrapper.find('button#newResultBtn').simulate('click'); - - wrapper.find('[tabId="3"] CacheInput[type="text"]').at(0).prop('onChange')( { target: { value: 'plot' }}); - wrapper.find('[tabId="3"] select').at(0).prop('onChange')( { target: { value: 'plot/scatter/1' }}); - - wrapper.find('[tabId="3"] CacheInput[type="text"]').at(1).prop('onChange')( { target: { value: 'out_data' }}); - wrapper.find('[tabId="3"] select').at(1).prop('onChange')( { target: { value: 'float32' }}); - - expect(wrapper.props().data.contents.results).to.deep.equal({ - 'plot': { - 'type': 'plot/scatter/1', - 'display': false, - }, - 'out_data': { - 'type': 'float32', - 'display': false - }, - }); - - expect(wrapper.props().data.contents).to.deep.equal({ - description: '', - uses: {}, - parameters: {}, - 'language': 'python', - 'groups': [ - { - name: 'group', - 'inputs': { - 'in_data': { - 'type': 'system/integer/1' - } - } - } - ], - 'results': { - 'out_data': { - 'type': 'float32', - 'display': false - }, - 'plot': { - 'type': 'plot/scatter/1', - 'display': false - } - } - }); - }); - }); - -}); diff --git a/conda/js/src/components/algorithm/index.js b/conda/js/src/components/algorithm/index.js deleted file mode 100644 index ee4f4928..00000000 --- a/conda/js/src/components/algorithm/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedAlgorithmEditor, {AlgorithmEditor} from './AlgorithmEditor.jsx'; - -export { - AlgorithmEditor, -}; - -export default ConnectedAlgorithmEditor; diff --git a/conda/js/src/components/database/DatabaseEditor.css b/conda/js/src/components/database/DatabaseEditor.css deleted file mode 100644 index 1d5dca69..00000000 --- a/conda/js/src/components/database/DatabaseEditor.css +++ /dev/null @@ -1,18 +0,0 @@ -.databaseEditor .toc > h4 { - text-align: center; -} - -.databaseEditor .toc { - right: 0; - top: 3em; - width: calc(50% - (1140px / 2)); - position: fixed; - overflow-y: auto; - bottom: 0; -} - -.databaseEditor .toc > .list-group > .list-group-item { - border-right: none; - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} diff --git a/conda/js/src/components/database/DatabaseEditor.jsx b/conda/js/src/components/database/DatabaseEditor.jsx deleted file mode 100644 index 4d90069e..00000000 --- a/conda/js/src/components/database/DatabaseEditor.jsx +++ /dev/null @@ -1,984 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - Button, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, - Dropdown, UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem, - ButtonGroup, - ListGroup, ListGroupItem, - UncontrolledTooltip, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import './DatabaseEditor.css'; - -import { changeObjFieldName, copyObj } from '@helpers'; -import { getValidDatabaseObj as getValidObj } from '@helpers/beat'; -import type { BeatObject } from '@helpers/beat'; -import fuse from 'fuse.js'; - -import * as Selectors from '@store/selectors.js'; - -import * as Actions from '@store/actions.js'; -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import CacheInput from '../CacheInput.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; -import TemplateButton from '../EntityTemplateGenerationButton.jsx'; -import InfoTooltip from '../InfoTooltip.jsx'; - - -type Props = { - data: BeatObject, - saveFunc: (BeatObject) => any, - databases: BeatObject[], - dataformats: BeatObject[], - updateFunc: (BeatObject) => any, - protocols: SelectorProtocol[] -}; - -export type Protocol = { - name: string, - template: string, - sets: Set[], -}; - -// the protocols from the databaseProtocols selector has an additional field -// that's not in the protocols in database objects -type SelectorProtocol = Protocol & { database: string }; - -type State = { - activeProtocol: number, - insertProtocolOpen: boolean, - searchResults: SelectorProtocol[], -}; - -export type Set = { - name: string, - template: string, - view: string, - parameters: { - [string]: string, - }, - outputs: { - [string]: string, - }, -}; - -const FuseOptions = { - shouldSort: true, - tokenize: true, - threshold: 0.6, - location: 0, - distance: 100, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: ['template'], -}; -let Fuse; - -export class DatabaseEditor extends React.Component<Props, State> { - constructor(props: Props) { - super(props); - } - - state = { - activeProtocol: 0, - insertProtocolOpen: false, - searchResults: [], - } - - setContents = (newContents: any) => { - this.props.updateFunc({ - ...this.props.data, - contents: { - 'description': this.props.data.contents['description'], - ...newContents, - } - }); - } - - componentDidMount = () => { - this.updateFuseInstance(); - } - - componentDidUpdate = (prevProps: Props, prevState: State) => { - this.updateFuseInstance(prevProps); - } - - updateFuseInstance = (prevProps?: Props) => { - // update fuse & reset results if search data changed - if(!prevProps || this.props.protocols !== prevProps.protocols){ - Fuse = new fuse(this.props.protocols, FuseOptions); - } - } - - activateProtocol = (index: number) => { - this.setState({ activeProtocol: index }); - } - - updateProtocol = (index: number, obj: Protocol) => { - this.setContents({ - ...this.props.data.contents, - protocols: this.props.data.contents.protocols.map((o, i) => i === index ? obj : o) - }); - } - - updateSet = (idxProtocol: number, idxSet: number, obj: Set) => { - const protocol = this.props.data.contents.protocols[idxProtocol]; - this.updateProtocol( - idxProtocol, - { - ...protocol, - sets: protocol.sets.map((s, i) => i === idxSet ? obj : s) - } - ); - } - - toggleInsertProtocol = (val: boolean = !this.state.insertProtocolOpen) => { - this.setState({ insertProtocolOpen: val }); - }; - - protocolSearch = (str: string) => { - const res = Fuse.search(str); - this.setState(prevState => ({ - searchResults: res.slice(0, 5), - insertProtocolOpen: res.length > 0, - })); - }; - - // if the protocol template name has any uses with a different protocol makeup, - // returns the info on all other uses - validateProtocolTemplate = (protocol: Protocol): null | React.Node => { - const tName = protocol.template; - const prots = this.props.protocols.filter(p => p.template === tName); - // basically a hashmap of all the different protocols using this template name - // if theres more than one, theres at least two different protocols using the same template name! - const diffTemplateMap: {[string]: {name: string, database: string}[]} = {}; - prots.forEach(prot => { - const p = copyObj(prot); - const pInfo = { - name: p.name, - database: p.database, - }; - - delete p['name']; - delete p['database']; - const json = JSON.stringify(p); - - if(Object.keys(diffTemplateMap).includes(json)){ - diffTemplateMap[json].push(pInfo); - } else { - diffTemplateMap[json] = [ pInfo ]; - } - }); - - const tMapData = Object.entries(diffTemplateMap); - if(tMapData.length > 1){ - // theres >=2 protocols using the same template name but with different contents - // get the currently active protocol - const prot = copyObj(protocol); - delete prot['name']; - delete prot['database']; - const pStr = JSON.stringify(prot); - - // print out the protocols that are using the same template name but diff contents - const TemplateAlert = <Alert color='secondary'> - <p> - There are protocols using the same template name but with different contents: - </p> - <ul> - { - tMapData - // only protocols with different contents - .filter(([k, pData]) => k !== pStr) - // get all the protocols of all the different contents - .reduce((ps, [k, pData]) => [...ps, ...pData], []) - .map(({ name, database }, i) => <li key={i}>{`${ name } (${ database })`}</li>) - } - </ul> - </Alert>; - - return TemplateAlert; - } else { - // valid template useage throughout all dbs - return null; - } - } - - renderProtocol = (index: number, protocol: Protocol) => ( - <Container className='protocol'> - <FormGroup row> - <Col sm='2'> - <Label for='protocolName' className='col-form-label'>Name</Label> - </Col> - <Col sm='10'> - <CacheInput - name='protocolName' - placeholder='Protocol name...' - value={protocol.name} - onChange={(e) => { - this.updateProtocol(index, {...protocol, name: e.target.value}); - }} - fieldTest - /> - </Col> - </FormGroup> - <FormGroup row> - <Col sm='2'> - <Label for='protocolTemplate' className='col-form-label'>Template Name</Label> - </Col> - <Col sm='10'> - <CacheInput - name='protocolTemplate' - placeholder='Protocol Template name...' - value={protocol.template} - onChange={(e) => { - this.updateProtocol(index, {...protocol, template: e.target.value}); - }} - fieldTest - /> - </Col> - </FormGroup> - - - { - // show an alert about protocol template usage - this.validateProtocolTemplate(protocol) - } - - <Row className='protocolSets'> - <Col className='d-flex align-items-center mb-2'> - <h3 className='mb-0 mr-2'> - <InfoTooltip - id='setsTooltip' - info={`Sets provide different ways to separate the database. For example, one set providing training data and another providing testing data.`} - > - Sets - </InfoTooltip> - </h3> - <Button color='success' - id='newSet' - onClick={e => { - const newSets = [...protocol.sets, { - name: '', - template: '', - view: '', - outputs: {}, - parameters: {}, - }]; - - this.updateProtocol( - index, - { - ...protocol, - sets: newSets - } - ); - }} - > - + - </Button> - </Col> - - <Col sm='12'> - { - protocol.sets.map((currSet, i) => - <Row key={i} className={`set${ i }`}> - <Col> - <h4> - { currSet.name } - {' '} - <ButtonGroup> - <Button outline color='danger' - onClick={e => { - this.updateProtocol( - index, - { - ...protocol, - sets: protocol.sets.filter((s, j) => i !== j) - } - ); - }} - > - Delete - </Button> - <Button outline color='secondary' - onClick={e => { - const newSets = [...protocol.sets]; - newSets.splice(i + 1, 0, copyObj(currSet)); - - this.updateProtocol( - index, - { - ...protocol, - sets: newSets - } - ); - }} - > - Clone - </Button> - </ButtonGroup> - </h4> - <FormGroup row> - <Col> - <Label for={`setName${ i }`} className='col-form-label'>Name</Label> - <CacheInput - name={`setName${ i }`} - placeholder='Set name...' - value={currSet.name} - onChange={(e) => { - this.updateSet(index, i, {...currSet, name: e.target.value}); - }} - fieldTest - /> - </Col> - <Col> - <Label for={`setTemplate${ i }`} className='col-form-label'>Template Name</Label> - <CacheInput - name={`setTemplate${ i }`} - placeholder='Set Template name...' - value={currSet.template} - onChange={(e) => { - this.updateSet(index, i, {...currSet, template: e.target.value}); - }} - fieldTest - /> - </Col> - <Col> - <Label for={`setView${ i }`} className='col-form-label'> - <InfoTooltip - id={`view${ i }Tooltip`} - info={`Every set in a database needs to have a View name assigned to it. This name references a class of the same name in the database's Python file. When data is requested from a set, the View class's code is executed.`} - > - View Name - </InfoTooltip> - </Label> - <CacheInput - name={`setView${ i }`} - placeholder='Set View name...' - value={currSet.view} - onChange={(e) => { - this.updateSet(index, i, {...currSet, view: e.target.value}); - }} - fieldTest - /> - </Col> - </FormGroup> - <Container className='setParameters'> - <Row> - <Col sm='12'> - <div className='d-flex align-items-center mb-2'> - <h5 className='mb-0 mr-2'> - <InfoTooltip - id={`parameters${ i }Tooltip`} - info={`Parameters are simple values that may be passed to the set's View class' "index" method. This lets a single View class support multiple sets by changing functionality based on these parameters.`} - > - Parameters - </InfoTooltip> - </h5> - <Button - color='success' - className='newParameter' - onClick={e => { - let newKey = ''; - let v = 0; - while(true) { - const tryKey = `parameter_${ v }`; - if(Object.keys(currSet.parameters).includes(tryKey)){ - v++; - continue; - } - newKey = tryKey; - break; - } - - this.updateSet(index, i, { - ...currSet, - parameters: { - ...currSet.parameters, - [newKey]: '' - } - }); - }} - > - + - </Button> - </div> - </Col> - </Row> - { - Object.keys(currSet.parameters).length > 0 && - <Row> - <Col sm='6'> - <h6>Parameter Name</h6> - </Col> - <Col sm='6'> - <h6>Parameter Value</h6> - </Col> - </Row> - } - { - ((Object.entries(currSet.parameters): any): [string, string][]).map(([pName, param], j, ps) => - <FormGroup row key={j} className={`setParameter${ j }`}> - <Col sm='6'> - <CacheInput - fieldTest - value={pName} - onChange={e => { - const str = e.target.value; - const newParams = changeObjFieldName( - currSet.parameters, - pName, - str - ); - - this.updateSet(index, i, - { - ...currSet, - parameters: newParams - } - ); - }} - > - <DeleteInputBtn - deleteFunc={() => { - const newParameters = { ...currSet.parameters }; - delete newParameters[pName]; - - this.updateSet(index, i, - { - ...currSet, - parameters: newParameters - } - ); - }} - /> - </CacheInput> - </Col> - <Col sm='6'> - <CacheInput - fieldTest - value={param} - onChange={e => { - const str = e.target.value; - this.updateSet(index, i, - { - ...currSet, - parameters: { - ...currSet.parameters, - [pName]: str - } - } - ); - }} - - /> - </Col> - </FormGroup> - ) - } - </Container> - <Container className='setOutputs'> - <Row> - <Col sm='12'> - <div className='d-flex align-items-center mb-2'> - <h5 className='mb-0 mr-2'> - <InfoTooltip - id={`outputs${ i }Tooltip`} - info={`Every set in a database needs at least 1 output. These outputs are of a specific type and provide data to algorithm blocks connected to this output.`} - > - Outputs - </InfoTooltip> - </h5> - <Button - color='success' - className='newOutput' - onClick={e => { - let newKey = ''; - let v = 0; - while(true) { - const tryKey = `output_${ v }`; - if(Object.keys(currSet.outputs).includes(tryKey)){ - v++; - continue; - } - newKey = tryKey; - break; - } - - this.updateSet(index, i, { - ...currSet, - outputs: { - ...currSet.outputs, - [newKey]: '' - } - }); - }} - > - + - </Button> - </div> - </Col> - </Row> - { - Object.keys(currSet.outputs).length > 0 && - <Row> - <Col sm='6'> - <h6>Output Name</h6> - </Col> - <Col sm='6'> - <h6>Output Type</h6> - </Col> - </Row> - } - { - ((Object.entries(currSet.outputs): any): [string, string][]).map(([outputName, df], j, os) => - <TypedField - className='setOutput' - key={j} - name={outputName} - type={df} - types={this.props.dataformats.map(d => d.name).filter(d => !['object', 'array'].includes(d))} - existingFields={Object.keys(currSet.outputs)} - nameUpdateFunc={str => { - const newOutputs = changeObjFieldName( - currSet.outputs, - outputName, - str - ); - - this.updateSet(index, i, - { - ...currSet, - outputs: newOutputs - } - ); - }} - typeUpdateFunc={str => this.updateSet(index, i, - { - ...currSet, - outputs: { - ...currSet.outputs, - [outputName]: str - } - } - )} - deleteFunc={() => { - const newOutputs = { ...currSet.outputs }; - delete newOutputs[outputName]; - - this.updateSet(index, i, - { - ...currSet, - outputs: newOutputs - } - ); - }} - - /> - ) - } - <FormGroup row> - <Col sm='12'> - </Col> - </FormGroup> - </Container> - </Col> - </Row> - ) - } - </Col> - </Row> - </Container> - ); - - render = () => { - const protocolIdx = this.state.activeProtocol; - const protocol = protocolIdx > -1 ? this.props.data.contents.protocols[protocolIdx] || undefined : undefined; - - return ( - <div className='databaseEditor'> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='database' obj={this.props.data} />) - </Button> - <TemplateButton - data={this.props.data} - entity={'database'} - /> - </div> - <Form onSubmit={(e) => e.preventDefault()}> - <FormGroup tag='fieldset'> - <FormGroup> - <Label for='description'>Short Description</Label> - <Input - type='text' - name='description' - placeholder='Database description...' - value={this.props.data.contents['description']} - onChange={e => this.setContents({ ...this.props.data.contents, 'description': e.target.value})} - /> - </FormGroup> - <FormGroup> - <Label for='rootFolder'>Root Folder</Label> - <Input - type='text' - name='rootFolder' - placeholder='Valid system path...' - value={this.props.data.contents['root_folder']} - onChange={e => this.setContents({ ...this.props.data.contents, 'root_folder': e.target.value})} - /> - </FormGroup> - </FormGroup> - <div className='d-flex align-items-center mb-3'> - <h3 className='mr-2 mb-0'> - <InfoTooltip - id='protocolsTooltip' - info={`Protocols provide different use-cases for the database.`} - > - Protocols - </InfoTooltip> - </h3> - <UncontrolledDropdown className='mr-3'> - <DropdownToggle color='secondary' caret className=''> - Active Protocol: { protocol ? protocol.name : '' } - </DropdownToggle> - <DropdownMenu> - { - this.props.data.contents.protocols - .map((p, i) => - <DropdownItem - id={`protocolChoice${ i }`} - key={i} - onClick={() => this.activateProtocol(i)} - > - { this.props.data.contents.protocols[i].name }{' '} - ({ this.props.data.contents.protocols[i].template }) - </DropdownItem> - ) - } - </DropdownMenu> - </UncontrolledDropdown> - <ButtonGroup> - <Button outline color='danger' - onClick={e => { - const protocols = this.props.data.contents.protocols - .filter((p, i) => i !== protocolIdx); - - this.setContents({ - ...this.props.data.contents, - protocols - }); - - this.activateProtocol(protocolIdx === 0 ? 0 : protocolIdx - 1); - }} - > - Delete - </Button> - <Button outline color='secondary' - onClick={e => { - const protocols = [...this.props.data.contents.protocols]; - protocols.splice( - protocolIdx + 1, - 0, - copyObj(protocol) - ); - - this.setContents({ - ...this.props.data.contents, - protocols - }); - - this.activateProtocol(protocolIdx + 1); - }} - > - Clone - </Button> - <Button - outline - color='success' - id='newProtocol' - onClick={e => { - const protocols = [...this.props.data.contents.protocols, { - name: '', - template: '', - sets: [], - }]; - - this.setContents({ - ...this.props.data.contents, - protocols - }); - - this.activateProtocol(protocols.length - 1); - }} - > - Create - </Button> - </ButtonGroup> - <Dropdown - isOpen={this.state.insertProtocolOpen} - toggle={e => this.toggleInsertProtocol(false)} - style={{flex: 1}} - className='ml-2 mr-2' - > - <DropdownToggle - tag='span' - > - <Input - onChange={e => { - this.protocolSearch(e.target.value); - }} - id='insertProtocolSearch' - placeholder={`Insert protocol from template...`} - title={`You may insert a protocol from a template from any database`} - /> - </DropdownToggle> - <DropdownMenu> - { - this.state.searchResults.map((r, i) => - <DropdownItem - tag={Button} - key={i} - className='insertProtocolOption' - onClick={e => { - const newProtocol = copyObj(r); - delete newProtocol['database']; - - const newProtocols = [...this.props.data.contents.protocols, newProtocol]; - this.setContents({ - ...this.props.data.contents, - protocols: newProtocols, - }); - - this.activateProtocol(newProtocols.length - 1); - }} - > - { `${ r.template } (${ r.database })` } - {' '} - <small className='text-muted'> - Sets: { r.sets.length } - </small> - </DropdownItem> - ) - } - </DropdownMenu> - </Dropdown> - </div> - { protocol && this.renderProtocol( - protocolIdx, - protocol - )} - </Form> - <div className='toc'> - <h4>Quick Jump:</h4> - <ListGroup> - { - this.props.data.contents.protocols.map((p, i) => { - const setList = ( - <ListGroup className='mt-1'> - { - p.sets.map((s, j) => { - return ( - <ListGroupItem - key={j} - > - <Button - color='link' - size='sm' - onClick={e => { - const setEl = document.querySelector(`.set${ j }`); - if(!setEl) - return; - setEl.scrollIntoView(true); - }} - > - { s.name.length > 20 ? `${ s.name.slice(0, 20) }…` : s.name } - {' '} - </Button> - <ButtonGroup className='float-right'> - <Button size='sm' outline color='danger' - onClick={e => { - this.updateProtocol( - i, - { - ...p, - sets: p.sets.filter((s, k) => j !== k) - } - ); - }} - > - Delete - </Button> - <Button size='sm' outline color='secondary' - onClick={e => { - const newSets = [...p.sets]; - newSets.splice(j + 1, 0, copyObj(s)); - - this.updateProtocol( - i, - { - ...p, - sets: newSets - } - ); - }} - > - Clone - </Button> - </ButtonGroup> - </ListGroupItem> - ); - }) - } - <ListGroupItem tag='button' action className='text-primary' - onClick={e => { - const newSets = [...p.sets, { - name: '', - template: '', - view: '', - outputs: {}, - parameters: {}, - }]; - - this.updateProtocol( - i, - { - ...p, - sets: newSets - } - ); - }} - > - New Set - </ListGroupItem> - </ListGroup> - ); - - return ( - <ListGroupItem - key={i} - > - <div - className='clearfix' - > - <Button - active={i === protocolIdx} - color='link' - size='sm' - onClick={() => i !== protocolIdx && this.activateProtocol(i)} - title={p.name} - > - { p.name.length > 25 ? `${ p.name.slice(0, 25) }…` : p.name } - </Button> - <ButtonGroup className='float-right'> - <Button size='sm' outline color='danger' - onClick={e => { - const protocols = this.props.data.contents.protocols - .filter((p, i) => i !== protocolIdx); - - this.setContents({ - ...this.props.data.contents, - protocols - }); - - this.activateProtocol(protocolIdx === 0 ? 0 : protocolIdx - 1); - }} - > - Delete - </Button> - <Button size='sm' outline color='secondary' - onClick={e => { - const protocols = [...this.props.data.contents.protocols]; - protocols.splice( - protocolIdx + 1, - 0, - copyObj(protocol) - ); - - this.setContents({ - ...this.props.data.contents, - protocols - }); - - this.activateProtocol(protocolIdx + 1); - }} - > - Clone - </Button> - </ButtonGroup> - </div> - { i === protocolIdx && setList } - </ListGroupItem> - ); - }) - } - <ListGroupItem tag='button' action className='text-primary' - onClick={e => { - const protocols = [...this.props.data.contents.protocols, { - name: '', - template: '', - sets: [], - }]; - - this.setContents({ - ...this.props.data.contents, - protocols - }); - - this.activateProtocol(protocols.length - 1); - }} - > - New Protocol - </ListGroupItem> - </ListGroup> - </div> - </div> - ); - } -} - -const mapStateToProps = (state, ownProps) => { - const dbs = Selectors.databaseGet(state); - const obj = { - databases: dbs, - dataformats: Selectors.dataformatGet(state), - data: dbs[ownProps.index] || getValidObj(), - protocols: Selectors.databaseProtocols(state), - }; - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`databaseUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(DatabaseEditor); diff --git a/conda/js/src/components/database/DatabaseEditor.spec.jsx b/conda/js/src/components/database/DatabaseEditor.spec.jsx deleted file mode 100644 index 5b0d2e51..00000000 --- a/conda/js/src/components/database/DatabaseEditor.spec.jsx +++ /dev/null @@ -1,455 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import { getValidDatabaseObj as getValidObj } from '@helpers/beat'; -import { DatabaseEditor as C } from '.'; -import { databaseProtocols } from '@store/selectors'; - -import testDbs from '@test/test_dbs.json'; -import testDfs from '@test/test_dfs.json'; - -const dfs = []; - -describe('<DatabaseEditor />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const dbs = [ - { - name: 'test/test/1', - contents: { - 'root_folder': '/testing', - description: 'this is the basic test case for database schema validation', - protocols: [ - { - name: 'protocol_1', - template: 'template_1', - sets: [ - { - name: 'set_1', - view: 'view_1', - template: 'set_template_1', - parameters: { - param1: 'i dont know what these are' - }, - outputs: { - output_1: 'a/specific_dataformat/1', - } - } - ] - } - ] - } - } - ].concat(testDbs.map(db => getValidObj(db))); - - dbs.forEach(function(db){ - const saveFunc = () => {}; - const updateFunc = () => {}; - it(`${ db.name }`, () => { - const protocols = databaseProtocols({ database: [ db ]}); - wrapper = mount( - <C - data={db} - databases={dbs} - dataformats={dfs} - saveFunc={saveFunc} - updateFunc={updateFunc} - protocols={protocols} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'databases', 'dataformats', 'saveFunc', 'updateFunc', 'protocols'] - ).deep.equal( - [db, dbs, dfs, saveFunc, updateFunc, protocols] - ); - }); - }); - }); - - describe('creates', () => { - it('simple/1', () => { - const dbName = 'simple/1'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - wrapper = mount( - <C - data={getValidObj({name: dbName, contents: {}})} - databases={testDbs.filter(d => d.name !== dbName).map(d => getValidObj(d))} - dataformats={testDfs} - saveFunc={saveFunc} - updateFunc={updateFunc} - protocols={[]} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'databases', 'dataformats', 'saveFunc'] - ); - - // general db - expect(wrapper.props().data).to.have.property('name', dbName); - - wrapper.find('input[name="description"]').simulate('change', { target: { value: 'A test database that emits integers' }}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.property('description', 'A test database that emits integers'); - - wrapper.find('input[name="rootFolder"]').simulate('change', { target: { value: '/this/database/does/not/require/a/path' }}); - expect(updateFunc.callCount).to.equal(2); - expect(wrapper.props().data.contents).to.have.property('root_folder', '/this/database/does/not/require/a/path'); - - // create protocols - wrapper.find('button#newProtocol').simulate('click'); - expect(updateFunc.callCount).to.equal(3); - wrapper.find('button#newProtocol').simulate('click'); - expect(updateFunc.callCount).to.equal(4); - - expect(wrapper.props().data.contents).to.have.property('protocols').with.lengthOf(2); - - // protocol 1 - wrapper.find('button#protocolChoice0').simulate('click'); - - wrapper.find('CacheInput[name="protocolName"]').prop('onChange')( { target: { value: 'protocol' }}); - expect(updateFunc.callCount).to.equal(5); - expect(wrapper.props().data.contents.protocols[0]).to.have.property('name', 'protocol'); - - wrapper.find('CacheInput[name="protocolTemplate"]').prop('onChange')( { target: { value: 'test_integers' }}); - expect(updateFunc.callCount).to.equal(6); - expect(wrapper.props().data.contents.protocols[0]).to.have.property('template', 'test_integers'); - - // protocol 1 sets - wrapper.find('button#newSet').simulate('click'); - expect(updateFunc.callCount).to.equal(7); - wrapper.find('button#newSet').simulate('click'); - expect(updateFunc.callCount).to.equal(8); - expect(wrapper.props().data.contents.protocols[0]).to.have.property('sets').with.lengthOf(2); - - // protocol 1 set 1 - wrapper.find('CacheInput[name="setName0"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(9); - expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('name', 'set'); - wrapper.find('CacheInput[name="setTemplate0"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(10); - expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('template', 'set'); - wrapper.find('CacheInput[name="setView0"]').prop('onChange')( { target: { value: 'View' }}); - expect(updateFunc.callCount).to.equal(11); - expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('view', 'View'); - - wrapper.find('.set0 button.newOutput').simulate('click'); - expect(updateFunc.callCount).to.equal(12); - wrapper.find('.set0 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }}); - expect(updateFunc.callCount).to.equal(13); - wrapper.find('.set0 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }}); - expect(updateFunc.callCount).to.equal(14); - expect(wrapper.props().data.contents.protocols[0].sets[0].outputs).to.have.property('out', 'system/integer/1'); - - // protocol 1 set 2 - wrapper.find('CacheInput[name="setName1"]').prop('onChange')( { target: { value: 'set2' }}); - expect(updateFunc.callCount).to.equal(15); - expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('name', 'set2'); - wrapper.find('CacheInput[name="setTemplate1"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(16); - expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('template', 'set'); - wrapper.find('CacheInput[name="setView1"]').prop('onChange')( { target: { value: 'View2' }}); - expect(updateFunc.callCount).to.equal(17); - expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('view', 'View2'); - - wrapper.find('.set1 button.newOutput').simulate('click'); - expect(updateFunc.callCount).to.equal(18); - wrapper.find('.set1 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }}); - expect(updateFunc.callCount).to.equal(19); - wrapper.find('.set1 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }}); - expect(updateFunc.callCount).to.equal(20); - expect(wrapper.props().data.contents.protocols[0].sets[1].outputs).to.have.property('out', 'system/integer/1'); - - // protocol 2 - wrapper.find('button#protocolChoice1').simulate('click'); - wrapper.find('CacheInput[name="protocolName"]').prop('onChange')( { target: { value: 'protocol2' }}); - expect(updateFunc.callCount).to.equal(21); - expect(wrapper.props().data.contents.protocols[1]).to.have.property('name', 'protocol2'); - - wrapper.find('CacheInput[name="protocolTemplate"]').prop('onChange')( { target: { value: 'test_integers' }}); - expect(updateFunc.callCount).to.equal(22); - expect(wrapper.props().data.contents.protocols[1]).to.have.property('template', 'test_integers'); - - // protocol 2 sets - wrapper.find('button#newSet').simulate('click'); - expect(updateFunc.callCount).to.equal(23); - wrapper.find('button#newSet').simulate('click'); - expect(updateFunc.callCount).to.equal(24); - expect(wrapper.props().data.contents.protocols[1]).to.have.property('sets').with.lengthOf(2); - - // protocol 2 set 1 - wrapper.find('CacheInput[name="setName0"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(25); - expect(wrapper.props().data.contents.protocols[1].sets[0]).to.have.property('name', 'set'); - wrapper.find('CacheInput[name="setTemplate0"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(26); - expect(wrapper.props().data.contents.protocols[1].sets[0]).to.have.property('template', 'set'); - wrapper.find('CacheInput[name="setView0"]').prop('onChange')( { target: { value: 'LargeView' }}); - expect(updateFunc.callCount).to.equal(27); - expect(wrapper.props().data.contents.protocols[1].sets[0]).to.have.property('view', 'LargeView'); - - wrapper.find('.set0 button.newOutput').simulate('click'); - expect(updateFunc.callCount).to.equal(28); - wrapper.find('.set0 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }}); - expect(updateFunc.callCount).to.equal(29); - wrapper.find('.set0 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }}); - expect(updateFunc.callCount).to.equal(30); - expect(wrapper.props().data.contents.protocols[1].sets[0].outputs).to.have.property('out', 'system/integer/1'); - - // protocol 2 set 2 - wrapper.find('CacheInput[name="setName1"]').prop('onChange')( { target: { value: 'set2' }}); - expect(updateFunc.callCount).to.equal(31); - expect(wrapper.props().data.contents.protocols[1].sets[1]).to.have.property('name', 'set2'); - wrapper.find('CacheInput[name="setTemplate1"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(32); - expect(wrapper.props().data.contents.protocols[1].sets[1]).to.have.property('template', 'set'); - wrapper.find('CacheInput[name="setView1"]').prop('onChange')( { target: { value: 'View2' }}); - expect(updateFunc.callCount).to.equal(33); - expect(wrapper.props().data.contents.protocols[1].sets[1]).to.have.property('view', 'View2'); - - wrapper.find('.set1 button.newOutput').simulate('click'); - expect(updateFunc.callCount).to.equal(34); - wrapper.find('.set1 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }}); - expect(updateFunc.callCount).to.equal(35); - wrapper.find('.set1 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }}); - expect(updateFunc.callCount).to.equal(36); - expect(wrapper.props().data.contents.protocols[1].sets[1].outputs).to.have.property('out', 'system/integer/1'); - - expect(wrapper.props().data.contents).to.deep.equal({ - 'root_folder': '/this/database/does/not/require/a/path', - 'description': 'A test database that emits integers', - 'protocols': [ - { - 'name': 'protocol', - 'template': 'test_integers', - 'sets': [ - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set', - 'template': 'set', - 'view': 'View', - parameters: {}, - }, - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set2', - 'template': 'set', - 'view': 'View2', - parameters: {}, - } - ] - }, - { - 'name': 'protocol2', - 'template': 'test_integers', - 'sets': [ - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set', - 'template': 'set', - 'view': 'LargeView', - parameters: {}, - }, - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set2', - 'template': 'set', - 'view': 'View2', - parameters: {}, - } - ] - } - ] - }); - }); - - // tests inserting a protocol from a database - it('simple/2', () => { - const dbName = 'simple/2'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ - data: obj, - protocols: databaseProtocols({ database: [ obj ] }) - }); - }; - const updateFunc = sinon.spy(_updateFunc); - const startData = getValidObj({name: dbName, contents: {}}); - wrapper = mount( - <C - data={startData} - databases={testDbs.filter(d => d.name !== dbName).map(d => getValidObj(d))} - dataformats={testDfs} - saveFunc={saveFunc} - updateFunc={updateFunc} - protocols={databaseProtocols({ database: [ startData ] })} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'databases', 'dataformats', 'saveFunc', 'protocols'] - ); - - // general db - expect(wrapper.props().data).to.have.property('name', dbName); - - wrapper.find('input[name="description"]').simulate('change', { target: { value: 'A test database that emits integers' }}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.property('description', 'A test database that emits integers'); - - wrapper.find('input[name="rootFolder"]').simulate('change', { target: { value: '/this/database/does/not/require/a/path' }}); - expect(updateFunc.callCount).to.equal(2); - expect(wrapper.props().data.contents).to.have.property('root_folder', '/this/database/does/not/require/a/path'); - - // create protocols - wrapper.find('button#newProtocol').simulate('click'); - expect(updateFunc.callCount).to.equal(3); - - expect(wrapper.props().data.contents).to.have.property('protocols').with.lengthOf(1); - - // protocol 1 - wrapper.find('button#protocolChoice0').simulate('click'); - - wrapper.find('CacheInput[name="protocolName"]').prop('onChange')( { target: { value: 'protocol' }}); - expect(updateFunc.callCount).to.equal(4); - expect(wrapper.props().data.contents.protocols[0]).to.have.property('name', 'protocol'); - - wrapper.find('CacheInput[name="protocolTemplate"]').prop('onChange')( { target: { value: 'test_integers' }}); - expect(updateFunc.callCount).to.equal(5); - expect(wrapper.props().data.contents.protocols[0]).to.have.property('template', 'test_integers'); - - // protocol 1 sets - wrapper.find('button#newSet').simulate('click'); - expect(updateFunc.callCount).to.equal(6); - wrapper.find('button#newSet').simulate('click'); - expect(updateFunc.callCount).to.equal(7); - expect(wrapper.props().data.contents.protocols[0]).to.have.property('sets').with.lengthOf(2); - - // protocol 1 set 1 - wrapper.find('CacheInput[name="setName0"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(8); - expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('name', 'set'); - wrapper.find('CacheInput[name="setTemplate0"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(9); - expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('template', 'set'); - wrapper.find('CacheInput[name="setView0"]').prop('onChange')( { target: { value: 'View' }}); - expect(updateFunc.callCount).to.equal(10); - expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('view', 'View'); - - wrapper.find('.set0 button.newOutput').simulate('click'); - expect(updateFunc.callCount).to.equal(11); - wrapper.find('.set0 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }}); - expect(updateFunc.callCount).to.equal(12); - wrapper.find('.set0 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }}); - expect(updateFunc.callCount).to.equal(13); - expect(wrapper.props().data.contents.protocols[0].sets[0].outputs).to.have.property('out', 'system/integer/1'); - - // protocol 1 set 2 - wrapper.find('CacheInput[name="setName1"]').prop('onChange')( { target: { value: 'set2' }}); - expect(updateFunc.callCount).to.equal(14); - expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('name', 'set2'); - wrapper.find('CacheInput[name="setTemplate1"]').prop('onChange')( { target: { value: 'set' }}); - expect(updateFunc.callCount).to.equal(15); - expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('template', 'set'); - wrapper.find('CacheInput[name="setView1"]').prop('onChange')( { target: { value: 'View2' }}); - expect(updateFunc.callCount).to.equal(16); - expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('view', 'View2'); - - wrapper.find('.set1 button.newOutput').simulate('click'); - expect(updateFunc.callCount).to.equal(17); - wrapper.find('.set1 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }}); - expect(updateFunc.callCount).to.equal(18); - wrapper.find('.set1 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }}); - expect(updateFunc.callCount).to.equal(19); - expect(wrapper.props().data.contents.protocols[0].sets[1].outputs).to.have.property('out', 'system/integer/1'); - - // protocol 2 - wrapper.find('input#insertProtocolSearch').prop('onChange')( { target: { value: 'test_integers' }}); - wrapper.update(); - wrapper.find('button.insertProtocolOption').at(0).simulate('click'); - expect(updateFunc.callCount).to.equal(20); - wrapper.find('button#protocolChoice1').simulate('click'); - wrapper.find('CacheInput[name="protocolName"]').prop('onChange')( { target: { value: 'protocol2' }}); - expect(updateFunc.callCount).to.equal(21); - expect(wrapper.props().data.contents.protocols[1]).to.have.property('name', 'protocol2'); - - expect(wrapper.props().data.contents).to.deep.equal({ - 'root_folder': '/this/database/does/not/require/a/path', - 'description': 'A test database that emits integers', - 'protocols': [ - { - 'name': 'protocol', - 'template': 'test_integers', - 'sets': [ - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set', - 'template': 'set', - 'view': 'View', - parameters: {}, - }, - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set2', - 'template': 'set', - 'view': 'View2', - parameters: {}, - } - ] - }, - { - 'name': 'protocol2', - 'template': 'test_integers', - 'sets': [ - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set', - 'template': 'set', - 'view': 'View', - parameters: {}, - }, - { - 'outputs': { - 'out': 'system/integer/1' - }, - 'name': 'set2', - 'template': 'set', - 'view': 'View2', - parameters: {}, - } - ] - } - ] - }); - }); - }); -}); diff --git a/conda/js/src/components/database/index.js b/conda/js/src/components/database/index.js deleted file mode 100644 index 6436068c..00000000 --- a/conda/js/src/components/database/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedDatabaseEditor, {DatabaseEditor} from './DatabaseEditor.jsx'; - -export { - DatabaseEditor, -}; - -export default ConnectedDatabaseEditor; diff --git a/conda/js/src/components/dataformat/DataformatEditor.jsx b/conda/js/src/components/dataformat/DataformatEditor.jsx deleted file mode 100644 index dcd2d03b..00000000 --- a/conda/js/src/components/dataformat/DataformatEditor.jsx +++ /dev/null @@ -1,292 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - Button, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, - InputGroupText, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import * as Selectors from '@store/selectors.js'; - -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import CacheInput from '../CacheInput.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; - -import * as Actions from '@store/actions.js'; -import { BUILTIN_TYPES, getValidDataformatObj as getValidObj } from '@helpers/beat'; -import type { - BeatObject, -} from '@helpers/beat.js'; - -import { changeObjFieldName, generateNewKey, copyObj } from '@helpers'; - -type Props = { - data: BeatObject, - dataformats: BeatObject[], - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, -}; - -const isObj = (obj): boolean => !Array.isArray(obj) && typeof obj === 'object' && obj !== null; - -const shownType = (obj: any): string => { - if(Array.isArray(obj)) - return 'array'; - if(isObj(obj)) - return 'object'; - return obj; -}; - -const RecursiveObj = ({ obj, dfs, updateFunc }: {obj: any, dfs: string[], updateFunc: (any) => any}) => ( - <div className='ml-3 pl-3 border border-top-0 border-right-0 border-bottom-0 my-1 dfLevel'> - { - (Object.entries(obj): [string, any][]).map(([name, val], i, entries) => - <div key={i} className={`field${ i }`}> - <TypedField - className='fieldNameType' - name={name} - type={shownType(val)} - types={dfs} - existingFields={Object.keys(obj)} - nameUpdateFunc={str => { - const newObj = changeObjFieldName(obj, name, str); - updateFunc(newObj); - }} - typeUpdateFunc={str => { - let newTypeObj; - switch(str){ - case 'array': - newTypeObj = [0, 'string']; - break; - case 'object': - newTypeObj = {}; - break; - default: - newTypeObj = str; - break; - } - - updateFunc({ ...obj, [name]: newTypeObj }); - }} - deleteFunc={() => { - const newObj = { ...obj }; - delete newObj[name]; - updateFunc(newObj); - }} - /> - { - Array.isArray(val) && - <FormGroup className='ml-3 pl-3 border border-top-0 border-right-0 border-bottom-0'> - <FormGroup row> - <Col sm='3'> - <InputGroup className='mb-1 dimensions'> - <InputGroupAddon addonType='prepend'>Dimensions</InputGroupAddon> - <Input - type='number' - min='1' - max='5' - value={val.filter(v => Number.isInteger(v)).length} - onChange={(e) => { - const newLength = Number.parseInt(`${ e.target.value }`); - const currVals = val.filter(v => Number.isInteger(v)); - const newVals = Array.apply(null, Array(newLength)) - .map((n, i) => currVals[i] !== undefined ? currVals[i] : 0); - newVals.push(val[val.length - 1]); - obj[name] = newVals; - updateFunc(obj); - }} - /> - </InputGroup> - </Col> - <Col sm='auto' className='d-flex my-auto p-0'> - <h5>Sizes:</h5> - </Col> - { - val.filter(v => Number.isInteger(v)).map((v, i) => - <Col key={i} className={`dimension${ i }`}> - <InputGroup className='mb-1'> - <InputGroupAddon addonType='prepend'> - <InputGroupText> - Dim. {i} - </InputGroupText> - </InputGroupAddon> - <Input - key={i} - type='number' - min='0' - value={v} - size='3' - onChange={(e) => { - obj[name][i] = Number.parseInt(`${ e.target.value }`); - updateFunc(obj); - }} - /> - </InputGroup> - </Col> - ) - } - </FormGroup> - <InputGroup className='mb-3'> - <InputGroupAddon addonType='prepend'>Subtype</InputGroupAddon> - <Input - type='select' - value={typeof val[val.length - 1] === 'string' ? val[val.length - 1] : 'object'} - className='custom-select subtype' - onChange={(e) => { - let newTypeObj; - switch(e.target.value){ - case 'array': - newTypeObj = [0, 'string']; - break; - case 'object': - newTypeObj = {}; - break; - default: - newTypeObj = e.target.value; - break; - } - - obj[name][val.length - 1] = newTypeObj; - updateFunc(obj); - }} - > - <option disabled value=''>Type...</option> - { - dfs.map((d, i) => ( - <option key={i} value={d}>{d === 'object' ? 'dict' : d}</option> - )) - } - </Input> - </InputGroup> - { - shownType(val[val.length - 1]) === 'object' && - <RecursiveObj - dfs={dfs} - obj={val[val.length - 1]} - updateFunc={(subobj) => { - obj[name][val.length - 1] = subobj; - updateFunc(obj); - }} - /> - } - - </FormGroup> - } - { - isObj(val) && - <RecursiveObj - dfs={dfs} - obj={val} - updateFunc={(subobj) => { - obj[name] = subobj; - updateFunc(obj); - }} - /> - } - </div> - ) - } - <Button - color='success' - onClick={e => { - let newKey = generateNewKey('field', Object.keys(obj)); - - updateFunc({ - ...obj, - [newKey]: 'string' - }); - }} - > - + - </Button> - </div> -); - -export class DataformatEditor extends React.Component<Props> { - constructor(props: Props) { - super(props); - } - - setContents = (newContents: any) => { - this.props.updateFunc({ - ...this.props.data, - contents: { - '#description': this.props.data.contents['#description'], - ...newContents, - } - }); - } - - allDfs = () => this.props.dataformats.map(d => d.name).concat(BUILTIN_TYPES); - - filteredContents = (obj: any = this.props.data.contents) => Object.entries(obj).filter(([n, v]) => n !== '#description').reduce((o, [n, v]) => ({...o, [n]: v}), {}); - - render = () => ( - <div> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='dataformat' obj={this.props.data} />) - </Button> - </div> - <Form onSubmit={(e) => e.preventDefault()}> - <FormGroup tag='fieldset'> - <FormGroup> - <Label for='description'>Short Description</Label> - <Input - type='text' - name='description' - placeholder='Dataformat description...' - value={this.props.data.contents['#description']} - onChange={e => this.setContents({ ...this.props.data.contents, '#description': e.target.value})} - /> - </FormGroup> - </FormGroup> - <h4>Fields</h4> - <RecursiveObj obj={this.filteredContents()} dfs={this.allDfs()} updateFunc={(obj) => this.setContents(obj)} /> - </Form> - </div> - ); -} - -const mapStateToProps = (state, ownProps) => { - const dfs = Selectors.dataformatGet(state); - const obj = { - dataformats: dfs, - data: dfs[ownProps.index] || getValidObj() - }; - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`dataformatUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(DataformatEditor); diff --git a/conda/js/src/components/dataformat/DataformatEditor.spec.jsx b/conda/js/src/components/dataformat/DataformatEditor.spec.jsx deleted file mode 100644 index 280172ab..00000000 --- a/conda/js/src/components/dataformat/DataformatEditor.spec.jsx +++ /dev/null @@ -1,261 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import { getValidDataformatObj as getValidObj } from '@helpers/beat'; -import { DataformatEditor as C } from '.'; - -import testDfs from '@test/test_dfs.json'; - -describe('<DataformatEditor />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const dfs = [ - { - name: 'test/df/1', - contents: { - '#description': '', - 'field_1': 'string', - } - } - ].concat(testDfs.map(df => getValidObj(df))); - - dfs.forEach(function(df){ - const saveFunc = () => {}; - const updateFunc = () => {}; - it(`${ df.name }`, () => { - wrapper = mount( - <C - data={df} - dataformats={dfs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'dataformats', 'saveFunc', 'updateFunc'] - ).deep.equal( - [df, dfs, saveFunc, updateFunc] - ); - }); - }); - }); - - describe('creates', () => { - it('system/integer/1', () => { - const dfName = 'system/integer/1'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - wrapper = mount( - <C - data={getValidObj({name: dfName, contents: {}})} - dataformats={testDfs.filter(d => d.name !== dfName)} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'dataformats', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', dfName); - - wrapper.find('input[name="description"]').simulate('change', { target: { value: 'Single (32 bits) integer value'}}); - expect(wrapper.props().data.contents).to.have.property('#description', 'Single (32 bits) integer value'); - expect(updateFunc.callCount).to.equal(1); - - wrapper.find('button.btn-success').simulate('click'); - expect(updateFunc.callCount).to.equal(2); - wrapper.find('CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'value' }}); - expect(updateFunc.callCount).to.equal(3); - - wrapper.find('select').simulate('change', { target: { value: 'int32' }}); - expect(updateFunc.callCount).to.equal(4); - expect(wrapper.props().data.contents).to.have.property('value', 'int32'); - - expect(wrapper.props().data).to.deep.equal({ - 'name': 'system/integer/1', - 'contents': { - '#description': 'Single (32 bits) integer value', - 'value': 'int32' - } - }); - }); - - it('system/array_1d_text/1', () => { - const dfName = 'system/array_1d_text/1'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - wrapper = mount( - <C - data={getValidObj({name: dfName, contents: {}})} - dataformats={testDfs.filter(d => d.name !== dfName)} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'dataformats', 'saveFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', dfName); - - wrapper.find('button.btn-success').simulate('click'); - wrapper.find('CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'text' }}); - - wrapper.find('select').simulate('change', { target: { value: 'array' }}); - expect(wrapper.props().data.contents).to.have.deep.property('text', [0, 'string']); - - expect(wrapper.props().data).to.deep.equal({ - 'name': 'system/array_1d_text/1', - 'contents': { - '#description': '', - 'text': [ - 0, - 'string' - ] - } - }); - }); - - it('system/array_2d_floats/1', () => { - const dfName = 'system/array_2d_floats/1'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - wrapper = mount( - <C - data={getValidObj({name: dfName, contents: {}})} - dataformats={testDfs.filter(d => d.name !== dfName)} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'dataformats', 'saveFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', dfName); - - wrapper.find('input[name="description"]').simulate('change', { target: { value: 'Basic format containing a two-dimensional array of float values'}}); - expect(wrapper.props().data.contents).to.have.property('#description', 'Basic format containing a two-dimensional array of float values'); - - wrapper.find('button.btn-success').simulate('click'); - wrapper.find('CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'value' }}); - - wrapper.find('select').simulate('change', { target: { value: 'array' }}); - wrapper.find('input[type="number"][min="1"]').simulate('change', { target: { value: '2' }}); - wrapper.find('select').at(1).simulate('change', { target: { value: 'float64' }}); - - expect(wrapper.props().data.contents).to.have.deep.property('value', [0, 0, 'float64']); - - expect(wrapper.props().data).to.deep.equal({ - 'name': 'system/array_2d_floats/1', - 'contents': { - '#description': 'Basic format containing a two-dimensional array of float values', - 'value': [ - 0, - 0, - 'float64' - ] - } - }); - }); - - it('plot/bar/1', () => { - const dfName = 'plot/bar/1'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - wrapper = mount( - <C - data={getValidObj({name: dfName, contents: {}})} - dataformats={testDfs.filter(d => d.name !== dfName)} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'dataformats', 'saveFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', dfName); - - wrapper.find('input[name="description"]').simulate('change', { target: { value: 'Array of bar plots'}}); - expect(wrapper.props().data.contents).to.have.property('#description', 'Array of bar plots'); - - // 'data' field - wrapper.find('.dfLevel button.btn-success').simulate('click'); - wrapper.find('.dfLevel .field0 CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'data' }}); - wrapper.find('.dfLevel .field0 select').simulate('change', { target: { value: 'array' }}); - wrapper.find('.dfLevel .field0 select.subtype').simulate('change', { target: { value: 'object' }}); - expect(wrapper.props().data.contents).to.have.deep.property('data', [0, {}]); - - // 'label' subfield - wrapper.find('.dfLevel .field0 .dfLevel button.btn-success').simulate('click'); - wrapper.find('.dfLevel .field0 .dfLevel .field0 CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'label' }}); - wrapper.find('.dfLevel .field0 .dfLevel .field0 select').simulate('change', { target: { value: 'string' }}); - expect(wrapper.props().data.contents.data[1]).to.have.deep.property('label', 'string'); - - // 'x' subfield - wrapper.find('.dfLevel .field0 .dfLevel button.btn-success').simulate('click'); - wrapper.find('.dfLevel .field0 .dfLevel .field1 CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'x' }}); - wrapper.find('.dfLevel .field0 .dfLevel .field1 select').simulate('change', { target: { value: 'array' }}); - wrapper.find('.dfLevel .field0 .dfLevel .field1 select.subtype').simulate('change', { target: { value: 'float64' }}); - expect(wrapper.props().data.contents.data[1]).to.have.deep.property('x', [0, 'float64']); - - // 'y' subfield - wrapper.find('.dfLevel .field0 .dfLevel button.btn-success').simulate('click'); - wrapper.find('.dfLevel .field0 .dfLevel .field2 CacheInput[placeholder="Name..."]').prop('onChange')( { target: { value: 'y' }}); - wrapper.find('.dfLevel .field0 .dfLevel .field2 select').simulate('change', { target: { value: 'array' }}); - wrapper.find('.dfLevel .field0 .dfLevel .field2 select.subtype').simulate('change', { target: { value: 'float64' }}); - expect(wrapper.props().data.contents.data[1]).to.have.deep.property('y', [0, 'float64']); - - - expect(wrapper.props().data).to.deep.equal({ - 'name': 'plot/bar/1', - 'contents': { - '#description': 'Array of bar plots', - 'data': [ - 0, - { - 'label': 'string', - 'x': [ - 0, - 'float64' - ], - 'y': [ - 0, - 'float64' - ] - } - ] - } - }); - }); - }); -}); diff --git a/conda/js/src/components/dataformat/index.js b/conda/js/src/components/dataformat/index.js deleted file mode 100644 index 9a1ab793..00000000 --- a/conda/js/src/components/dataformat/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedDataformatEditor, {DataformatEditor} from './DataformatEditor.jsx'; - -export { - DataformatEditor, -}; - -export default ConnectedDataformatEditor; diff --git a/conda/js/src/components/experiment/ExperimentEditor.css b/conda/js/src/components/experiment/ExperimentEditor.css deleted file mode 100644 index be978991..00000000 --- a/conda/js/src/components/experiment/ExperimentEditor.css +++ /dev/null @@ -1,3 +0,0 @@ -.experimentEditor .fo { - cursor: pointer; -} diff --git a/conda/js/src/components/experiment/ExperimentEditor.jsx b/conda/js/src/components/experiment/ExperimentEditor.jsx deleted file mode 100644 index acc55144..00000000 --- a/conda/js/src/components/experiment/ExperimentEditor.jsx +++ /dev/null @@ -1,1398 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - Button, ButtonGroup, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, - Badge, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import cn from 'classnames'; - -import lev from 'fast-levenshtein'; - -import './ExperimentEditor.css'; -import { getValidExperimentObj as getValidObj, expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat'; -import type { BeatObject, ParameterValue, BeatEnvironment } from '@helpers/beat'; -import { changeObjFieldName, sortObject, copyObj } from '@helpers'; - -import * as Selectors from '@store/selectors.js'; -import * as Actions from '@store/actions.js'; - -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import CacheInput from '../CacheInput.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; -import InfoTooltip from '../InfoTooltip.jsx'; -import ParameterConsume from '../ParameterConsume.jsx'; - -import GraphicalEditor from '../toolchain/GraphicalEditor.jsx'; -import type { BlockSet } from '../toolchain/types.js'; -import { connectionToId } from '../toolchain/ToolchainConnection.jsx'; - -type Props = { - data: BeatObject, - experiments: BeatObject[], - normalBlocks: BeatObject[], - analyzerBlocks: BeatObject[], - datasets: any[], - toolchain: BeatObject, - environments: { [string]: BeatEnvironment }, - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, -}; - -type State = { - /* LockMap: map of which blocks are used in the type inference - * This is a per-block mapping of which blocks are used for type inference. - * There are more references (including some commented-out buttons & such) to - * block-level control of the lock map. Currently this is managed behind-the-scenes, - * where once a dataset/block has a valid dataset/algorithm assigned to it, - * its lock map value is true. The user can only influence this by disabling - * the entire lock map via "disable type inference" button. - */ - lockMap: LockMap, - // info for the modal for editing blocks - activeBlockInfo: { - set: ?BlockSet, - name: ?string, - }, - // is type inference disabled globally? - disableTypeInference: boolean, -}; - -type LockMap = { - [string]: boolean, -}; - -// parses a string resulting from the "datasetFieldToString" function into the original database, protocol, and set -const rxStringToDataset = /^(\S+)\/(\S+)\s\((\S+\/\d+)\)/; -// parses a string resulting from the "datasetProtocolFieldToString" function into the original database and protocol -const rxStringToDatasetProtocol = /^(\S+)\s\((\S+\/\d+)\)/; -// given a dataset obj (with database, protocol, and set fields), return a user-readable string representing this dataset -const datasetFieldToString = (dataset: any) => `${ dataset.protocol }/${ dataset.set } (${ dataset.database })`; -// given a dataset obj (with database, protocol, and set fields), return a user-readable string representing this dataset's protocol -const datasetProtocolFieldToString = (dataset: any) => `${ dataset.protocol } (${ dataset.database })`; -// given an algorithm, returns maps of the inputs and outputs of the algorithm (the i/o name mapped to its type) -const algIOs = (alg: any) => { - const inputs = alg.contents.groups.map(g => { - if(!g.inputs) - return []; - return Object.entries(g.inputs) - .map(([iName, tObj]) => ({[iName]: tObj.type})) - .reduce((o, iObj) => ({...o, ...iObj}), {}) - ; - }) - .reduce((o, is) => ({...o, ...is}), {}); - - const outputs = alg.contents.groups.map(g => { - if(!g.outputs) - return []; - return Object.entries(g.outputs) - .map(([iName, tObj]) => ({[iName]: tObj.type})) - .reduce((o, iObj) => ({...o, ...iObj}), {}) - ; - }) - .reduce((o, is) => ({...o, ...is}), {}); - - return [ - inputs, - outputs, - ]; -}; - -// given a block and the available algorithms, -// remap the chosen algorithm type data onto the block i/o names -const getBlockIOTypes = (block: any, algs: any[]) => { - const alg = algs.find(alg => alg.name === block.algorithm); - const [ais, aos] = alg ? algIOs(alg) : [{}, {}]; - const bis = Object.entries(block.inputs).reduce((o, [name, bi]) => ({...o, [bi]: ais[name] || ''}), {}); - const bos = Object.entries(block.outputs || {}).reduce((o, [name, bo]) => ({...o, [bo]: aos[name] || ''}), {}); - - return [bis, bos]; -}; - -// generate a new lock map for the given toolchain -const genLockMap = (toolchain: any): LockMap => [...toolchain.contents.datasets, ...toolchain.contents.blocks, ...toolchain.contents.analyzers] -.map(b => b.name) -.reduce((o, name) => ({...o, [name]: false}), {}); - -// checks if the given object is valid for the current entity given the i/o types and inferred types map -const isValidEntity = ( - entityName: string, - blockTcEntity: {inputs?: [], outputs?: []} = {}, - possibleObj: {inputs: any, outputs: any} = {inputs:{},outputs:{}}, - inferredTypes = {} -): boolean => { - const hasInputs = Array.isArray(blockTcEntity.inputs); - const hasOutputs = Array.isArray(blockTcEntity.outputs); - if(!hasInputs && Object.keys(possibleObj.inputs).length > 0) - return false; - if(!hasOutputs && Object.keys(possibleObj.outputs).length > 0) - return false; - if(hasInputs && blockTcEntity.inputs.length !== Object.keys(possibleObj.inputs).length) - return false; - if(hasInputs && hasOutputs && - blockTcEntity.outputs.length !== Object.keys(possibleObj.outputs).length - ) - return false; - - if(inferredTypes.hasOwnProperty(entityName)){ - if(inferredTypes[entityName][0] !== undefined){ - const remainingEntityInputTypes = Object.values(possibleObj.inputs); - const remainingInferredInputTypes = Object.values(inferredTypes[entityName][0]).filter(t => t !== ''); - while(remainingInferredInputTypes.length > 0){ - const it = remainingInferredInputTypes.pop(); - if(!remainingEntityInputTypes.includes(it)) - return false; - remainingEntityInputTypes.splice(remainingEntityInputTypes.indexOf(it), 1); - } - } - - if(inferredTypes[entityName][1] !== undefined){ - const remainingEntityOutputTypes = Object.values(possibleObj.outputs); - const remainingInferredOutputTypes = Object.values(inferredTypes[entityName][1]).filter(t => t !== ''); - while(remainingInferredOutputTypes.length > 0){ - const it = remainingInferredOutputTypes.pop(); - if(!remainingEntityOutputTypes.includes(it)) - return false; - remainingEntityOutputTypes.splice(remainingEntityOutputTypes.indexOf(it), 1); - } - } - } - - return true; -}; - -const dbSetIsValidForTcDataset = (dbSet, tcDs) => { - if(Object.keys(dbSet.outputs).length < tcDs.outputs.length) - return false; - if(!tcDs.outputs.reduce((b, output) => b && dbSet.outputs.hasOwnProperty(output), true)) - return false; - return true; -}; - -// maps key strings to value strings via levenshtein distances -// must have the same # of keys as vals -const levMapStrings = (keyArr: string[], valArr: string[]): { [string]: string } => { - if(keyArr.length !== valArr.length){ - throw new Error(`Cannot lev map arrays of different lengths!`); - } - - const keys = [...keyArr]; - const vals = [...valArr]; - const map = {}; - - //console.log(keys); - //console.log(vals); - - while(keys.length > 0){ - const scores = {}; - const matches = {}; - for(const k of keys){ - scores[k] = 10000; - matches[k] = 'notfound'; - for(const v of vals){ - const score = lev.get(k, v); - if(score < scores[k]){ - scores[k] = score; - matches[k] = v; - } - } - } - - let chosenKey = keys[0]; - let bestScore = 10000; - for(const k of keys){ - if(scores[k] < bestScore){ - chosenKey = k; - bestScore = scores[k]; - } - } - - map[chosenKey] = matches[chosenKey]; - keys.splice(keys.indexOf(chosenKey), 1); - vals.splice(vals.indexOf(matches[chosenKey]), 1); - //console.log(map); - } - - const orderedMap = {}; - for(const k of keyArr){ - orderedMap[k] = map[k]; - } - - //console.log(orderedMap); - return orderedMap; -}; - -type EnvironmentConfigProps = { - envInfo: { - name: string, - version: string, - }, - queue: string, - availableEnvs: { [string]: BeatEnvironment }, - updateEnvInfo: (name: string, version: string) => any, - updateQueue: (queue: string) => any, - disabled?: boolean, -}; - -const formatEnv = (name, version) => `${ name } (${ version })`; -const EnvironmentConfig = ({ envInfo, queue, availableEnvs, updateEnvInfo, updateQueue, disabled = false }: EnvironmentConfigProps) => { - const eObjs = Object.values(availableEnvs).map(e => ({[formatEnv(e.name, e.version)]: Object.keys(e.queues)})); - const envQueues = Object.assign({}, ...eObjs); - const currEnv = formatEnv(envInfo.name, envInfo.version); - const queues = envQueues[currEnv]; - return ( - <FormGroup row> - <Col> - <Label> - <InfoTooltip - id='envTooltip' - info={`When executing an experiment in a docker-ized execution system (on BEAT web or in beat.cmdline using the "--docker" flag), there are certain Python environments available to run the experiment in. To choose a non-default environment, select the environment (and queue) here.`} - > - Environment Name - </InfoTooltip> - </Label> - <Input - type='select' - className='env custom-select' - value={currEnv} - onChange={e => { - // deconstruct selected env - const rx = /^(.*) \((.*)\)$/; - const res = rx.exec(e.target.value); - if(!res) - return; - const [n, v] = res.slice(1, 3); - updateEnvInfo(n, v); - }} - placeholder='Environment' - disabled={disabled} - > - <option value={''}>Environment...</option> - { - Object.keys(envQueues).map((name, i) => - <option key={i} value={name}>{ name }</option> - ) - } - </Input> - </Col> - { Array.isArray(queues) && queues.length > 0 && - <Col> - <Label> - <InfoTooltip - id='queueTooltip' - info={`The "queue" refers to the job queue to put the experiment in once a user decides to run it. This setting currently is only used on the BEAT web platform, and has no effect if ran through beat.cmdline.`} - > - Queue - </InfoTooltip> - </Label> - <Input - type='select' - className='queue custom-select' - value={queue} - onChange={e => updateQueue(e.target.value)} - placeholder='Queue' - disabled={disabled} - > - { - (queues).map((queue, i) => - <option key={i} value={queue}>{ queue }</option> - ) - } - </Input> - </Col> - } - </FormGroup> - ); -}; - -export class ExperimentEditor extends React.Component<Props, State> { - constructor(props: Props) { - super(props); - } - - state = { - lockMap: genLockMap(this.props.toolchain), - activeBlockInfo: { - name: undefined, - set: undefined, - }, - disableTypeInference: false, - } - - setContents = (newContents: any) => { - this.props.updateFunc({ - ...this.props.data, - contents: { - 'description': this.props.data.contents['description'], - ...newContents, - } - }); - } - - // handles left clicking on a block - handleBlockClick = (blockName: string, set: BlockSet) => { - const newMBI = { - set, - name: blockName - }; - this.setState({ - activeBlockInfo: newMBI, - }); - - setTimeout(() => { - const elForm = document.querySelector(`.${ set === 'datasets' ? 'dataset' : 'block' }_${ blockName }`); - if(!elForm){ - return; - } - elForm.scrollIntoView(true); - }, 50); - } - - setLockMap = (name: string, value: boolean) => { - this.setState((prevState, props) => ({ - lockMap: { - ...prevState.lockMap, - [name]: value, - }, - })); - } - - // gets parameter data for all the blocks with selected algorithms - getParameterObjs = (): any[] => { - const algs = [...this.props.normalBlocks, ...this.props.analyzerBlocks]; - return Object.entries({...this.props.data.contents.blocks, ...this.props.data.contents.analyzers}) - .map(([bName, block]) => algs.find(a => a.name === block.algorithm)) - .filter(a => a !== null && a !== undefined && a.contents.parameters !== undefined && Object.keys(a.contents.parameters).length > 0) - .map(a => [a.name, a.contents.parameters]) - ; - } - - // tries to infer the types of inputs & outputs given the structure of the toolchain, - // the algorithms currently chosen for blocks, - // and the database/protocol/set currently chosen for datasets. - // Does forward (from datasets to analyzers) and backward (from analyzers to datasets). - getConnectionInferredTypes = (): any => { - const isLocked = (name) => !this.state.disableTypeInference && this.state.lockMap[name]; - - const dsTypes = Object.entries(this.props.data.contents.datasets) - .reduce((o, [name, ds]) => { - const d = this.props.datasets.find(pds => datasetFieldToString(pds) === datasetFieldToString(ds)); - const outputs = d ? d.outputs : {}; - return { - ...o, - [name]: [{}, outputs] - }; - }, {}); - - const nTypes = Object.entries(this.props.data.contents.blocks) - .filter(([name, block]) => isLocked(name)) - .reduce((o, [name, block]) => ({ - ...o, - [name]: getBlockIOTypes(block, this.props.normalBlocks), - }), {}); - - const aTypes = Object.entries(this.props.data.contents.analyzers) - .filter(([name, block]) => isLocked(name)) - .reduce((o, [name, block]) => ({ - ...o, - [name]: getBlockIOTypes(block, this.props.analyzerBlocks), - }), {}); - - const missingDatasets = [...this.props.toolchain.contents.datasets] - .filter(ds => !dsTypes.hasOwnProperty(ds.name)) - .reduce((o, ds) => ({ - ...o, - [ds.name]: [{}, ds.outputs.reduce((o, out) => ({...o, [out]: ''}), {})] - }), {}); - - const missingBlocks = Object.entries({ - ...this.props.data.contents.blocks, - ...this.props.data.contents.analyzers - }) - .filter(([name, block]) => !nTypes.hasOwnProperty(name) && !aTypes.hasOwnProperty(name)) - .reduce((o, [name, block]) => ({...o, [name]: getBlockIOTypes(block, [...this.props.normalBlocks, ...this.props.analyzerBlocks])}), {}); - - const inferredCache = Object.keys({...missingDatasets, ...missingBlocks}).reduce((o, name) => ({...o, [name]: []}), {}); - - const getSetTypes = (entityName: string) => { - if(dsTypes.hasOwnProperty(entityName)) - return dsTypes[entityName]; - if(nTypes.hasOwnProperty(entityName)) - return nTypes[entityName]; - if(aTypes.hasOwnProperty(entityName)) - return aTypes[entityName]; - return [{}, {}]; - }; - - // false === forwards, inferring input types - // true === backwards, inferring output types - const calcInferredType = (entityName: string, forwardsOrBackwards: boolean): [any, any][] => { - //forwards - if(!forwardsOrBackwards) { - const connectionsTo = this.props.toolchain.contents.connections.filter(c => c.to.split('.')[0] === entityName); - const types = connectionsTo.map(c => { - const [bName, oName] = c.from.split('.'); - const iName = c.to.split('.')[1]; - const fromTypes = getSetTypes(bName)[1]; - return [iName, fromTypes[oName] || '']; - }) - .reduce((o, [iName, type]) => ({...o, [iName]: o.hasOwnProperty(iName) ? (o[iName] === '' ? type : o[iName]) : type}), {}); - inferredCache[entityName] = [types, inferredCache[entityName][1]]; - } else { - const connectionsFrom = this.props.toolchain.contents.connections.filter(c => c.from.split('.')[0] === entityName); - const types = connectionsFrom.map(c => { - const [bName, iName] = c.to.split('.'); - const oName = c.from.split('.')[1]; - const toTypes = getSetTypes(bName)[0]; - return [oName, toTypes[iName] || '']; - }) - .reduce((o, [oName, type]) => ({...o, [oName]: o.hasOwnProperty(oName) ? (o[oName] === '' ? type : o[oName]) : type}), {}); - inferredCache[entityName] = [inferredCache[entityName][0], types]; - } - - return inferredCache[entityName]; - }; - - - Object.keys({...missingBlocks, ...missingDatasets}) - .forEach(name => { - calcInferredType(name, false); - calcInferredType(name, true); - }); - - return inferredCache; - }; - - // finds any issues/errors/misconfiguration throughout the experiment. things it checks: - // - whether a block doesnt have a dataset/algorithm assigned yet - // - whether a block with an algorithm doesnt have an input/output assigned yet - // - whether a connection of a block has different types at the output and input - getErrorMap = (): { - dataSourceMissing: string[], - algorithmMissing: string[], - ioMissing: string[], - } => { - const dataSourceMissing = Object.entries(this.props.data.contents.datasets) - .filter(([name, ds]) => ds.set === '') - .map(([name, b]) => name) - ; - - const algorithmMissing = [ - ...Object.entries(this.props.data.contents.blocks), - ...Object.entries(this.props.data.contents.analyzers), - ].filter(([name, b]) => b.algorithm === '') - .map(([name, b]) => name) - ; - - const ioMissing = [ - ...Object.entries(this.props.data.contents.blocks), - ...Object.entries(this.props.data.contents.analyzers), - ].filter(([name, b]) => { - if(b.algorithm === '') - return false; - const inputs = Object.values(b.inputs); - if(inputs.includes('') || Array.from(new Set(inputs)).length !== inputs.length) - return true; - if(b.hasOwnProperty('outputs')){ - const outputs = Object.values(b.outputs); - if(outputs.includes('') || Array.from(new Set(outputs)).length !== outputs.length) - return true; - } - return false; - }) - .map(([name, b]) => name) - ; - - const dsTypes = Object.entries(this.props.data.contents.datasets) - .reduce((o, [name, ds]) => { - const d = this.props.datasets.find(pds => datasetFieldToString(pds) === datasetFieldToString(ds)); - const outputs = d ? d.outputs : {}; - return { - ...o, - [name]: [{}, outputs] - }; - }, {}); - - const nTypes = Object.entries(this.props.data.contents.blocks) - .reduce((o, [name, block]) => ({ - ...o, - [name]: getBlockIOTypes(block, this.props.normalBlocks), - }), {}); - - const aTypes = Object.entries(this.props.data.contents.analyzers) - .reduce((o, [name, block]) => ({ - ...o, - [name]: getBlockIOTypes(block, this.props.analyzerBlocks), - }), {}); - // returns the connection ids instead of block names - const incompatibleConnectionTypes = this.props.toolchain.contents.hasOwnProperty('connections') ? - this.props.toolchain.contents.connections.map(c => { - const [fromBlock, fromOutput] = c.from.split('.'); - const [toBlock, toInput] = c.to.split('.'); - const fromTypes = dsTypes[fromBlock] || nTypes[fromBlock]; - if(!fromTypes) - return false; - const fromType = fromTypes[1][fromOutput]; - const toTypes = dsTypes[toBlock] || nTypes[toBlock]; - if(!toTypes) - return false; - const toType = toTypes[0][toInput]; - if(!fromType || !toType) - return false; - if(fromType === toType) - return false; - return connectionToId(c); - }).filter(id => id) : - [] - ; - - return { - dataSourceMissing, - algorithmMissing, - ioMissing, - incompatibleConnectionTypes, - }; - }; - - renderDatasets = () => ( - <FormGroup className='datasets'> - <FormGroup className='d-flex'> - <h3 className='mr-2'> - <InfoTooltip - id='datasetsTooltip' - info={`Assign sets from database protocols to your dataset blocks. Or, assign all your dataset blocks at once using a compatible database protocol.`} - > - Datasets - </InfoTooltip> - </h3> - <Input - type='select' - className='custom-select' - value={JSON.stringify(sortObject(this.props.data.contents.datasets))} - onChange={e => { - const str = e.target.value; - - const newDs = JSON.parse(str); - //console.log(newDs); - this.setContents({...this.props.data.contents, datasets: newDs}); - /* - for(const dataset in this.props.data.contents.datasets){ - this.setLockMap(dataset, true); - } - */ - }} - > - <option value=''>Protocol...</option> - { - Object.entries( - this.props.datasets - .reduce((o, ds) => { - const key = datasetProtocolFieldToString(ds); - return { - ...o, - [key]: [ - ...(o[key] || []), - ds - ] - }; - }, {}) - ) - .map(([dbProtStr, sets]) => { - const enoughSets = sets.length == Object.keys(this.props.data.contents.datasets).length; - if(!enoughSets) - return [dbProtStr, false]; - - // least to greatest outputs len - const tcDss = [...this.props.toolchain.contents.datasets] - .sort((a, b) => a.outputs.length - b.outputs.length); - - const newDataset = {}; - // start at greatest go to least - while(tcDss.length > 0){ - const tcDs = tcDss.pop(); - let setsIdx = sets.findIndex(set => set.set === tcDs.name && dbSetIsValidForTcDataset(set, tcDs)); - if(setsIdx === -1){ - const validSets = sets.filter(set => dbSetIsValidForTcDataset(set, tcDs)); - let bestScore = 10000; - let bestMatch = 'notfound'; - for(const s of validSets){ - const score = lev.get(tcDs.name, s.set); - if(score < bestScore){ - bestScore = score; - bestMatch = s; - } - } - setsIdx = sets.findIndex(set => set == bestMatch); - } - if(setsIdx === -1) - return [dbProtStr, false]; - - const dbSet = sets.splice(setsIdx, 1)[0]; - newDataset[tcDs.name] = { - set: dbSet.set, - protocol: dbSet.protocol, - database: dbSet.database, - }; - } - return [dbProtStr, newDataset]; - }) - .filter(([dbProtStr, dss]) => dss !== false) - .map(([dbProtStr, dss], i) => <option key={i} value={JSON.stringify(sortObject(dss))}>{dbProtStr}</option>) - } - </Input> - </FormGroup> - { - (Object.entries(this.props.data.contents.datasets): [string, any][]) - .sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1) - .map(([name, dataset], i, dEntries) => { - const inferredTypes = this.getConnectionInferredTypes(); - const tcDataset = this.props.toolchain.contents.datasets.find(d => d.name === name); - const dsString = datasetFieldToString(dataset); - return ( - <FormGroup row key={i} className={`dataset${ i } dataset_${ name }`}> - <Label sm={4}> - { name } - {' '} - <Badge - title={`This dataset provides the "${ name }" synchronization channel.`} - color='info' - > - { name } - </Badge> - {/* - {' '} - <Button - color={this.state.lockMap[name] ? 'primary' : 'secondary'} - title={`When unlocked, connected blocks will not restrict their available algorithms to those compatible with this dataset's output types. When locked, connected blocks will take into account this dataset's output types.`} - onClick={() => { - this.setLockMap(name, !this.state.lockMap[name] && dataset.set !== ''); - }} - > - { this.state.lockMap[name] ? 'Locked' : 'Unlocked' } - </Button> - */} - </Label> - <Col sm={8}> - <Input - type='select' - className='custom-select' - valid={dsString !== datasetFieldToString({database:'',protocol:'',set:''})} - value={dsString} - onChange={e => { - const str = e.target.value; - const res = rxStringToDataset.exec(str) || []; - const ds = { - set: res[2] || '', - protocol: res[1] || '', - database: res[3] || '', - }; - - const newDs = {...this.props.data.contents.datasets, [name]: ds}; - this.setContents({...this.props.data.contents, datasets: newDs}); - //this.setLockMap(name, true); - }} - > - <option value=''>Dataset...</option> - { - this.props.datasets - .filter(ds => dbSetIsValidForTcDataset(ds, tcDataset)) - .filter(ds => isValidEntity( - name, - tcDataset, - {outputs: ds.outputs, inputs: {}}, - inferredTypes - )) - .map(ds => datasetFieldToString(ds)) - .map((str, i) => - <option key={i} value={str}>{ str }</option> - ) - } - </Input> - </Col> - </FormGroup> - ); - }) - } - </FormGroup> - ); - - // update a block's data (and the globals object, if it changed) - updateBlock = (blockName: string, isAnalyzer: boolean, newBlock: any, globals: any = this.props.data.contents.globals) => { - if(isAnalyzer) - delete newBlock.outputs; - - const bKey = isAnalyzer ? 'analyzers' : 'blocks'; - const newBlocks = copyObj(this.props.data.contents[bKey]); - newBlocks[blockName] = newBlock; - this.setContents({ - ...this.props.data.contents, - [bKey]: newBlocks, - globals, - }); - } - - // renders the currently selected block to edit, if any - renderBlock = (blockName: string, block: any, isAnalyzer: boolean, key: number) => { - // gets the block info from the tc - const tcBlock = isAnalyzer ? this.props.toolchain.contents.analyzers.find(b => b.name === blockName) : this.props.toolchain.contents.blocks.find(b => b.name === blockName); - // gets the possible algorithms - const algorithms = isAnalyzer ? this.props.analyzerBlocks : this.props.normalBlocks; - - // finds the current algorithm, if any - const alg = algorithms.find(nb => nb.name === block.algorithm) || {contents: {groups: []}}; - // gets the input & output info of the current alg - const [ inputs, outputs ] = algIOs(alg); - - // calculates the inferred types throughout the experiment - const inferredTypes = this.getConnectionInferredTypes(); - - // filters through the algs based on shape (input/output count) and type inferrence - // to get the list of possible algs for this block - const possibleAlgorithms = algorithms.filter(pa => { - const [iAlg, oAlg] = algIOs(pa); - return isValidEntity(blockName, tcBlock, {inputs: iAlg, outputs: oAlg}, inferredTypes); - }); - - // func to update the exp's block info - const updateBlock = (newBlock: any, globals: any = this.props.data.contents.globals) => - this.updateBlock(blockName, isAnalyzer, newBlock, globals); - - // get info that could be from the block or from the global settings - const envInfo = block.environment || this.props.data.contents.globals.environment; - const queue = block.queue || this.props.data.contents.globals.queue; - const envDisabled = !block.hasOwnProperty('environment'); - - const getClearedGlobals = () => { - const globals = copyObj(this.props.data.contents.globals); - // if the old algorithm had parameters and no other block is using that alg, - // delete the global param defaults for the old alg - if(globals.hasOwnProperty(block.algorithm) && - [...this.props.toolchain.contents.analyzers, ...this.props.toolchain.contents.blocks] - .filter(b => b.algorithm === block.algorithm).length <= 1) - delete globals[block.algorithm]; - return globals; - }; - - return ( - <FormGroup key={key} className={`block${ key } block_${ blockName }`}> - <h4> - <InfoTooltip - id='blockTooltip' - info={`Choose a compatible algorithm for this block to run when execution reaches this place in the toolchain. When you choose an algorithm, inputs & outputs in the algorithm are automatically mapped to the inputs & outputs of the block - but make sure to check this mapping and manually fix incorrect assignments.`} - > - Block <pre className='preInline'>{ blockName }</pre> - </InfoTooltip> - {' '} - <Badge - title={`Block is synchronized to the "${ tcBlock.synchronized_channel }" channel`} - color='info' - >{ tcBlock.synchronized_channel }</Badge> - </h4> - <FormGroup row> - <Col sm='2'> - <Label>Execution Info</Label> - <Button - color={envDisabled ? 'secondary' : 'warning'} - onClick={() => { - if(envDisabled) - updateBlock({ - ...block, - environment: { - name: envInfo.name, - version: envInfo.version, - }, - queue: queue, - }); - else { - const newBlock = copyObj(block); - delete newBlock.environment; - delete newBlock.queue; - updateBlock(newBlock); - } - }} - title={`Toggle whether or not the block is using the global default value for execution information, or is using a custom setting for this specific block.`} - > - { envDisabled ? 'Using global defaults' : 'Using block value' } - </Button> - </Col> - <Col> - <EnvironmentConfig - envInfo={envInfo} - queue={queue} - availableEnvs={this.props.environments} - disabled={envDisabled} - updateEnvInfo={(name, version) => { - const env = Object.values(this.props.environments).find(e => e.name === name && e.version === version); - if(!env) - return; - const queue = Object.keys(env.queues)[0]; - updateBlock({ - ...block, - environment: { - name, - version, - }, - queue, - }); - }} - updateQueue={queue => updateBlock({ - ...block, - queue, - })} - /> - </Col> - </FormGroup> - <FormGroup className='algorithm'> - <Label> - Algorithm - </Label> - <FormGroup row> - <Col> - <Input - type='select' - className='custom-select' - valid={block.algorithm !== ''} - value={block.algorithm} - onChange={e => { - // user selected a different algorithm - const str = e.target.value; - // find the alg or use a dummy algorithm instead - const alg = algorithms.find(nb => nb.name === str) || {name: '', contents: {groups: []}}; - const [ inputs, outputs ] = algIOs(alg); - // try to map the IOs from the algorithm to the block via names - const findCloseIOMatch = (s: string, arr: string[]): string => { - if(arr.length === 1) - return arr[0]; - const findRes = arr.find(str => str.includes(s)); - if(findRes !== undefined) - return findRes; - return ''; - }; - - // create the new block obj with the new alg - const thisBlock = { - ...block, - algorithm: str, - }; - // assign new inputs - if(tcBlock.inputs) - thisBlock.inputs = levMapStrings(Object.keys(inputs), tcBlock.inputs); - // assign new outputs - if(tcBlock.outputs) - thisBlock.outputs = levMapStrings(Object.keys(outputs), tcBlock.outputs); - - // setup the parameters (erase & create stuff) - const globals = getClearedGlobals(); - - // if the new alg has parameters, gen the global defaults for the params - if(alg.contents.parameters && Object.keys(alg.contents.parameters).length > 0) - globals[alg.name] = { - ...Object.entries(alg.contents.parameters || {}) - .map(([pName, param]) => ({[pName]: getDefaultParameterValue(param)})) - .reduce((o, p) => ({...o, ...p}), {}), - ...this.props.data.contents.globals[alg.name], - }; - - updateBlock(thisBlock, globals); - //this.setLockMap(blockName, true); - }} - > - <option value=''>Algorithm...</option> - { - possibleAlgorithms - .map(nb => nb.name) - .map((str, i) => - <option key={i} value={str}>{ str }</option> - ) - } - </Input> - </Col> - <Col sm='auto'> - { !isAnalyzer && - <React.Fragment> - <Button - color='primary' - disabled={block.algorithm === ''} - title={`Copies the algorithm & IO mappings to all unconfigured blocks with the same inputs & outputs`} - onClick={() => { - // copy the algorithm and input/output mappings to blocks - // that are the same except for the block name and dont have an algorithm assigned already - const targetBlocks = this.props.toolchain.contents.blocks - // not the block being copied from - .filter(b => b.name !== blockName) - // same IO - .filter(b => JSON.stringify(b.inputs) === JSON.stringify(tcBlock.inputs)) - .filter(b => JSON.stringify(b.outputs) === JSON.stringify(tcBlock.outputs)) - .map(b => b.name) - ; - //console.log(targetBlocks); - - // because the target blocks have the exact same inputs/outputs as the current block - // we dont need to re-compute the block object that we will copy! - // instead, just reuse the current block object and assign it to all - // the target blocks. - // also, because all these blocks are the same algorithm as the current block - // we dont need to mess with the globals. - - const newBlocks = copyObj(this.props.data.contents.blocks); - targetBlocks.forEach(bName => { newBlocks[bName] = copyObj(block); }); - this.setContents({ - ...this.props.data.contents, - blocks: newBlocks, - }); - }} - > - Copy to similar blocks - </Button> - {' '} - </React.Fragment> - } - <Button - color='secondary' - title={`Clears the block data, resetting the selected block.`} - onClick={() => { - const newBlock = copyObj(block); - const newGlobals = getClearedGlobals(); - newBlock.algorithm = ''; - if(newBlock.inputs) - newBlock.inputs = {}; - if(newBlock.outputs) - newBlock.outputs = {}; - if(newBlock.parameters) - newBlock.parameters = {}; - - updateBlock(newBlock, newGlobals); - }} - > - Reset - </Button> - </Col> - </FormGroup> - </FormGroup> - { Object.entries(alg.contents.parameters || {}).length > 0 && <h5>Parameters</h5> } - { - Object.entries(alg.contents.parameters || {}).map(([pName, paramObj], i) => { - const isTethered = !block.parameters.hasOwnProperty(pName); - const globalParams = this.props.data.contents.globals[alg.name]; - const currVal = block.parameters[pName] || globalParams[pName]; - - const deleteParam = () => { - const thisBlock = {...block, - }; - delete block.parameters[pName]; - updateBlock(thisBlock); - }; - const updateParam = (val: ParameterValue) => { - const thisBlock = {...block, - parameters: {...block.parameters, - [pName]: val - } - }; - updateBlock(thisBlock); - }; - - return ( - <FormGroup key={i} className={`parameter${ i }`}> - <Label> - { pName } - </Label> - <FormGroup row> - <Col sm='auto'> - <Button - color={isTethered ? 'secondary' : 'warning'} - onClick={() => { - if(isTethered){ - updateParam(currVal); - } else { - deleteParam(); - } - }} - title={`Toggle whether or not the block is using the global default value for this parameter, or is using a custom value for this specific block.`} - > - { isTethered ? 'Using global defaults' : 'Using block value' } - </Button> - </Col> - <Col> - <ParameterConsume - parameter={paramObj} - currVal={currVal} - updateFunc={updateParam} - /> - </Col> - </FormGroup> - </FormGroup> - ); - }) - } - <h5>Inputs</h5> - { - Object.entries(inputs).map(([iName, type], i, inputs) => { - const iLabel = `${ iName } (${ type })`; - const value = block.inputs[iName] || ''; - const foundCount = Object.values(block.inputs).filter(s => s === value).length; - return ( - <FormGroup row key={i} className={`input${ i }`}> - <Label sm={6}>{ iLabel }</Label> - <Col sm={6}> - <Input - type='select' - className='custom-select' - valid={value !== '' && foundCount === 1} - value={value} - onChange={e => { - const str = e.target.value; - const thisBlock = { - ...block, - inputs: {...block.inputs, [iName]: str} - }; - for(const key in block.inputs){ - if(block.inputs[key] === str) - thisBlock.inputs[key] = value; - } - updateBlock(thisBlock); - }} - > - <option value=''>Input...</option> - { - tcBlock.inputs - .map((str, i) => - <option key={i} value={str}>{ str }</option> - ) - } - </Input> - </Col> - </FormGroup> - ); - }) - } - { Object.keys(outputs).length > 0 && <h5>Outputs</h5> } - { - Object.entries(outputs).map(([oName, type], i) => { - const oLabel = `${ oName } (${ type })`; - const value = block.outputs[oName] || ''; - const foundCount = Object.values(block.outputs).filter(s => s === value).length; - return ( - <FormGroup row key={i} className={`output${ i }`}> - <Label sm={6}>{ oLabel }</Label> - <Col sm={6}> - <Input - type='select' - className='custom-select' - valid={value !== '' && foundCount === 1} - value={value} - onChange={e => { - const str = e.target.value; - const thisBlock = { - ...block, - outputs: {...block.outputs, [oName]: str} - }; - for(const key in block.outputs){ - if(block.outputs[key] === str) - thisBlock.outputs[key] = value; - } - updateBlock(thisBlock); - }} - > - <option value=''>Output...</option> - { - tcBlock.outputs - .map((str, i) => - <option key={i} value={str}>{ str }</option> - ) - } - </Input> - </Col> - </FormGroup> - ); - }) - } - - </FormGroup> - ); - } - - renderBlocks = () => this.state.activeBlockInfo.set === 'blocks' && ( - <FormGroup> - { - (Object.entries(this.props.data.contents.blocks): [string, any][]) - .filter(([n, b]) => n === this.state.activeBlockInfo.name) - .sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1) - .map(([name, blk], i) => - this.renderBlock(name, blk, false, i) - ) - } - </FormGroup> - ); - - renderAnalyzers = () => this.state.activeBlockInfo.set === 'analyzers' && ( - <FormGroup> - <h3>Analyzers</h3> - { - (Object.entries(this.props.data.contents.analyzers): [string, any][]) - .filter(([n, b]) => n === this.state.activeBlockInfo.name) - .sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1) - .map(([name, blk], i) => - this.renderBlock(name, blk, true, i) - ) - } - </FormGroup> - ) - - renderGlobals = () => { - const paramObjs = this.getParameterObjs(); - return ( - <FormGroup className='globals'> - <h3> - <InfoTooltip - id='globalSettingsTooltip' - info={`These settings are for the entire experiment, not for a specific block.`} - > - Global Settings - </InfoTooltip> - </h3> - <EnvironmentConfig - envInfo={this.props.data.contents.globals.environment} - queue={this.props.data.contents.globals.queue} - availableEnvs={this.props.environments} - updateEnvInfo={(name, version) => this.setContents({ - ...this.props.data.contents, - globals: { - ...this.props.data.contents.globals, - environment: { - ...this.props.data.contents.globals.environment, - name, - version, - }, - queue: '', - } - })} - updateQueue={queue => this.setContents({ - ...this.props.data.contents, - globals: { - ...this.props.data.contents.globals, - queue, - } - })} - /> - { paramObjs.length > 0 && - <h3> - Algorithm Parameter Defaults - </h3> - } - { - paramObjs.map(([algName, ps], i) => ( - <FormGroup key={i} className={`globalParameter${ i }`}> - <h4>{ algName }</h4> - { - Object.entries(ps).map(([pName, paramObj], j) => ( - <FormGroup key={j}> - <Label for={`${ algName }/${ pName }`}>{ pName }</Label> - <ParameterConsume - name={`${ algName }/${ pName }`} - parameter={paramObj} - currVal={this.props.data.contents.globals[algName][pName]} - updateFunc={(val: ParameterValue) => { - const globals = { - ...this.props.data.contents.globals, - [algName]: { - ...this.props.data.contents.globals[algName], - [pName]: val - } - }; - this.setContents({ - ...this.props.data.contents, - globals - }); - }} - /> - </FormGroup> - )) - } - </FormGroup> - )) - } - </FormGroup> - ); - } - - renderGraphicalEditor = () => { - const tc = this.props.toolchain; - const {representation, blocks, datasets, analyzers, connections} = tc.contents; - const groups = tc.extraContents ? tc.extraContents.groups : []; - const expData = [ - ...Object.entries(this.props.data.contents.datasets) - .map(([name, ds]) => ({ [name]: datasetFieldToString(ds) })), - ...Object.entries(this.props.data.contents.blocks) - .map(([name, b]) => ({ [name]: b.algorithm })), - ...Object.entries(this.props.data.contents.analyzers) - .map(([name, a]) => ({ [name]: a.algorithm })), - ].reduce((o, data) => ({ ...o, ...data }), {}); - const errorMap = this.getErrorMap(); - const errorStrings: { [string]: string[] } = ((Object.entries(errorMap): any): [ string, string[] ][]) - .map(([ error, names ]) => names.reduce((o, n) => { - let errorMessage = ''; - // messages need to be short enough to not be clipped (up to 1 char longer than the ioMissing message) - switch(error){ - case 'dataSourceMissing': - errorMessage = 'Data source not assigned!'; - break; - case 'algorithmMissing': - errorMessage = 'Algorithm not assigned!'; - break; - case 'ioMissing': - errorMessage = 'Input/output not assigned!'; - break; - case 'incompatibleConnectionTypes': - errorMessage = '. Connection has incompatible start/end types!'; - break; - default: - errorMessage = error; - break; - } - return {...o, [n]: errorMessage}; - }, {})) - .reduce((o, errors) => { - Object.entries(errors).forEach(([name, errorString]) => { - if(o.hasOwnProperty(name)) - o[name].push(errorString); - else - o[name] = [errorString]; - }); - return o; - }, {}); - - const scrollToGlobalSettings = (e) => { - const elSettings = document.querySelector('.globals'); - if(!elSettings){ - return; - } - elSettings.scrollIntoView(true); - }; - - return ( - <FormGroup row> - <Col sm={12}> - <GraphicalEditor - repData={representation || {blocks: {}, connections: {}, channel_colors: {}}} - blocks={blocks || []} - datasets={datasets || []} - analyzers={analyzers || []} - connections={connections || []} - groups={groups} - experimentData={expData} - handleBlockClick={this.handleBlockClick} - errorBlocks={errorStrings} - focusBlocks={[this.state.activeBlockInfo.name || '']} - handleBackgroundClick={scrollToGlobalSettings} - /> - </Col> - </FormGroup> - ); - } - - render = () => ( - <div className='experimentEditor'> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='experiment' obj={this.props.data} />) - </Button> - </div> - <Form onSubmit={(e) => e.preventDefault()}> - <FormGroup tag='fieldset'> - <FormGroup> - <Label>Short Description</Label> - <Input - type='text' - className='expDescription' - placeholder='Experiment description...' - value={this.props.data.contents['description']} - onChange={e => this.setContents({ ...this.props.data.contents, 'description': e.target.value})} - /> - </FormGroup> - </FormGroup> - {/* - <pre>{JSON.stringify(this.getConnectionInferredTypes(), null, 4)}</pre> - */} - { this.renderGraphicalEditor() } - <FormGroup> - <Button block outline - onClick={e => { - this.setState({ disableTypeInference: !this.state.disableTypeInference }); - }} - title={`When assigning algorithms & datasets to blocks, the platform tries to infer types throughout the toolchain to filter the possibilities. If you don't want any filtering, you may turn this feature off to be able to select any compatible algorithm/dataset. You may re-enable filtering at any time by clicking the button again.`} - > - { this.state.disableTypeInference ? 'Enable' : 'Disable' } Type Inference - </Button> - </FormGroup> - { this.state.activeBlockInfo.set === 'blocks' && this.renderBlocks() } - { this.state.activeBlockInfo.set === 'analyzers' && this.renderAnalyzers() } - { this.state.activeBlockInfo.set === 'datasets' && this.renderDatasets() } - { this.renderGlobals() } - </Form> - </div> - ); -} - -const mapStateToProps = (state, ownProps) => { - const exps = Selectors.experimentGet(state); - const data = exps[ownProps.index] || undefined; - const tcName = data ? data.name.split('/').slice(1, 4).join('/') : ''; - const tc = Selectors.toolchainGet(state).find(t => t.name === tcName) || { - name: '', - contents: { - blocks: [], - analyzers: [], - datasets: [], - } - }; - const normalBlocks = Selectors.normalBlocks(state); - const analyzerBlocks = Selectors.analyzerBlocks(state); - - const obj = { - experiments: exps, - data: data || getValidObj({name: '', contents: {}}, tc, [normalBlocks, ...analyzerBlocks]), - // algorithms for normal blocks - normalBlocks, - // algorithms for analyzer blocks - analyzerBlocks, - datasets: Selectors.flattenedDatabases(state), - toolchain: tc, - environments: Selectors.environmentsGet(state), - }; - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`experimentUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(ExperimentEditor); diff --git a/conda/js/src/components/experiment/ExperimentEditor.spec.jsx b/conda/js/src/components/experiment/ExperimentEditor.spec.jsx deleted file mode 100644 index 017ee392..00000000 --- a/conda/js/src/components/experiment/ExperimentEditor.spec.jsx +++ /dev/null @@ -1,694 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import * as Selectors from '@store/selectors.js'; -import { ExperimentEditor as C } from '.'; -import { getValidExperimentObj as getValidObj } from '@helpers/beat'; - -import testAlgs from '@test/test_algs.json'; -import testDbs from '@test/test_dbs.json'; -import testExps from '@test/test_exps.json'; -import testTcs from '@test/test_tcs.json'; - -const envs = { - 'Scientific Python 2.7': { - name: 'Scientific Python 2.7', - version: '1.0.0', - queues: { - Default: {} - }, - packages: {} - } -}; - -describe('<ExperimentEditor />', () => { - let wrapper; - const normalBlocks = Selectors.normalBlocks({ algorithm: testAlgs }); - const analyzerBlocks = Selectors.analyzerBlocks({ algorithm: testAlgs }); - const datasets = Selectors.flattenedDatabases({ database: testDbs }); - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const exps = [ - ].concat(testExps); - - exps.forEach(function(exp){ - if(exp.name !== 'user/user/single/1/single_add') - return; - const saveFunc = () => {}; - const updateFunc = () => {}; - const tc = testTcs.find(tc => exp.name.includes(tc.name)); - - it(`${ exp.name }`, () => { - wrapper = mount( - <C - data={exp} - experiments={exps} - normalBlocks={normalBlocks} - analyzerBlocks={analyzerBlocks} - datasets={datasets} - toolchain={tc} - saveFunc={saveFunc} - environments={envs} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'experiments', 'normalBlocks', 'analyzerBlocks', 'datasets', 'toolchain', 'saveFunc', 'environments', 'updateFunc'] - ); - }); - }); - }); - - describe('creates', () => { - it(`user/user/single/1/single_add`, () => { - const expName = 'user/user/single/1/single_add'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const tc = testTcs.find(tc => expName.includes(tc.name)); - wrapper = mount( - <C - data={getValidObj({name: expName, contents: {}}, tc, [...normalBlocks, ...analyzerBlocks])} - experiments={[]} - normalBlocks={normalBlocks} - analyzerBlocks={analyzerBlocks} - datasets={datasets} - toolchain={tc} - saveFunc={saveFunc} - environments={envs} - updateFunc={updateFunc} - /> - ); - - //console.log('doing name'); - - expect(wrapper.props().data).to.have.property('name', expName); - - //console.log('finished name change, doing dataset'); - - wrapper.find('svg #block_set').simulate('click'); - wrapper.find('div.dataset0 select').simulate('change', { target: { value: 'protocol/set (simple/1)'}}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.deep.property('datasets', { - 'set': { - 'set': 'set', - 'protocol': 'protocol', - 'database': 'simple/1' - } - }); - - //console.log('finished dataset, doing block'); - - wrapper.find('svg #block_echo').simulate('click'); - expect(wrapper.find({ name: 'echo', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'user/integers_add/1'}}); - expect(updateFunc.callCount).to.equal(2); - expect(wrapper.props().data.contents).to.have.deep.property('blocks', { - 'echo': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_add/1', - 'outputs': { - 'out_data': 'out' - }, - parameters: {} - } - }); - - //console.log('finished block, doing analyzer'); - - wrapper.find('svg #block_analysis').simulate('click'); - expect(wrapper.find({ name: 'analysis', set: 'analyzers'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'user/integers_echo_analyzer/1'}}); - expect(updateFunc.callCount).to.equal(3); - expect(wrapper.props().data.contents).to.have.deep.property('analyzers', { - 'analysis': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_echo_analyzer/1', - parameters: {}, - } - }); - - //console.log('finished analyzer, doing env'); - - wrapper.find('.globals select.env').simulate('change', { target: { value: 'Scientific Python 2.7 (1.0.0)'}}); - expect(updateFunc.callCount).to.equal(4); - wrapper.find('.globals select.queue').simulate('change', { target: { value: 'Default'}}); - expect(updateFunc.callCount).to.equal(5); - expect(wrapper.props().data.contents).to.have.deep.property('globals', { - 'queue': 'Default', - 'environment': { - 'version': '1.0.0', - 'name': 'Scientific Python 2.7' - }, - 'user/integers_add/1': { - offset: 1 - }, - }); - - //console.log('finished env, doing cache check'); - - expect(wrapper.props().data).to.be.deep.equal({ - 'name': 'user/user/single/1/single_add', - 'contents': { - description: '', - 'analyzers': { - 'analysis': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_echo_analyzer/1', - parameters: {}, - } - }, - 'datasets': { - 'set': { - 'set': 'set', - 'protocol': 'protocol', - 'database': 'simple/1' - } - }, - 'blocks': { - 'echo': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_add/1', - 'outputs': { - 'out_data': 'out' - }, - parameters: {} - } - }, - 'globals': { - 'queue': 'Default', - 'environment': { - 'version': '1.0.0', - 'name': 'Scientific Python 2.7' - }, - 'user/integers_add/1': { - offset: 1 - }, - } - } - }); - }); - - // tests: - // - assigning protocol for datasets - // - copy block algs - it('test/test/iris_advanced/1/iris', () => { - const expName ='test/test/iris_advanced/1/iris'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const tc = testTcs.find(tc => expName.includes(tc.name)); - wrapper = mount( - <C - data={getValidObj({name: expName, contents: {}}, tc, [...normalBlocks, ...analyzerBlocks])} - experiments={[]} - normalBlocks={normalBlocks} - analyzerBlocks={analyzerBlocks} - datasets={datasets} - toolchain={tc} - saveFunc={saveFunc} - environments={envs} - updateFunc={updateFunc} - /> - ); - - expect(wrapper.props().data).to.have.property('name', expName); - - //console.log('doing dataset'); - - wrapper.find('svg #block_training_data').simulate('click'); - wrapper.find('div.datasets select').at(0).simulate('change', { target: { value: '{"testing_data":{"database":"iris/1","protocol":"Main","set":"testing"},"training_data":{"database":"iris/1","protocol":"Main","set":"training"}}'}}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.deep.property('datasets', { - 'testing_data': { - 'database': 'iris/1', - 'protocol': 'Main', - 'set': 'testing' - }, - 'training_data': { - 'database': 'iris/1', - 'protocol': 'Main', - 'set': 'training' - } - }); - - //console.log('finished dataset, doing preprocessor blocks'); - - wrapper.find('svg #block_pre_training').simulate('click'); - expect(wrapper.find({ name: 'pre_training', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_preprocessor/1'}}); - //console.log('finished preprocessor_training, copying alg to other preprocessors'); - expect(updateFunc.callCount).to.equal(2); - wrapper.find('div.block0 div.algorithm button').at(0).simulate('click'); - expect(updateFunc.callCount).to.equal(3); - - expect(wrapper.props().data.contents).to.have.deep.property('blocks', { - 'pre_testing': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'pre_training': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'testing_alg': { - 'algorithm': '', - 'inputs': { - 'lda_machine': '', - 'measurements': '' - }, - 'outputs': { - 'scores': '' - }, - 'parameters': {} - }, - 'training_alg': { - 'algorithm': '', - 'inputs': { - 'measurements': '', - 'species': '' - }, - 'outputs': { - 'lda_machine': '' - }, - 'parameters': {} - } - }); - - //console.log('finished preprocessors, doing training'); - - wrapper.find('svg #block_training_alg').simulate('click'); - expect(wrapper.find({ name: 'training_alg', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_training/1'}}); - expect(updateFunc.callCount).to.equal(4); - expect(wrapper.props().data.contents).to.have.deep.property('blocks', { - 'pre_testing': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'pre_training': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'testing_alg': { - 'algorithm': '', - 'inputs': { - 'lda_machine': '', - 'measurements': '' - }, - 'outputs': { - 'scores': '' - }, - 'parameters': {} - }, - 'training_alg': { - 'algorithm': 'test/iris_training/1', - 'inputs': { - 'measurements': 'measurements', - 'species': 'species' - }, - 'outputs': { - 'lda_machine': 'lda_machine' - }, - 'parameters': {} - } - }); - - //console.log('finished training, doing testing'); - - wrapper.find('svg #block_testing_alg').simulate('click'); - expect(wrapper.find({ name: 'testing_alg', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_testing/1'}}); - expect(updateFunc.callCount).to.equal(5); - expect(wrapper.props().data.contents).to.have.deep.property('blocks', { - 'pre_testing': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'pre_training': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'testing_alg': { - 'algorithm': 'test/iris_testing/1', - 'inputs': { - 'lda_machine': 'lda_machine', - 'measurements': 'measurements' - }, - 'outputs': { - 'scores': 'scores' - }, - 'parameters': {} - }, - 'training_alg': { - 'algorithm': 'test/iris_training/1', - 'inputs': { - 'measurements': 'measurements', - 'species': 'species' - }, - 'outputs': { - 'lda_machine': 'lda_machine' - }, - 'parameters': {} - } - }); - - //console.log('finished blocks, doing analyzer'); - - wrapper.find('svg #block_analyzer').simulate('click'); - expect(wrapper.find({ name: 'analyzer', set: 'analyzers'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_analyzer/1'}}); - expect(updateFunc.callCount).to.equal(6); - expect(wrapper.props().data.contents).to.have.deep.property('analyzers', { - 'analyzer': { - 'algorithm': 'test/iris_analyzer/1', - 'inputs': { - 'scores': 'scores', - 'species': 'species' - }, - 'parameters': {} - } - }); - - //console.log('finished analyzer, doing cache check'); - - expect(wrapper.props().data).to.be.deep.equal({ - 'name': 'test/test/iris_advanced/1/iris', - 'contents': { - 'description': '', - 'analyzers': { - 'analyzer': { - 'algorithm': 'test/iris_analyzer/1', - 'inputs': { - 'scores': 'scores', - 'species': 'species' - }, - 'parameters': {} - } - }, - 'blocks': { - 'pre_testing': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'pre_training': { - 'algorithm': 'test/iris_preprocessor/1', - 'inputs': { - 'measurements': 'measurements' - }, - 'outputs': { - 'measurements': 'measurements' - }, - 'parameters': {} - }, - 'testing_alg': { - 'algorithm': 'test/iris_testing/1', - 'inputs': { - 'lda_machine': 'lda_machine', - 'measurements': 'measurements' - }, - 'outputs': { - 'scores': 'scores' - }, - 'parameters': {} - }, - 'training_alg': { - 'algorithm': 'test/iris_training/1', - 'inputs': { - 'measurements': 'measurements', - 'species': 'species' - }, - 'outputs': { - 'lda_machine': 'lda_machine' - }, - 'parameters': {} - } - }, - 'datasets': { - 'testing_data': { - 'database': 'iris/1', - 'protocol': 'Main', - 'set': 'testing' - }, - 'training_data': { - 'database': 'iris/1', - 'protocol': 'Main', - 'set': 'training' - } - }, - 'globals': { - 'queue': 'Default', - 'environment': { - 'name': 'Scientific Python 2.7', - 'version': '0.0.4' - } - } - } - }); - }); - }); - - describe('Regression Tests', () => { - it(`clears the 'echo' & 'analysis' blocks from user/user/single/1/single_add`, () => { - const expName = 'user/user/single/1/single_add'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const exp = testExps.find(exp => expName === exp.name); - const tc = testTcs.find(tc => expName.includes(tc.name)); - wrapper = mount( - <C - data={getValidObj(exp, tc, [...normalBlocks, ...analyzerBlocks])} - experiments={[]} - normalBlocks={normalBlocks} - analyzerBlocks={analyzerBlocks} - datasets={datasets} - toolchain={tc} - saveFunc={saveFunc} - environments={envs} - updateFunc={updateFunc} - /> - ); - - expect(wrapper.props().data).to.have.property('name', expName); - expect(wrapper.props().data.contents).to.have.deep.property('blocks', { - 'echo': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_add/1', - 'outputs': { - 'out_data': 'out' - }, - parameters: {} - } - }); - - wrapper.find('svg #block_echo').simulate('click'); - wrapper.update(); - wrapper.find('.algorithm button.btn-secondary').simulate('click'); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.deep.property('blocks', - { echo: { - inputs: {}, - algorithm: '', - outputs: {}, - parameters: {} - }} - ); - - wrapper.find('svg #block_analysis').simulate('click'); - wrapper.update(); - wrapper.find('.algorithm button.btn-secondary').simulate('click'); - expect(updateFunc.callCount).to.equal(2); - expect(wrapper.props().data.contents).to.have.deep.property('analyzers', - { analysis: { - inputs: {}, - algorithm: '', - parameters: {} - }} - ); - - expect(wrapper.props().data).to.be.deep.equal({ - 'name': 'user/user/single/1/single_add', - 'contents': { - description: '', - 'analyzers': { - 'analysis': { - inputs: {}, - algorithm: '', - parameters: {} - } - }, - 'datasets': { - 'set': { - 'set': 'set', - 'protocol': 'protocol', - 'database': 'simple/1' - } - }, - 'blocks': { - 'echo': { - algorithm: '', - inputs: {}, - outputs: {}, - parameters: {} - } - }, - 'globals': { - 'queue': 'queue', - 'environment': { - 'version': '1.2.0', - 'name': 'Python 2.7' - }, - } - } - }); - }); - - it(`doesnt change the lockMap after an algorithm or dataset is assigned`, () => { - const expName = 'user/user/single/1/single_add'; - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const tc = testTcs.find(tc => expName.includes(tc.name)); - wrapper = mount( - <C - data={getValidObj({name: expName, contents: {}}, tc, [...normalBlocks, ...analyzerBlocks])} - experiments={[]} - normalBlocks={normalBlocks} - analyzerBlocks={analyzerBlocks} - datasets={datasets} - toolchain={tc} - saveFunc={saveFunc} - environments={envs} - updateFunc={updateFunc} - /> - ); - - expect(wrapper.props().data).to.have.property('name', expName); - - //console.log('finished name change, doing dataset'); - - wrapper.find('svg #block_set').simulate('click'); - wrapper.find('div.dataset0 select').simulate('change', { target: { value: 'protocol/set (simple/1)'}}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.deep.property('datasets', { - 'set': { - 'set': 'set', - 'protocol': 'protocol', - 'database': 'simple/1' - } - }); - - //console.log('finished dataset, doing block'); - - wrapper.find('svg #block_echo').simulate('click'); - expect(wrapper.find({ name: 'echo', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'user/integers_add/1'}}); - expect(updateFunc.callCount).to.equal(2); - expect(wrapper.props().data.contents).to.have.deep.property('blocks', { - 'echo': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_add/1', - 'outputs': { - 'out_data': 'out' - }, - parameters: {} - } - }); - - //console.log('finished block, doing analyzer'); - - wrapper.find('svg #block_analysis').simulate('click'); - expect(wrapper.find({ name: 'analysis', set: 'analyzers'}).find('.tcBlockBackground').prop('className')).to.include('highlighted'); - wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'user/integers_echo_analyzer/1'}}); - expect(updateFunc.callCount).to.equal(3); - expect(wrapper.props().data.contents).to.have.deep.property('analyzers', { - 'analysis': { - 'inputs': { - 'in_data': 'in' - }, - 'algorithm': 'user/integers_echo_analyzer/1', - parameters: {}, - } - }); - - expect(wrapper.state().lockMap).to.deep.equal({ - set: false, - echo: false, - analysis: false, - }); - }); - }); -}); diff --git a/conda/js/src/components/experiment/index.js b/conda/js/src/components/experiment/index.js deleted file mode 100644 index f530318b..00000000 --- a/conda/js/src/components/experiment/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedExperimentEditor, {ExperimentEditor} from './ExperimentEditor.jsx'; - -export { - ExperimentEditor, -}; - -export default ConnectedExperimentEditor; diff --git a/conda/js/src/components/library/LibraryEditor.jsx b/conda/js/src/components/library/LibraryEditor.jsx deleted file mode 100644 index a241194e..00000000 --- a/conda/js/src/components/library/LibraryEditor.jsx +++ /dev/null @@ -1,188 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - Button, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import { getValidLibraryObj as getValidObj } from '@helpers/beat'; -import type { BeatObject } from '@helpers/beat'; -import { changeObjFieldName, copyObj } from '@helpers'; - -import * as Selectors from '@store/selectors.js'; - -import * as Actions from '@store/actions.js'; -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import CacheInput from '../CacheInput.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; -import TemplateButton from '../EntityTemplateGenerationButton.jsx'; - -type Props = { - data: BeatObject, - libraries: BeatObject[], - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, -}; - -export class LibraryEditor extends React.Component<Props> { - constructor(props: Props) { - super(props); - } - - setContents = (newContents: any) => { - this.props.updateFunc({ - ...this.props.data, - contents: newContents - }); - } - - updateLibraries = (libraries: {}) => { - this.setContents({...this.props.data.contents, uses: libraries}); - } - - render = () => { - const data = this.props.data; - - return ( - <div> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='library' obj={data} />) - </Button> - <TemplateButton - data={data} - entity={'library'} - /> - </div> - <Form onSubmit={(e) => e.preventDefault()}> - <FormGroup tag='fieldset'> - <legend>Library Settings</legend> - <FormGroup> - <Label for='description'>Short Description</Label> - <CacheInput - type='text' - name='description' - placeholder='Library description...' - value={data.contents['description']} - onChange={e => this.setContents({ ...data.contents, 'description': e.target.value})} - /> - </FormGroup> - <FormGroup> - <Label>Language</Label> - <Input - id='libLanguage' - type='select' - className='custom-select' - value={data.contents.language} - onChange={() => {}} - > - <option value='python'>Python</option> - <option disabled value='cxx'>C++</option> - <option disabled value='matlab'>Matlab</option> - <option disabled value='r'>R</option> - </Input> - </FormGroup> - </FormGroup> - <FormGroup id='usedLibs'> - <h4>Libraries Used</h4> - { - (Object.entries(data.contents.uses): [string, any][]).map(([name, lib], i) => ( - <TypedField - key={i} - name={name} - type={lib} - types={this.props.libraries.filter(l => l.name !== data.name).map(l => l.name)} - existingFields={Object.keys(data.contents.uses)} - nameUpdateFunc={str => { - const newLibs = changeObjFieldName(data.contents.uses, name, str); - this.updateLibraries(newLibs); - }} - typeUpdateFunc={str => { - const newLibs = { - ...data.contents.uses, - [name]: str - }; - this.updateLibraries(newLibs); - }} - deleteFunc={() => { - const newLibs = { ...data.contents.uses }; - delete newLibs[name]; - this.updateLibraries(newLibs); - }} - /> - )) - } - <Button - outline - block - id='newLibrary' - onClick={e => { - let newKey = ''; - let v = 0; - while(true) { - const tryKey = `lib_${ v }`; - if(Object.keys(data.contents.uses).includes(tryKey)){ - v++; - continue; - } - newKey = tryKey; - break; - } - - this.updateLibraries({ - ...data.contents.uses, - [newKey]: '' - }); - }} - > - Use Another Library - </Button> - </FormGroup> - </Form> - </div> - ); - } -} - -const mapStateToProps = (state, ownProps) => { - const libs = Selectors.libraryGet(state); - const obj = { - libraries: libs, - data: libs[ownProps.index] || getValidObj() - }; - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`libraryUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(LibraryEditor); diff --git a/conda/js/src/components/library/LibraryEditor.spec.jsx b/conda/js/src/components/library/LibraryEditor.spec.jsx deleted file mode 100644 index aa5e29ea..00000000 --- a/conda/js/src/components/library/LibraryEditor.spec.jsx +++ /dev/null @@ -1,124 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import { LibraryEditor as C } from '.'; - -import testLibs from '@test/test_libs.json'; - -describe('<LibraryEditor />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount){ - wrapper.unmount(); - } - }); - - describe('accepts', () => { - const libs = [ - { - name: 'test/lib/1', - contents: { - language: 'python', - uses: [], - } - } - ].concat(testLibs); - - libs.forEach(function(lib){ - const saveFunc = () => {}; - const updateFunc = () => {}; - it(`${ lib.name }`, () => { - wrapper = mount( - <C - data={lib} - libraries={libs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'libraries', 'saveFunc', 'updateFunc'] - ).deep.equal( - [lib, libs, saveFunc, updateFunc] - ); - }); - }); - }); - - describe('creates', () => { - it('user/anotherlib/1', () => { - const libName = 'user/anotherlib/1'; - const saveFunc = sinon.spy(); - const updateFunc = sinon.spy(); - wrapper = mount( - <C - data={{name: libName, contents: { description: '', uses: {}, language: 'python' }}} - libraries={testLibs.filter(l => l.name !== libName)} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'libraries', 'saveFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', libName); - - expect(wrapper.props().data.contents).to.deep.equal({ - 'description': '', - 'uses': {}, - 'language': 'python' - }); - }); - - it('user/thelib/1', () => { - const libName = 'user/thelib/1'; - const saveFunc = sinon.spy(); - const data = {name: libName, contents: { description: '', uses: {}, language: 'python' }}; - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - wrapper = mount( - <C - data={data} - libraries={testLibs.filter(l => l.name !== libName)} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'libraries', 'saveFunc', 'updateFunc'] - ); - - let props = wrapper.props(); - expect(props.data).to.have.property('name', libName); - - wrapper.find('button#newLibrary').simulate('click'); - expect(updateFunc.callCount).to.equal(1); - - wrapper.find('#usedLibs CacheInput[type="text"]').prop('onChange')({ target: { value: 'lib'}}); - expect(updateFunc.callCount).to.equal(2); - - wrapper.find('#usedLibs select').simulate('change', { target: { value: 'user/anotherlib/1'}}); - expect(updateFunc.callCount).to.equal(3); - - props = wrapper.props(); - expect(props.data.contents).to.deep.equal({ - 'description': '', - 'uses': { - lib: 'user/anotherlib/1' - }, - 'language': 'python' - }); - }); - }); -}); diff --git a/conda/js/src/components/library/index.js b/conda/js/src/components/library/index.js deleted file mode 100644 index e331ab4e..00000000 --- a/conda/js/src/components/library/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedLibraryEditor, {LibraryEditor} from './LibraryEditor.jsx'; - -export { - LibraryEditor, -}; - -export default ConnectedLibraryEditor; diff --git a/conda/js/src/components/plotter/PlotterEditor.jsx b/conda/js/src/components/plotter/PlotterEditor.jsx deleted file mode 100644 index 9095ced7..00000000 --- a/conda/js/src/components/plotter/PlotterEditor.jsx +++ /dev/null @@ -1,277 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Row, - Col, - Button, - Form, FormGroup, - Label, Input, - Card, CardHeader, CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, - Alert, - UncontrolledDropdown, DropdownToggle, DropdownMenu, - InputGroup, InputGroupAddon, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import cn from 'classnames'; - -import { changeObjFieldName, generateNewKey, copyObj } from '@helpers'; -import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidPlotterObj as getValidObj } from '@helpers/beat'; -import type { BeatObject } from '@helpers/beat'; - -import * as Selectors from '@store/selectors.js'; - -import * as Actions from '@store/actions.js'; -import CacheInput from '../CacheInput.jsx'; -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; -import TemplateButton from '../EntityTemplateGenerationButton.jsx'; -import InfoTooltip from '../InfoTooltip.jsx'; -import ParameterCreate from '../ParameterCreate.jsx'; - -type Props = { - data: BeatObject, - libraries: BeatObject[], - plotDfNames: string[], - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, -}; - -type State = { - choiceCache: string, -}; - -export class PlotterEditor extends React.Component<Props, State> { - constructor(props: Props) { - //console.log(`Creating AlgDetail`); - super(props); - } - - state = { - choiceCache: '', - } - - setContents = (newContents: any) => { - this.props.updateFunc({ - ...this.props.data, - contents: { - ...this.props.data.contents, - ...newContents, - } - }); - } - - updateDescription = (desc: string) => { - this.setContents({ description: desc }); - } - - updateDataformat = (df: string) => { - this.setContents({ dataformat: df }); - } - - // 4 different functions: - // creates a parameter (provide name & value) - // updates a parameter (provide name & value) - // renames a parameter (provide name & value & the old name) - // deletes a parameter (provide null as name, value is optional, the name) - updateParameter = (name: null | string, value: any, oldName: ?string) => { - const params = copyObj(this.props.data.contents.parameters); - if(oldName) - delete params[oldName]; - if(name !== null) - params[name] = value; - this.setContents({ parameters: params }); - } - - // helper to change a value in the "contents" subobject of a plotter - // (this is where the vast majority of change happens) - changeContentsVal = (field: string, val: any) => { - const newCache = { - ...this.props.data, - contents: { - ...this.props.data.contents, - [field]: val - } - }; - - this.props.updateFunc(newCache); - } - - - renderLibraries = () => ( - <TabPane tabId='2'> - <Row> - <Col sm='12'> - { - // loop through all the used libs - (Object.entries(this.props.data.contents.uses): [string, any][]) - .map(([name, lib], i, lEntries) => ( - <TypedField - key={i} - name={name} - type={lib} - types={this.props.libraries.map(l => l.name)} - existingFields={lEntries.map(([n, v]) => n)} - nameUpdateFunc={str => { - // update the alias - this.changeContentsVal('uses', - changeObjFieldName( - this.props.data.contents.uses, - name, - str - ) - ); - }} - typeUpdateFunc={str => { - // update the chosen library for the alias - const libs = { - ...this.props.data.contents.uses, - [name]: str - }; - this.changeContentsVal('uses', libs); - }} - deleteFunc={() => { - const libs = { ...this.props.data.contents.uses }; - delete libs[name]; - this.changeContentsVal('uses', libs); - }} - /> - )) - } - </Col> - </Row> - <Button outline block - id='newLibraryBtn' - onClick={() => { - const newKey = generateNewKey('library', Object.keys(this.props.data.contents.uses)); - this.changeContentsVal('uses', - { - ...this.props.data.contents.uses, - [newKey]: '' - } - ); - }} - > - New Library - </Button> - </TabPane> - ); - - - render = () => { - return ( - <div> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='plotter' obj={this.props.data} />) - </Button> - <TemplateButton - data={this.props.data} - entity={'plotter'} - /> - </div> - <Form> - <FormGroup tag='fieldset'> - <FormGroup> - <Label>Short Description</Label> - <Input - type='text' - id='plDesc' - placeholder='Plotter description...' - value={this.props.data.contents.description} - onChange={(e) => this.updateDescription(e.target.value)} - /> - </FormGroup> - <FormGroup> - <Label>Input Dataformat</Label> - <Input - id='plDf' - type='select' - className='custom-select' - value={this.props.data.contents.dataformat} - onChange={e => this.updateDataformat(e.target.value)} - > - { - this.props.plotDfNames.map((df, i) => - <option key={i} value={df}>{ df }</option> - ) - } - </Input> - </FormGroup> - <FormGroup id='usedLibs'> - <h5>Libraries</h5> - { this.renderLibraries() } - </FormGroup> - <FormGroup id='paramsForm'> - <h5>Parameters</h5> - { - (Object.entries(this.props.data.contents.parameters): [string, any][]).map(([name, param], i, params) => ( - <Row key={i} className='mb-2'> - <Col sm='12'> - <ParameterCreate - name={name} - param={param} - params={params} - updateParameter={this.updateParameter} - /> - </Col> - </Row> - )) - } - <Button outline block - id='newParameterBtn' - onClick={() => { - const newKey = generateNewKey('parameter', Object.keys(this.props.data.contents.parameters || {})); - this.updateParameter( - newKey, - { - type: '', - default: '', - description: '', - } - ); - }} - > - New Parameter - </Button> - </FormGroup> - </FormGroup> - </Form> - </div> - ); - } -} - -const mapStateToProps = (state, ownProps) => { - const plotters = Selectors.plotterGet(state); - const obj = { - libraries: Selectors.libraryGet(state), - plotDfNames: Selectors.dataformatGet(state).map(df => df.name).filter(df => df.startsWith('plot/')), - data: plotters[ownProps.index] || getValidObj(), - }; - - if(obj.data.contents.dataformat === "") - { - obj.plotDfNames.unshift("-- select an option --") - }; - - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`plotterUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(PlotterEditor); diff --git a/conda/js/src/components/plotter/PlotterEditor.spec.jsx b/conda/js/src/components/plotter/PlotterEditor.spec.jsx deleted file mode 100644 index 5aa3bd3b..00000000 --- a/conda/js/src/components/plotter/PlotterEditor.spec.jsx +++ /dev/null @@ -1,236 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import { PlotterEditor as C } from '.'; -import { getValidPlotterObj as getValidObj } from '@helpers/beat'; - -import testPlotters from '@test/test_plotters.json'; -import testDfs from '@test/test_dfs.json'; -import testLibs from '@test/test_libs.json'; - -const libs = []; - -describe('<PlotterEditor />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const plots = [ - { - name: 'test/myplot/1', - contents: { - description: 'A basic plotter as a sanity test for the PlotterEditor', - language: 'python', - parameters: { - 'parameter_1': { - type: 'string', - default: 'default', - description: 'description', - } - }, - dataformat: "plot/bar/1", - uses: { - 'library': 'plot/baselib/1', - } - } - } - ].concat(testPlotters.map(a => getValidObj(a))); - - plots.forEach(function(plot){ - const saveFunc = () => {}; - const updateFunc = () => {}; - const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name); - it(`${ plot.name }`, () => { - wrapper = mount( - <C - data={getValidObj(plot)} - plotters={plots} - dataformats={plot.contents.dataformat} - plotDfNames={dfs} - libraries={libs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - expect(wrapper).to.have.props( - ['data', 'plotters', 'dataformats', 'libraries', 'saveFunc', 'updateFunc'] - ) - }); - }); - }); - - describe('creates', () => { - it('test/createplot/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const plotName = 'test/createplot/1'; - const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name); - wrapper = mount( - <C - data={getValidObj({name: plotName, contents: {}})} - plotters={[]} - dataformats={testDfs} - plotDfNames={dfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'plotters', 'dataformats', 'plotDfNames', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', plotName); - - expect(wrapper.props().data.contents).to.have.property('dataformat', ''); - expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(0); - expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6); - expect(wrapper.props().data.contents).to.have.property('language', 'python'); - wrapper.find('#plDf select').simulate('change', { target: { value: 'user/anotherdataformat/1'}}); - expect(updateFunc.callCount).to.equal(1); - - expect(wrapper.props().data.contents).to.have.property('dataformat', 'user/anotherdataformat/1'); - expect(wrapper.props().data.contents).to.have.property('language', 'python'); - - expect(wrapper.props().data.contents).to.have.property('description').with.lengthOf(0); - expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6); - expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(24); - expect(wrapper.props().data.contents).to.have.property('parameters').that.deep.equals({}); - expect(wrapper.props().data.contents).to.have.property('uses').that.deep.equals({}); - expect(wrapper.props().data.contents).to.deep.equal({ - 'description': '', - 'uses': {}, - 'parameters': {}, - 'language': 'python', - 'dataformat': 'user/anotherdataformat/1' - }); - - }); - - it('test/plot_add_lib/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const plotName = 'test/plot_other/1'; - const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name); - wrapper = mount( - <C - data={getValidObj({name: plotName, contents: {}})} - plotters={[]} - dataformats={testDfs} - plotDfNames={dfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'plotters', 'dataformats', 'plotDfNames', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', plotName); - - expect(wrapper.props().data.contents).to.have.property('dataformat', ''); - expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(0); - expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6); - expect(wrapper.props().data.contents).to.have.property('language', 'python'); - expect(wrapper.props().data.contents).to.have.property('parameters').that.deep.equals({}); - expect(wrapper.props().data.contents).to.have.property('uses').that.deep.equals({}); - - wrapper.find('button#newLibraryBtn').simulate('click'); - wrapper.find('#usedLibs CacheInput[type="text"]').prop('onChange')({ target: { value: 'lib'}}); - expect(updateFunc.callCount).to.equal(2); - - wrapper.find('#usedLibs select').simulate('change', { target: { value: 'user/anotherlib/1'}}); - expect(updateFunc.callCount).to.equal(3); - - expect(wrapper.props().data.contents).to.deep.equal({ - 'description': '', - 'uses': { - lib: 'user/anotherlib/1' - }, - 'language': 'python', - 'parameters': {}, - 'dataformat': '' - }); - }); - - it('test/plot_add_param/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const plotName = 'test/plot_param/1'; - const dfs = testDfs.filter(d => d.name.startsWith('plot')).map(testDfs => testDfs.name); - wrapper = mount( - <C - data={getValidObj({name: plotName, contents: {}})} - plotters={[]} - dataformats={testDfs} - plotDfNames={dfs} - libraries={testLibs} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'plotters', 'dataformats', 'plotDfNames', 'libraries', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', plotName); - - expect(wrapper.props().data.contents).to.have.property('dataformat', ''); - expect(wrapper.props().data.contents).to.have.property('dataformat').with.lengthOf(0); - expect(wrapper.props().data.contents).to.have.property('language').with.lengthOf(6); - expect(wrapper.props().data.contents).to.have.property('language', 'python'); - expect(wrapper.props().data.contents).to.have.property('parameters').that.deep.equals({}); - expect(wrapper.props().data.contents).to.have.property('uses').that.deep.equals({}); - wrapper.find('button#newParameterBtn').simulate('click'); - expect(updateFunc.callCount).to.equal(1); - - wrapper.find('CacheInput[placeholder="Parameter name..."]').prop('onChange')( { target: { value: 'offset' }}); - expect(updateFunc.callCount).to.equal(2); - wrapper.find('#paramsForm select').prop('onChange')( { target: { value: 'int32' }}); - expect(updateFunc.callCount).to.equal(3); - wrapper.find('input[placeholder="Default"]').simulate('change', { target: { value: '1' }}); - expect(updateFunc.callCount).to.equal(4); - - expect(wrapper.props().data.contents.parameters).to.have.deep.property('offset', { - 'default': '1', - 'type': 'int32', - 'description': '', - }); - - expect(wrapper.props().data.contents).to.deep.equal({ - 'description': '', - 'uses': {}, - 'language': 'python', - 'parameters': { - 'offset': { - 'default': '1', - 'type': 'int32', - description: '', - } - }, - 'dataformat': '' - }); - }); - }); -}); diff --git a/conda/js/src/components/plotter/index.js b/conda/js/src/components/plotter/index.js deleted file mode 100644 index c3bf287a..00000000 --- a/conda/js/src/components/plotter/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedPlotterEditor, {PlotterEditor} from './PlotterEditor.jsx'; - -export { - PlotterEditor, -}; - -export default ConnectedPlotterEditor; diff --git a/conda/js/src/components/plotterparameter/PlotterParameterEditor.jsx b/conda/js/src/components/plotterparameter/PlotterParameterEditor.jsx deleted file mode 100644 index 9c90b2ff..00000000 --- a/conda/js/src/components/plotterparameter/PlotterParameterEditor.jsx +++ /dev/null @@ -1,193 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Row, - Col, - Button, - Form, FormGroup, - Label, Input, - Card, CardHeader, CardBody, - TabContent, TabPane, Nav, NavItem, NavLink, - Alert, - UncontrolledDropdown, DropdownToggle, DropdownMenu, - InputGroup, InputGroupAddon, -} from 'reactstrap'; - -import { connect } from 'react-redux'; - -import cn from 'classnames'; - -import { changeObjFieldName, generateNewKey, copyObj } from '@helpers'; -import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidPlotterparameterObj as getValidObj, expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat'; -import type { BeatObject } from '@helpers/beat'; - -import * as Selectors from '@store/selectors.js'; - -import * as Actions from '@store/actions.js'; -import CacheInput from '../CacheInput.jsx'; -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import TypedField from '../TypedField.jsx'; -import TemplateButton from '../EntityTemplateGenerationButton.jsx'; -import InfoTooltip from '../InfoTooltip.jsx'; -import ParameterConsume from '../ParameterConsume.jsx'; - -type Props = { - plotters: BeatObject[], - data: BeatObject, - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, -}; - -export class PlotterParameterEditor extends React.Component<Props> { - constructor(props: Props) { - //console.log(`Creating AlgDetail`); - super(props); - } - - setContents = (newContents: any) => { - this.props.updateFunc({ - ...this.props.data, - contents: { - ...this.props.data.contents, - ...newContents, - } - }); - } - - updateDescription = (desc: string) => { - this.setContents({ description: desc }); - } - - getPlotterName = (): string => { - return this.props.data.contents.plotter; - } - - getPlotter = (name: ?string) => { - const n = name || this.getPlotterName(); - const pl = this.props.plotters.find(pl => pl.name === n); - return pl || {}; - } - - updatePlotter = (plName: string) => { - const pl = this.getPlotter(plName); - const oldPlotter = this.getPlotterName(); - if(oldPlotter === pl.name) - return; - - this.setContents({ - plotter: pl.name, - data: Object.entries(pl.contents.parameters) - .map(([p, info]) => ({ [p]: getDefaultParameterValue(info) })) - .reduce((o, p) => ({ ...o, ...p }), {}) - }); - } - - updateParameter = (pName: string, v: number | string | boolean) => { - this.setContents({ - data: { - ...this.props.data.contents.data, - [pName]: v - } - }); - } - - render = () => { - const pn = this.getPlotterName(); - const pl = this.getPlotter(pn); - - return ( - <div> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='plotterparameter' obj={this.props.data} />) - </Button> - {/* - <TemplateButton - data={this.props.data} - entity={'plotter'} - /> - */} - </div> - <Form> - <FormGroup tag='fieldset'> - <FormGroup> - <Label>Short Description</Label> - <Input - type='text' - id='ppDesc' - placeholder='Parameter description...' - value={this.props.data.contents.description} - onChange={(e) => this.updateDescription(e.target.value)} - /> - </FormGroup> - <FormGroup> - <Label>Plotter</Label> - <Input - type='select' - className='custom-select' - id='ppPl' - placeholder='Plotter...' - value={pn} - onChange={e => this.updatePlotter(e.target.value)} - > - { - this.props.plotters.map((pl, i) => - <option key={i} value={pl.name}>{ pl.name }</option> - ) - } - </Input> - </FormGroup> - <h5>Parameters</h5> - { - pl.contents && - Object.entries(pl.contents.parameters).map(([pName, o], i) => - <FormGroup row key={i}> - <Label sm={4}>{ pName }</Label> - <Col> - <ParameterConsume - parameter={o} - updateFunc={(v: any) => this.updateParameter(pName, v)} - currVal={this.props.data.contents.data[pName]} - /> - </Col> - </FormGroup> - ) - } - </FormGroup> - </Form> - </div> - ); - } -} - -const mapStateToProps = (state, ownProps) => { - const params = Selectors.plotterparameterGet(state); - const obj = { - plotters: Selectors.plotterGet(state), - data: params[ownProps.index] || getValidObj(), - }; - - if(!obj.data.contents.hasOwnProperty('plotter') || - obj.data.contents.plotters === "") - { - obj.plotters.unshift({name: "-- select an option --"}) - }; - - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`plotterparameterUpdate`](obj.name, obj)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(PlotterParameterEditor); diff --git a/conda/js/src/components/plotterparameter/PlotterParameterEditor.spec.jsx b/conda/js/src/components/plotterparameter/PlotterParameterEditor.spec.jsx deleted file mode 100644 index 1efd2552..00000000 --- a/conda/js/src/components/plotterparameter/PlotterParameterEditor.spec.jsx +++ /dev/null @@ -1,126 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import { PlotterParameterEditor as C } from '.'; -import { getValidPlotterparameterObj as getValidObj } from '@helpers/beat'; - -import testPlotterParameters from '@test/test_plotterparameters.json'; -import testPlotters from '@test/test_plotters.json'; - -const libs = []; - -describe('<PlotterParameterEditor />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const plotparams = [ - { - name: 'test/myplotterparameter/1', - contents: { - description: 'A basic plotterparameter as a sanity test for the PlotterParameterEditor', - data: { - legend_loc: 'string' - }, - plotter: "plot/bar/1" - } - } - ].concat(testPlotterParameters.map(a => getValidObj(a))); - - plotparams.forEach(function(plotparam){ - const saveFunc = () => {}; - const updateFunc = () => {}; - const plotters = testPlotters.filter(d => d.name.startsWith('plot')).map(testPlotters => testPlotters.name); - it(`${ plotparam.name }`, () => { - wrapper = mount( - <C - data={getValidObj(plotparam)} - plotterparameters={plotparams} - plotters={plotters} - plotterNames={plotters} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - expect(wrapper).to.have.props( - ['data', 'plotterparameters', 'plotters', 'saveFunc', 'updateFunc'] - ) - }); - }); - }); - - describe('creates', () => { - it('test/createplotparam/1', () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const plotparamName = 'test/createplotparam/1'; - const plotters = testPlotters.filter(d => d.name.startsWith('plot')).map(testPlotters => testPlotters); - wrapper = mount( - <C - data={getValidObj({name: plotparamName, contents: {}})} - plotterparameters={[]} - plotters={plotters} - plotterNames={plotters} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'plotterparameters', 'plotters', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', plotparamName); - - expect(wrapper.props().data.contents).to.have.property('description'); - expect(wrapper.props().data.contents).to.have.property('description').with.lengthOf(0); - wrapper.find('#ppPl select').simulate('change', { target: { value: 'user/anotherploter/1'}}); - expect(updateFunc.callCount).to.equal(0); - wrapper.find('#ppPl select').simulate('change', { target: { value: 'plot/bar/1'}}); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents).to.have.property('plotter', 'plot/bar/1'); - - expect(wrapper.props().data.contents).to.have.property('description').with.lengthOf(0); - expect(wrapper.props().data.contents).to.have.property('plotter').with.lengthOf(10); - expect(wrapper.props().data.contents).to.have.property('data'); - expect(wrapper.props().data.contents).to.deep.equal({ - 'description': '', - 'plotter': 'plot/bar/1', - 'data': { - 'axis-fontsize': 10, - 'bar-alpha': 0.75, - 'bar-norm': true, - 'bar_attributes': '', - 'content_type': 'image/png', - 'dpi': 60, - 'grid': false, - 'height': 300, - 'legend': '', - 'legend-bbox-to-anchor': 1, - 'legend-fontsize': 12, - 'legend-loc': 'best', - 'title': 'Bar plot', - 'title-fontsize': 10, - 'width': 400, - 'xaxis_multiplier': 1, - 'xlabel': '', - 'yaxis_log': false, - 'yaxis_multiplier': 1, - 'ylabel': '' - } - }); - - }); - }); -}); diff --git a/conda/js/src/components/plotterparameter/index.js b/conda/js/src/components/plotterparameter/index.js deleted file mode 100644 index 43b74bd5..00000000 --- a/conda/js/src/components/plotterparameter/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import ConnectedPlotterParameterEditor, {PlotterParameterEditor} from './PlotterParameterEditor.jsx'; - -export { - PlotterParameterEditor, -}; - -export default ConnectedPlotterParameterEditor; diff --git a/conda/js/src/components/toolchain/GraphicalEditor.css b/conda/js/src/components/toolchain/GraphicalEditor.css deleted file mode 100644 index 169634b8..00000000 --- a/conda/js/src/components/toolchain/GraphicalEditor.css +++ /dev/null @@ -1,72 +0,0 @@ -svg { - background-color: white; - user-select: none; -} - -line { - stroke-linecap: round; -} - -.editorWrapper { - height: 500px; - width: 100%; - background-color: grey; - z-index: 1; -} - -.editorWrapper.maximized { - position: fixed; - left: 5%; - top: 5%; - width: 90%; - height: 90%; - background-color: grey; - border: solid 1px grey; - border-radius: 2px; - box-shadow: 0 0 5px grey; -} - -.editorWrapper2 { - height: 100%; - width: 100%; - background-color: white; - overflow: scroll; -} - -.tcBlock:hover > .tcBlockWhiteFill { - filter: brightness(95%); -} - -.tcBlock > .highlighted { - stroke-dasharray: 10, 10; -} - -.experimentEditor .tcBlock > .highlighted { - stroke-width: 3px; -} - -.editorMenu { - background: rgba(255, 255, 255, 0.5); - position: absolute; - margin: auto; - margin-top: 0.5em; - right: 2em; -} - -.editorWrapper.maximized > .editorMenu { - right: 1em; -} - -text { - user-select: none; - font-family: monospace; -} - -.tcBlockTitle { - font-weight: bold; -} - -.tcConnection > .error { - stroke: crimson; - stroke-dasharray: 10, 10; -} diff --git a/conda/js/src/components/toolchain/GraphicalEditor.jsx b/conda/js/src/components/toolchain/GraphicalEditor.jsx deleted file mode 100644 index a78ced34..00000000 --- a/conda/js/src/components/toolchain/GraphicalEditor.jsx +++ /dev/null @@ -1,1134 +0,0 @@ -// @flow -import './GraphicalEditor.css'; -import * as React from 'react'; -import * as d3 from 'd3'; -import { - Button, - ButtonGroup, -} from 'reactstrap'; -import cn from 'classnames'; -import Block from './ToolchainBlock.jsx'; -import Connection, { connectionToId } from './ToolchainConnection.jsx'; -import HelpModal from './GraphicalEditorHelpModal.jsx'; -import { ContextMenuTrigger } from 'react-contextmenu'; -import { changeObjFieldName, generateNewKey } from '@helpers'; - -import type { - BlockType, - NormalBlock, - AnalyzerBlock, - DatasetBlock, - BlockSet, - BlockCoords, - ConnectionType, - Group, - LocationMapEntry, - LocationMap , -} from '@helpers/toolchainTypes'; - -type Props = { - // the representation data of the toolchain (block locations & channel colors) - repData: { - blocks: { - [string]: { - col: number, - row: number, - } - }, - channel_colors: { - [string]: string - }, - }, - // the blocks in the toolchain - blocks: NormalBlock[], - // the datasets in the toolchain - datasets: DatasetBlock[], - // the analyzers in the toolchain - analyzers: AnalyzerBlock[], - // the connections in the toolchain - connections: ConnectionType[], - // block groups (not a feature in beat web) - groups: Group[], - handleBlockClick?: (blockName: string, set: BlockSet) => any, - handleBackgroundClick?: (e: any) => any, - // updates a block location to col #x & row #y - updateBlockLocations?: (bLocs: {blockName: string, x: number, y: number}[]) => any, - createConnection?: (from: string, to: string, channel: string) => any, - // extra svg to be drawn after the blocks & connections - svgChildren?: React.Node, - // extra children (e.g. context menus) that arent svg - divChildren?: React.Node, - // should the d3 behaviours be enabled? - interactable?: boolean, - // map of block names to strings of text to display on the bottom of a block - // used for showing the selected dataset/algorithm in an exp - experimentData?: { [string]: string }, - // block names mapped to an array of error strings - errorBlocks?: { [string]: string[] }, - // blocks to highlight strongly - focusBlocks?: string[], - toolbarContent?: React.Node, -}; - -type State = { - // the scale transformation for the svg - zoomLevel: number, - // represents the most recent click at a specific point on the svg's grid background - svgActionLocation: { - x: number, - y: number, - }, - selectedBlocks: BlockType[], - maximized: boolean, - helpActive: boolean, - rightClickBlock: ?string, - rightClickConnection: ?ConnectionType, -}; - -// note: all measurements are in px by default for svg -// how tall a line of text is in a block -export const blockTextHeight = 20; -export const svgDimensionLength = 6000; -export const svgWidth = svgDimensionLength; -export const svgHeight = svgDimensionLength; -export const startingZoomLevel = svgDimensionLength; -export const minZoomLevel = 5000; -export const svgWidthHalf = svgWidth / 2; -export const svgHeightHalf = svgHeight / 2; -export const blockWidth = 200; -// spacing between grid rows/cols -export const gridDistance = 20; -// how much the scaling changes at once -export const zoomAdjustmentAmount = 100; -// convert coords in the SVG element to coords to save in data -export const convertWorldToDataCoords = (x: number, y: number) => { - return [x - svgWidthHalf, y - svgHeightHalf]; -}; -// convert coords in the data to the actual SVG locations -export const convertDataToWorldCoords = (x: number, y: number) => { - return [x + svgWidthHalf, y + svgHeightHalf]; -}; -export const clampCoordsToGrid = (x: number, y: number): [number, number] => { - const nx = Math.round(x / gridDistance) * gridDistance; - const ny = Math.round(y / gridDistance) * gridDistance; - return [nx, ny]; -}; - -export default class GraphicalEditor extends React.PureComponent<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - zoomLevel: startingZoomLevel, - svgActionLocation: { - x: -1, - y: -1, - }, - selectedBlocks: [], - maximized: false, - helpActive: false, - rightClickBlock: undefined, - rightClickConnection: undefined, - }; - - // initializes d3 behaviours (most SVG interactions) - componentDidMount = () => { - this.initD3Behaviours(); - this.fitToToolchain(this.getLocationMap()); - //this.scrollToMiddle(); - } - - // initalize all the d3 behaviours again if the tc changed, - // so new blocks have the d3 stuff and old blocks are removed - // (they overwrite older ones) - componentDidUpdate = (prevProps: Props, prevState: State, snapshot: any) => { - if(prevProps !== this.props){ - this.initD3Behaviours(); - } - } - - initD3Behaviours = () => { - if(this.props.interactable){ - this.initD3Drag(); - this.initD3Connections(); - this.initD3AreaSelect(); - this.initD3MouseMovement(); - } - } - - // used for the scrollElement ref - scrollElement = null; - // used for the svgContextMenu ref - svgContextMenu = null; - // used for the blockContextMenu ref - blockContextMenu = null; - handleBlockContextMenu = (e: any, name: string, set: string) => { - //console.log(`${ name } : ${ set }`); - if(this.blockContextMenu){ - this.setState({ rightClickBlock: name }); - e.persist(); - e.preventDefault(); - e.stopPropagation(); - setTimeout(() => { - if(this.blockContextMenu) - this.blockContextMenu.handleContextClick(e); - }, 0); - } - } - - // used for the connectionContextMenu ref - connectionContextMenu = null; - handleConnectionContextMenu = (e: any, connection: ConnectionType) => { - //console.log(`${ name } : ${ set }`); - if(this.connectionContextMenu){ - this.setState({ rightClickConnection: connection }); - e.persist(); - e.preventDefault(); - e.stopPropagation(); - setTimeout(() => { - if(this.connectionContextMenu) - this.connectionContextMenu.handleContextClick(e); - }, 0); - } - } - - scrollTo = (x: number, y: number) => { - setTimeout(() => { - if(this.scrollElement){ - this.scrollElement.scrollLeft = x; - this.scrollElement.scrollTop = y; - } - }, 50); - }; - - // scrolls to the middle of the page - scrollToMiddle = () => { - this.scrollTo(svgWidthHalf - 300, svgHeightHalf - 300); - }; - - // adjusts the zoomlevel - setZoomLevel = (zoomLevel: number) => zoomLevel >= minZoomLevel && this.setState({zoomLevel: zoomLevel}); - // zoom out - zoomOut = () => this.setZoomLevel(this.state.zoomLevel + zoomAdjustmentAmount); - // zoom in - zoomIn = () => this.setZoomLevel(this.state.zoomLevel - zoomAdjustmentAmount); - // toggle maximized - toggleMaximized = () => this.setState({ maximized: !this.state.maximized }); - // toggles the help modal - toggleHelp = () => this.setState({ helpActive: !this.state.helpActive }); - - // generates the string representing the viewbox of the svg. The first two numbers represent the offset, the last two the scaling. - getSvgViewBox = () => `0 0 ${ this.state.zoomLevel } ${ this.state.zoomLevel }`; - - findBlock = (name: string): BlockType => { - const b = this.props.blocks.find(b => b.name === name) || - this.props.datasets.find(b => b.name === name) || - this.props.analyzers.find(b => b.name === name) - ; - if(!b) - throw new Error(`invalid block name: ${ name }`); - - return b; - - } - - // generates a map of the location (and sizes) of all blocks, inputs, & outputs on the graphical editor. - // necessary to draw lines between connected outputs & inputs. - getLocationMap = (): LocationMap => { - const locMap = {}; - const hasExpData = this.props.experimentData !== undefined; - const ioVerticalOffset = hasExpData ? blockTextHeight : blockTextHeight / 4; - const notShownBlocks: string[] = hasExpData ? [] : this.props.groups.reduce((arr, g) => g.collapsed ? [...g.blocks, ...arr] : arr, []); - - ((Object.entries(this.props.repData.blocks): any): [string, any][]) - .forEach(([name, rep], i) => { - const data: BlockType = this.findBlock(name); - - const [x, y] = convertDataToWorldCoords(rep.col * gridDistance, rep.row * gridDistance); - const inputs = data.inputs || []; - const outputs = data.outputs || []; - const height = ((Math.max(inputs.length, outputs.length, 1) + 1) + 1) * blockTextHeight; - const width = blockWidth; - - const locBlock = { x, y, height, width }; - - locMap[name] = { - block: locBlock, - }; - - if(data.inputs){ - const locInputs = {}; - inputs.forEach((inp, i) => { - locInputs[inp] = { - x: x - 8, - y: (y + blockTextHeight) + (i * blockTextHeight) + (blockTextHeight * 0.3) + ioVerticalOffset, - width: 8, - height: blockTextHeight * 0.75, - }; - }); - locMap[name].inputs = locInputs; - } - - if(data.outputs){ - const locOutputs = {}; - outputs.forEach((out, i) => { - locOutputs[out] = { - x: x + blockWidth, - y: (y + blockTextHeight) + (i * blockTextHeight) + (blockTextHeight * 0.3) + ioVerticalOffset, - width: 8, - height: blockTextHeight * 0.75, - }; - }); - locMap[name].outputs = locOutputs; - } - }); - - const getBlocksBoundingBox = (names: string[], collapsed: boolean) => { - const blockLocs = names.filter(n => locMap.hasOwnProperty(n)).map(n => locMap[n].block); - let x = collapsed && !hasExpData ? - blockLocs.map(l => l.x).reduce((n, x) => n + x, 0) / blockLocs.length : - Math.min(...blockLocs.map(l => l.x)) - ; - let y = collapsed && !hasExpData ? - blockLocs.map(l => l.y).reduce((n, y) => n + y, 0) / blockLocs.length : - Math.min(...blockLocs.map(l => l.y)) - ; - if(collapsed && !hasExpData) - [x, y] = clampCoordsToGrid(x, y); - - const width = collapsed && !hasExpData ? - blockWidth : - Math.max(...blockLocs.map(l => l.x + l.width - x)) + gridDistance * 2 - ; - const height = collapsed && !hasExpData ? - gridDistance * 3 : - Math.max(...blockLocs.map(l => l.y + l.height - y)) + gridDistance * 2 - ; - - return { - x: x - gridDistance, - y: y - gridDistance, - width, - height, - }; - }; - - this.props.groups.forEach(g => { - // get the x,y,width,height for the group box - const bbox = getBlocksBoundingBox(g.blocks, g.collapsed); - locMap[g.name] = { - block: bbox, - }; - // if the group is collapsed, - // patch the locMap so that connections to/from blocks in the group - // instead are to/from the group block - if(g.collapsed && !hasExpData){ - g.blocks.forEach(b => { - if(locMap[b].inputs){ - for(const inp in locMap[b].inputs){ - const o = locMap[b].inputs[inp]; - o.x = bbox.x - 1; - o.y = bbox.y + bbox.height / 2; - } - } - - if(locMap[b].outputs){ - for(const out in locMap[b].outputs){ - const o = locMap[b].outputs[out]; - o.x = bbox.x + bbox.width - 2; - o.y = bbox.y + bbox.height / 2; - } - } - }); - } - }); - - return locMap; - } - - // manually triggers the svg's context menu - triggerSvgAction = (x: number, y: number, clickEvent: any) => { - this.setState({ - svgActionLocation: { - x, - y, - } - }); - - if(this.svgContextMenu) - this.svgContextMenu.handleContextClick(clickEvent); - } - - scaleD3EventLocation = (d3X: number, d3Y: number): [number, number] => { - const x = d3X * (this.state.zoomLevel / svgWidth); - const y = d3Y * (this.state.zoomLevel / svgHeight); - return [x, y]; - }; - - selectBlocks = (blocks: BlockType[]) => { - this.setState({ - selectedBlocks: blocks, - }); - this.initD3Drag(); - } - - // synchronizes setState call via passing a func instead of an object - // uses names instead of block objects so it can find them in the latest props - safeSelectBlocksByName = (blockNames: string[]) => { - this.setState((prevState, props) => { - return { - selectedBlocks: blockNames - .map(name => - props.blocks.find(b => b.name === name) || - props.datasets.find(b => b.name === name) || - props.analyzers.find(b => b.name === name) - ).filter(b => b) - }; - }); - this.initD3Drag(); - } - - // d3 hooks for dragging blocks around - // to get around perf problems with updating the entire react state every drag event, - // a placeholder (that's outside the react framework!) is drawn via d3. - // only at the end of the drag is the react state updated. - initD3Drag = () => { - setTimeout(() => { - const updateBlockLocations = this.props.updateBlockLocations; - if(!updateBlockLocations) - return; - const that = this; - // currently debouncing isnt necessary perf-wise - let startX = 0; - let startY = 0; - let dx = 0; - let dy = 0; - let mx = 0; - let my = 0; - // the event handler for all the drag events in between the start/end - function dragged(d) { - // keep track of the change to mouse location across drag events - dx += d3.event.dx; - dy += d3.event.dy; - // if the user has dragged enough to move at least one grid space, - // calculate the amount of grid spaces to move - if(Math.abs(dx) > gridDistance){ - mx = Math.round(dx / gridDistance); - dx = dx - mx * gridDistance; - } - if(Math.abs(dy) > gridDistance){ - my = Math.round(dy / gridDistance); - dy = dy - my * gridDistance; - } - // if theres any grid movement to be made, make it - if(mx != 0 || my != 0){ - const dRect = d3.select('.dragRect'); - dRect - .attr('x', Number.parseInt(dRect.attr('x')) + mx * gridDistance) - .attr('y', Number.parseInt(dRect.attr('y')) + my * gridDistance); - } - // reset the grid movement since we made it already - mx = 0; - my = 0; - } - - // when the user starts dragging, create the placeholder block - function startDrag(d) { - const b = d3.select(this); - const x = Number.parseFloat(b.attr('x')); - const y = Number.parseFloat(b.attr('y')); - const height = b.attr('height'); - const width = b.attr('width'); - startX = x / gridDistance; - startY = y / gridDistance; - - d3.select('svg') - .insert('rect', '.tcBlock') - .attr('class', 'dragRect') - .attr('fill', 'grey') - .attr('stroke', 'black') - .attr('stroke-width', '2') - .attr('stroke-dasharray', '10, 10') - .attr('opacity', '0.4') - .attr('x', x) - .attr('y', y) - .attr('height', height) - .attr('width', width) - ; - - // reset vals for a new drag - dx = 0; - dy = 0; - mx = 0; - my = 0; - } - - // when the user lets go, move the block to the location of the placeholder - function endDrag(d) { - const dRect = d3.select('.dragRect'); - const d3this = d3.select(this); - const x = Number.parseInt(dRect.attr('x')) / gridDistance; - const y = Number.parseInt(dRect.attr('y')) / gridDistance; - const xShift = x - startX; - const yShift = y - startY; - if(xShift !== 0 || yShift !== 0){ - let bNames = []; - if(d3this.classed('areaSelect')){ - bNames = that.state.selectedBlocks.map(b => b.name); - } else if(d3this.classed('tcGroup')){ - const gId = d3this.attr('id').slice(6); - const g = that.props.groups.find(g => g.name === gId); - if(!g) - return; - bNames = g.blocks; - } else { - bNames = [d3this.attr('id').slice(6)]; - } - - const bLocs = bNames.map(b => { - const x = that.props.repData.blocks[b].col; - const y = that.props.repData.blocks[b].row; - const bx = x + xShift; - const by = y + yShift; - - return {blockName: b, x: bx, y: by}; - }); - - updateBlockLocations(bLocs); - } - dRect.remove(); - } - - // all block elements should be draggable - d3.selectAll('.fo,.areaSelect,.tcGroup').call( - d3.drag() - .on('start', startDrag) - .on('end', endDrag) - .on('drag', dragged) - ); - }, 50); - }; - - // d3 behaviour for connecting an output and input and creating a connection - // allows users to drag from output to input, - // or click an output and click an input - initD3Connections = () => { - // creating connections - setTimeout(() => { - let startId; - const createConnection = this.props.createConnection; - const channelColors = this.props.repData.channel_colors; - const {datasets, blocks} = this.props; - let startBlock; - let startX = 0; - let startY = 0; - // the user has started dragging from an output block, - // or it might be starting a click event! - // to see if the user is clicking or dragging, - // check in endDrag() if the distance travelled is small - // enough to be considered a click or not - function startDrag(d) { - //console.log('startDrag'); - startX = d3.event.x; - startY = d3.event.y; - // find the block that the user started from - const rawId = d3.select(this).attr('id'); - const bName = rawId.split('-output-')[0]; - startId = rawId.replace('-output-', '.'); - startBlock = datasets.find(d => d.name === bName); - if(!startBlock) - startBlock = blocks.find(d => d.name === bName); - // draw a line from the output rect to the mouse location - d3.select('svg') - .append('line') - .classed('tmp', true) - .attr('stroke', 'black') - .attr('x1', startX) - .attr('y1', startY) - .attr('x2', startX) - .attr('y2', startY); - } - - const processEndBlock = (endInput: HTMLElement) => { - if(!startBlock) - return; - //console.log(endInput); - const endId = endInput.id.replace('-input-', '.'); - // create a new connection assuming theres a given func that does it - if(createConnection) - createConnection(startId, endId, startBlock.synchronized_channel || startBlock.name); - - startBlock = undefined; - }; - - // create a connection if the user ended the drag on an input block, - // else just remove the temp svg line - function endDrag(d) { - //console.log('endDrag'); - const {x, y} = d3.event; - if(Math.abs(startX - x) < 10 && Math.abs(startY - y) < 10) { - // click event not drag - } else { - // probably not a click event - d3.select('.tmp').remove(); - // with the location of the end event, - // compare the location to the location & dims of all input blocks - // in the svg. - const endInput = Array.from(document.querySelectorAll('.iBlock')) - .find(n => { - const nx = n.x.baseVal.value; - const ny = n.y.baseVal.value; - const width = n.width.baseVal.value; - const height = n.height.baseVal.value; - return nx <= x && x <= nx + width && ny <= y && y <= ny + height; - }); - if(endInput === undefined){ - startBlock = undefined; - } else { - processEndBlock(endInput); - } - } - } - - // create a connection if the user clicked an input block, - // else just reset the startBlock - function endClick() { - processEndBlock(this); - } - - // update the temp line - function dragged() { - d3.select('.tmp') - .attr('x2', d3.event.x) - .attr('y2', d3.event.y); - } - - d3.selectAll('.oBlock') - .call( - d3.drag() - .on('start', startDrag) - .on('end', endDrag) - .on('drag', dragged) - ); - - d3.selectAll('.iBlock') - .on('click', endClick); - }, 50); - } - - // show a little black dot signifying the closest grid point to the current mouse location. - // right-clicking the svg background will use this location for its context menu's actions (e.g. adding/pasting blocks). - initD3MouseMovement = () => { - // mouse movement - setTimeout(() => { - let cx = 0; - let cy = 0; - - d3.select('.puck') - .remove(); - - // draw the puck - d3.select('svg') - .insert('circle', '.backgroundLimit') - .attr('class', 'puck background') - .attr('cx', 0) - .attr('cy', 0) - .attr('r', 5); - - const svg = document.querySelector('svg'); - // when the mouse moves, recalc the puck's point on the grid - // needs to scale to the zoomlevel - d3.select('svg') - .on('mousemove', () => { - const [rawx, rawy] = d3.mouse(svg); - const [x, y] = clampCoordsToGrid(rawx, rawy); - cx = x; - cy = y; - d3.select('.puck') - .attr('cx', cx) - .attr('cy', cy) - ; - }) - // if the click event's target is the svg background, - // trigger the svg action at the puck's current point - .on('contextmenu', () => { - if(!Array.from(d3.event.target.classList).includes('background')) - return; - const [xData, yData] = convertWorldToDataCoords(cx, cy); - this.triggerSvgAction(xData / gridDistance, yData / gridDistance, d3.event); - }) - ; - }, 50); - } - - // d3 behaviour for selecting all blocks inside a rect (via click-and-drag) - initD3AreaSelect = () => { - setTimeout(() => { - const {findBlock, selectBlocks} = this; - let startX, startY; - let currX, currY; - const getPolygonPoints = () => { - return `${ startX },${ startY } ${ startX },${ currY } ${ currX },${ currY } ${ currX },${ startY }`; - }; - function startDrag(d) { - const [rawx, rawy] = d3.mouse(document.querySelector('svg')); - const [x, y] = clampCoordsToGrid(rawx, rawy); - startX = x; - startY = y; - currX = x; - currY = y; - d3.select('svg') - .insert('polygon', '.backgroundLimit') - .attr('class', 'tmp') - .attr('fill', 'grey') - .attr('stroke', 'black') - .attr('opacity', '0.3') - .attr('points', getPolygonPoints()) - ; - } - - function endDrag(d) { - const p = d3.select('polygon.tmp'); - const lesserX = Math.min(startX, currX); - const lesserY = Math.min(startY, currY); - const greaterX = Math.max(startX, currX); - const greaterY = Math.max(startY, currY); - const isInArea = (svgEl) => { - const ex = svgEl.x.baseVal.value; - const ey = svgEl.y.baseVal.value; - const ew = svgEl.width.baseVal.value; - const eh = svgEl.height.baseVal.value; - if(ex >= greaterX || ex + ew <= lesserX) - return false; - if(ey >= greaterY || ey + eh <= lesserY) - return false; - return true; - }; - const blocksInArea = Array.from(document.querySelectorAll('.fo')) - .filter(el => isInArea(el)) - .map(el => el.id.slice(6)) - .map(name => findBlock(name)) - ; - - selectBlocks(blocksInArea); - - p.remove(); - startX = 0; - startY = 0; - currX = 0; - currY = 0; - } - - // update the temp rect - function dragged(d) { - const [rawx, rawy] = d3.mouse(document.querySelector('svg')); - const [x, y] = clampCoordsToGrid(rawx, rawy); - currX = x; - currY = y; - d3.select('polygon.tmp') - .attr('points', getPolygonPoints()) - ; - } - - d3.selectAll('.background').call( - d3.drag() - .on('start', startDrag) - .on('end', endDrag) - .on('drag', dragged) - ); - }, 50); - } - - fitToToolchain = (locMap: LocationMap) => { - if(!this.scrollElement) - return; - - // need to check the editorWrapper size dynamically - // because it changes when the user maximizes/minimizes the editor - const editorWrapper = document.querySelector('.editorWrapper'); - if(!editorWrapper) - return; - const wrapperWidth = editorWrapper.offsetWidth; - const wrapperHeight = editorWrapper.offsetHeight; - - // find the min/max coords (boundaries) for the entire toolchain - const ls = ((Object.values(locMap): any): LocationMapEntry[]); - const minX = Math.min(...ls.map(l => l.block.x)); - const minY = Math.min(...ls.map(l => l.block.y)); - const maxX = Math.max(...ls.map(l => l.block.x + l.block.width)); - const maxY = Math.max(...ls.map(l => l.block.y + l.block.height)); - - // calculate needed zoom level via the largest dimension - const width = (maxX - minX) * svgWidth / wrapperWidth; - const height = (maxY - minY) * svgWidth / wrapperHeight; - // the scrollbars cut into the space so pad it a bit - const zoomScaling = 1.05; - const maxDimension = Math.max(Math.max(width, height) * zoomScaling, minZoomLevel); - // zoom so the entire toolchain can fit in the window - this.setZoomLevel(maxDimension); - - // scroll to view the entire toolchain - const scaleFactor = startingZoomLevel / maxDimension; - const centerX = Number.isFinite(minX) ? minX : svgWidthHalf - wrapperWidth / 4; - const centerY = Number.isFinite(minY) ? minY : svgHeightHalf - wrapperHeight / 4; - this.scrollTo(centerX * scaleFactor, centerY * scaleFactor); - } - - render = () => { - const gridX = gridDistance; - const gridY = gridDistance; - const locMap = this.getLocationMap(); - // scales width/height to the zoomlevel so the background grid lines cover the entire svg - const scaledSvgWidth = svgWidth * (this.state.zoomLevel / startingZoomLevel); - const scaledSvgHeight = svgHeight * (this.state.zoomLevel / startingZoomLevel); - - const getBlocksBoundingBox = (names: string[]) => { - const blockLocs = names.filter(n => locMap.hasOwnProperty(n)).map(n => locMap[n].block); - const xMin = Math.min(...blockLocs.map(l => l.x)); - const yMin = Math.min(...blockLocs.map(l => l.y)); - const width = Math.max(...blockLocs.map(l => l.x + l.width - xMin)); - const height = Math.max(...blockLocs.map(l => l.y + l.height - yMin)); - - return { - x: xMin - gridDistance, - y: yMin - gridDistance, - width: width + gridDistance * 2, - height: height + gridDistance * 2, - }; - }; - - const selectedBlockNames = this.state.selectedBlocks.map(b => b.name); - const selectBoxCoords = getBlocksBoundingBox(selectedBlockNames); - const hiddenBlocks = this.props.experimentData !== undefined ? [] : this.props.groups.reduce((bs, g) => g.collapsed ? [...g.blocks, ...bs] : bs, []); - const shownConnections = ( - selectedBlockNames.length === 0 ? this.props.connections : this.props.connections - .filter(conn => selectedBlockNames.find(n => conn.from.startsWith(`${ n }.`) || conn.to.startsWith(`${ n }.`))) - ).filter(({ from, to }) => { - const fb = from.split('.')[0]; - const tb = to.split('.')[0]; - return !this.props.groups.find(g => g.collapsed && g.blocks.includes(fb) && g.blocks.includes(tb)); - }) - ; - - - const datasetData = {}; - for(const b of this.props.datasets){ - datasetData[b.name] = b; - } - const blockData = {}; - for(const b of this.props.blocks){ - blockData[b.name] = b; - } - const analyzerData = {}; - for(const b of this.props.analyzers){ - analyzerData[b.name] = b; - } - - return ( - <div className={cn('editorWrapper', {maximized: this.state.maximized})}> - <div className='editorMenu'> - <ButtonGroup> - { this.props.toolbarContent || null } - <Button - size='sm' - onClick={this.zoomOut} - > - Zoom out - </Button> - <Button - size='sm' - onClick={this.zoomIn} - > - Zoom in - </Button> - <Button - size='sm' - onClick={() => this.fitToToolchain(locMap)} - > - Fit - </Button> - <Button - size='sm' - onClick={this.toggleMaximized} - > - { this.state.maximized ? 'Pop In' : 'Pop Out' } - </Button> - { !this.props.experimentData && - <Button - color='primary' - size='sm' - onClick={this.toggleHelp} - > - See help - </Button> - } - </ButtonGroup> - </div> - <div className='editorWrapper2' - ref={e => this.scrollElement = e} - > - <svg - onClick={e => { - if((e.button === 0 || e.button === undefined) && this.props.handleBackgroundClick) - this.props.handleBackgroundClick(e); - }} - className='background' - width={svgWidth} - height={svgHeight} - viewBox={this.getSvgViewBox()} - onWheel={e => { - // zoom when scrolling only with the shift key held - if(!e.shiftKey) - return; - - e.preventDefault(); - if(e.deltaY < 0) - this.zoomIn(); - else if(e.deltaY > 0) - this.zoomOut(); - }} - > - { - /* horizontal grid lines */ - [...Array(Math.round(scaledSvgHeight / gridY))].map((u, i) => { - return ( - <line - className='background' - key={`gridY${ i }`} - x1={0} - y1={i * gridY} - x2={scaledSvgWidth} - y2={i * gridY} - stroke='#EEEEEE' - strokeWidth={1} - /> - ); - }) - } - - { - /* vertical grid lines */ - [...Array(Math.round(scaledSvgWidth / gridX))].map((u, i) => { - return ( - <line - className='background' - key={`gridX${ i }`} - x1={i * gridX} - y1={0} - x2={i * gridX} - y2={scaledSvgHeight} - stroke='#EEEEEE' - strokeWidth={1} - /> - ); - }) - } - <line - className='background' - id='gridXCenter' - x1={0} - y1={svgHeightHalf - 2} - x2={scaledSvgWidth} - y2={svgHeightHalf - 2} - stroke='gainsboro' - strokeWidth={4} - /> - <line - className='background' - id='gridYCenter' - x1={svgWidthHalf - 2} - y1={0} - x2={svgWidthHalf - 2} - y2={scaledSvgHeight} - stroke='gainsboro' - strokeWidth={4} - /> - - <g className='backgroundLimit'> - </g> - - { - this.props.groups.map(({name, blocks, collapsed}, i) => { - const {x, y, width, height} = locMap[name].block; - const nameClipId = `groupClip_${ name }`; - return ( - <ContextMenuTrigger - key={i} - id='groupContextMenu' - collect={props => ({ group: name, selectBlocks: this.selectBlocks })} - renderTag='g' - > - <rect - id={`group_${ name }`} - className='tcGroup' - x={x} - y={y} - width={width} - height={height} - fill='grey' - opacity='0.2' - > - <title>Group { `"${ name }"` } contains { blocks.join(', ') }</title> - </rect> - <text - x={x} - y={y + 16} - clipPath={`url(#${ nameClipId })`} - > - { name } - </text> - <clipPath id={nameClipId}> - <rect - x={x} - y={y} - height={height} - width={width} - /> - </clipPath> - </ContextMenuTrigger> - ); - }) - } - - { - Number.isFinite(selectBoxCoords.x) && - <ContextMenuTrigger - id='areaSelectContextMenu' - renderTag='g' - collect={props => ({ selection: this.state.selectedBlocks })} - > - <rect - className='areaSelect' - x={selectBoxCoords.x} - y={selectBoxCoords.y} - width={selectBoxCoords.width} - height={selectBoxCoords.height} - fill='grey' - opacity='0.5' - /> - </ContextMenuTrigger> - } - <ContextMenuTrigger - id='connectionContextMenu' - renderTag='g' - ref={e => this.connectionContextMenu = e} - collect={props => ({ connection: this.state.rightClickConnection })} - > - <g></g> - </ContextMenuTrigger> - <ContextMenuTrigger - id='blockContextMenu' - renderTag='g' - ref={e => this.blockContextMenu = e} - collect={props => ({ name: this.state.rightClickBlock })} - > - <g></g> - </ContextMenuTrigger> - - { - /* connections between blocks */ - shownConnections.map((conn, i) => { - const fromInfo = conn.from.split('.'); - const toInfo = conn.to.split('.'); - - const fromLoc = locMap[fromInfo[0]].outputs[fromInfo[1]]; - const toLoc = locMap[toInfo[0]].inputs[toInfo[1]]; - return ( - <Connection - key={i} - connection={conn} - locMap={locMap} - fromLocMap={fromLoc} - toLocMap={toLoc} - channelColor={this.props.repData.channel_colors[conn.channel]} - errors={this.props.errorBlocks ? this.props.errorBlocks[connectionToId(conn)] || [] : []} - handleContextMenu={this.handleConnectionContextMenu} - /> - ); - }) - } - - { - /* blocks */ - Object.entries(this.props.repData.blocks) - .filter(([name, rep]) => !hiddenBlocks.includes(name)) - .map(([name, rep], i) => { - // assume the block is in "blocks" - let data: ?BlockType = blockData[name]; - // find the set the block belongs to manually - let set: BlockSet = 'blocks'; - if(data === undefined){ - // if its not in there, try datasets - data = datasetData[name]; - set = 'datasets'; - if(data === undefined){ - // the block isnt in datasets, is in analyzers - data = analyzerData[name]; - set = 'analyzers'; - } - } - if(!data) - return null; - - const isSelected = this.state.selectedBlocks.find(b => b.name === name); - - /* - * the block handleClick must be bound here, not in a different file! - * it needs to be bound afterish the d3 drag setup code runs - */ - return ( - <Block - key={i} - name={name} - locMap={locMap[name]} - data={data} - set={set} - highlighted={isSelected !== undefined || (this.props.focusBlocks !== undefined && this.props.focusBlocks.includes(name))} - handleClick={() => this.props.handleBlockClick ? this.props.handleBlockClick(name, set) : undefined} - handleShiftClick={() => { - const sels = this.state.selectedBlocks; - if(!this.props.interactable) - return; - if(sels.find(b => b.name === name)) - this.selectBlocks(sels.filter(b => b.name !== name)); - else - this.selectBlocks([...sels, data]); - }} - channelColor={this.props.repData.channel_colors[data.synchronized_channel || data.name]} - opacity={isSelected ? 0.5 : 1} - experimentString={this.props.experimentData ? this.props.experimentData[name] || 'Not Selected' : undefined} - errors={this.props.errorBlocks ? this.props.errorBlocks[name] || [] : []} - handleContextMenu={this.handleBlockContextMenu} - /> - ); - }) - } - { this.props.svgChildren } - </svg> - {/* the trigger to the menu that pops up on left-clicking the background. - * there needs to be a <ContextMenu> element with the same id somewhere in the divChildren to show anything. - */} - <ContextMenuTrigger - id='svgContextMenu' - ref={e => this.svgContextMenu = e} - collect={props => ({...this.state.svgActionLocation, selectBlocks: this.safeSelectBlocksByName})} - attributes={{ - onContextMenu: (e) => { - e.stopPropagation(); - e.preventDefault(); - } - }} - > - <span></span> - </ContextMenuTrigger> - { this.props.divChildren } - </div> - <HelpModal - toggle={this.toggleHelp} - active={this.state.helpActive} - /> - </div> - ); - } -} diff --git a/conda/js/src/components/toolchain/GraphicalEditorHelpModal.jsx b/conda/js/src/components/toolchain/GraphicalEditorHelpModal.jsx deleted file mode 100644 index bc6f7a7e..00000000 --- a/conda/js/src/components/toolchain/GraphicalEditorHelpModal.jsx +++ /dev/null @@ -1,239 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - TabContent, TabPane, - Alert, - Badge, - Modal, ModalBody, ModalHeader, ModalFooter, - Table, -} from 'reactstrap'; - -type Props = { - // func to close modal - toggle: () => any, - // is the modal active? - active: boolean, -}; - -class GraphicalEditorHelpModal extends React.PureComponent<Props> { - constructor(props: Props){ - super(props); - } - - render = () => { - return ( - <Modal - size='lg' - isOpen={this.props.active} - toggle={this.props.toggle} - fade={true} - onOpened={e => { - /* - const f = document.querySelector('#tcModalInitFocus'); - if(f && f.focus) - f.focus(); - */ - }} - > - <ModalHeader toggle={this.props.toggle}> - Graphical Editor - </ModalHeader> - <ModalBody> - <h3>How do I...</h3> - <h5>Add a block?</h5> - <p> - Right-clicking anywhere on the background grid will open a menu for adding (or pasting) blocks to the grid point where the puck (the black dot that follows your mouse) is. - </p> - <h5>Change the information of a block?</h5> - <p> - Left-clicking on a block will bring up the Block Editor modal, which lets you change the block name, add & remove & rename inputs and outputs, change the synchronized channel, and delete the block. Remember to click <i>Save Changes</i>! If you want to discard your changes, you can either click outside of the modal or click the <b>x</b> button on the top-right corner. - </p> - <h5>Create a connection?</h5> - <p> - Connections are between an output of a block and an input of a block. To create a connection, click on the black rectangle to the right of the desired output, and drag onto the black rectangle next to the desired input. - </p> - <h5>Delete a block or connection?</h5> - <p> - Besides being able to delete a block in the Block Editor, you can right-click blocks or connections to show a menu where you may delete the corresponding element. - </p> - <h5>Temporarily hide connections?</h5> - <p> - The editor only displays connections connected to selected blocks. For example, to only see connections to/from Block X, select Block X (via shift+clicking on the block). - </p> - <h5>Insert blocks from another toolchain, an algorithm, or a database?</h5> - <p> - Right-click on the background grid and select <i>Insert Object Here</i> to insert blocks for an object relative to the position of your mouse. A modal will pop up, and lets you insert a toolchain, algorithm, or part of a database, to easily create toolchains using BEAT objects that you already have created. - </p> - <h3>Keyboard Shortcuts</h3> - <Table striped> - <thead> - <tr> - <th>Action</th> - <th>Shortcut</th> - <th>Additional Info</th> - </tr> - </thead> - <tbody> - <tr> - <td> - Pan - </td> - <td><pre className='preInline'> - Middle-click and move - </pre></td> - <td> - The preferred way to pan around the editor is to use a mouse with middle-click functionality. You can middle-click anywhere in the canvas and then move your mouse to pan around on both axis. If this does not work for you, you may need to turn on <i>autoscrolling</i> in your browser settings. - </td> - </tr> - <tr> - <td> - Pan vertically - </td> - <td><pre className='preInline'> - Scroll up/down - </pre></td> - <td> - You can also manually drag the scroll bar on the right edge of the editor. - </td> - </tr> - <tr> - <td> - Pan horizontally - </td> - <td> - <pre className='preInline'>Scroll left/right</pre> - {' '} - <span> - or - </span> - {' '} - <pre className='preInline'>Left arrow key & Right arrow key</pre> - </td> - <td> - You can also manually drag the scroll bar on the bottom edge of the editor. To scroll left or right, three-button mice will usually let you click & hold on the middle button to scroll freely. - </td> - </tr> - <tr> - <td> - Zoom in/out - </td> - <td><pre className='preInline'> - Shift + scroll up/down - </pre></td> - <td> - You can also use the {`"Zoom in"`} and {`"Zoom out"`} buttons in the top-right menu. - </td> - </tr> - <tr> - <td> - Edit a block - </td> - <td><pre className='preInline'> - Left click - </pre></td> - <td> - Left-clicking a block will open a modal where you can edit the block name, the synchronized channel, inputs, and outputs. - </td> - </tr> - <tr> - <td> - Move blocks - </td> - <td><pre className='preInline'> - Left click + drag - </pre></td> - <td> - You may move a block at a time by clicking & dragging on a block. You may move a selection or group of blocks by dragging the grey rectangle representing the selection or group. - </td> - </tr> - <tr> - <td> - Open a context (right-click) menu - </td> - <td><pre className='preInline'> - Right click - </pre></td> - <td> - There are context menus for: blocks, connections, area selections, groups, and the background. - </td> - </tr> - <tr> - <td> - Select Multiple Blocks - </td> - <td> - <pre className='preInline'> - Shift + left click - </pre> - {' '} - <span> - or - </span> - {' '} - <pre className='preInline'> - Click + drag - </pre> - </td> - <td> - Shift + left-clicking a block will toggle selection. Clicking on the background grid will clear the selection. - </td> - </tr> - <tr> - <td> - Create a Connection between an output and an input - </td> - <td> - <pre className='preInline'> - Left click + drag - </pre> - {' '} - <span> - on the black rectangle next to the desired output, and release the drag on the black rectangle next to the desired input. - </span> - </td> - <td> - You can also create a connection by clicking on the black rectangle of an output and then clicking on the black rectangle of an input. This lets you create connections between distant blocks and move around the canvas. - </td> - </tr> - <tr> - <td> - Create an Algorithm based on a block - </td> - <td> - <pre className='preInline'> - Left click - </pre> - {' '} - <span> - on the block to bring up the block editor. At the top of the modal, enter the username and name for the algorithm to be created, and click the <i>Create</i> button to generate an algorithm based off of the connections, inputs, and outputs of the block. You will have to edit the algorithm in the editor to choose the types, and to add any any parameters or results. - </span> - </td> - <td> - This only works for normal and analyzer blocks. If you do not see your new algorithm, refresh the browser tab/window. - </td> - </tr> - <tr> - <td> - See more information - </td> - <td> - <pre className='preInline'> - Hover - </pre> - </td> - <td> - Blocks and connections in the editor have extra information found by hovering over the element for a couple seconds. - </td> - </tr> - </tbody> - </Table> - </ModalBody> - </Modal> - ); - } -} - -export default GraphicalEditorHelpModal; diff --git a/conda/js/src/components/toolchain/InsertObjectModal.jsx b/conda/js/src/components/toolchain/InsertObjectModal.jsx deleted file mode 100644 index 788a8157..00000000 --- a/conda/js/src/components/toolchain/InsertObjectModal.jsx +++ /dev/null @@ -1,399 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - TabContent, TabPane, - Alert, - Badge, - Modal, ModalBody, ModalHeader, ModalFooter, - Table, - Input, - Button, - ButtonGroup, - FormGroup, - ListGroup, - ListGroupItem, -} from 'reactstrap'; - -import type { FlattenedDatabaseEntry } from '@store/selectors'; - -import type { ConnectionType } from '@helpers/toolchainTypes'; -import type { Protocol, Set as ProtocolSet } from '../database/DatabaseEditor.jsx'; -import type { BeatObject } from '@helpers/beat'; -import { generateNewKey } from '@helpers'; - -import SearchWorker from '@helpers/search.worker.js'; - -type ObjectTypeOption = 'toolchains' | 'protocols' | 'sets' | 'normalAlgorithms' | 'analyzerAlgorithms'; - -type Props = { - // func to close modal - toggle: () => any, - // is the modal active? - active: boolean, - // user selected a search result - addNewBlocks: (type: ObjectTypeOption, newBlocksData: any[], newConnections?: ConnectionType[]) => any, - // all toolchains - toolchains: BeatObject[], - // all database protocols - protocols: BeatObject[], - // sets of protocols of protocols - sets: FlattenedDatabaseEntry[], - // algorithms for normal blocks (inputs & outputs) - normalAlgorithms: BeatObject[], - // algorithms for analyzer blocks (inputs & results) - analyzerAlgorithms: BeatObject[], - usedNames: string[], -}; - -type Res = BeatObject[] | FlattenedDatabaseEntry[] | any; - -type State = { - searchResults: ?Res, - searchFilter: ObjectTypeOption, -}; - -const options: ObjectTypeOption[] = ['toolchains', 'protocols', 'sets', 'normalAlgorithms', 'analyzerAlgorithms']; -const optionText = { - toolchains: 'Toolchain', - protocols: 'Protocol', - sets: 'Dataset', - normalAlgorithms: 'Block Algorithm', - analyzerAlgorithms: 'Analyzer Algorithm', -}; - -class InsertObjectModal extends React.PureComponent<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - searchResults: this.props[options[0]], - searchFilter: options[0], - } - - searchWorker = null; - - componentDidMount = () => { - this.searchWorker = new SearchWorker(); - this.searchWorker.onmessage = (m) => { - this.setState(prevState => ({ searchResults: m.data })); - }; - this.updateFuseInstance(); - } - - componentDidUpdate = (prevProps: Props) => { - if(this.props[this.state.searchFilter] !== prevProps[this.state.searchFilter]){ - this.updateFuseInstance(this.props[this.state.searchFilter]); - } - } - - updateFuseInstance = (data: any[] = this.props[this.state.searchFilter]) => { - if(!this.searchWorker) - throw new Error(`searchWorker is not instantiated!`); - - this.searchWorker.postMessage( - { - type: 'dataChanged', - payload: { - data, - options: { - shouldSort: true, - threshold: 0.6, - location: 0, - distance: 100, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: Object.keys(data.length > 0 ? data[0] : {}), - } - } - } - ); - } - - search = (str: string) => { - if(!this.searchWorker) - throw new Error(`searchWorker is not instantiated!`); - this.searchWorker.postMessage( - { - type: 'search', - payload: str - } - ); - } - - updateSearchFilter = (filter: ObjectTypeOption) => { - this.setState(prevState => ({ - searchFilter: filter, - searchResults:this.props[filter], - })); - this.updateFuseInstance(this.props[filter]); - } - - stringifyResult = (obj: any, type: ObjectTypeOption): string => { - if(!obj) - return ''; - switch(type){ - case 'toolchains': - // tc obj - return `datasets: ${ obj.contents.datasets.length }, blocks: ${ obj.contents.blocks.length }`; - case 'protocols': - // protocol obj w "database" field for db name - return `sets: ${ obj.sets.length }`; - case 'sets': - // set w protocol & db - return `outputs: ${ Object.keys(obj.outputs).length }`; - case 'normalAlgorithms': - // alg obj - return `inputs: ${ - obj.contents.groups.reduce((iNum, g) => g.inputs ? iNum + Object.keys(g.inputs).length : iNum, 0) - }, outputs: ${ - obj.contents.groups.reduce((iNum, g) => g.outputs ? iNum + Object.keys(g.outputs).length : iNum, 0) - }`; - case 'analyzerAlgorithms': - // alg obj - return `inputs: ${ - obj.contents.groups.reduce((iNum, g) => g.inputs ? iNum + Object.keys(g.inputs).length : iNum, 0) - }`; - default: - return obj.name; - } - } - - stringifyResultName = (obj: any) => { - if(!obj) - return ''; - if(obj.set) - return `${ obj.protocol }/${ obj.set } (${ obj.database })`; - if(obj.database) - return `${ obj.name } (${ obj.database })`; - if(obj.name) - return obj.name; - return 'undefined'; - } - - generateNewBlockData = (obj: any): {blocks: any[], connections: ConnectionType[]} | any[] => { - const copiedObj = JSON.parse(JSON.stringify(obj)); - const usedNames = this.props.usedNames; - const type = this.state.searchFilter; - switch(type){ - case 'toolchains': - const rep = copiedObj.contents.representation.blocks; - // add blocks/connections from a toolchain - // map all the blocks to new data to give to addBlocks() - const newBlocksData = [ - ...copiedObj.contents.datasets - .map((blk) => ([generateNewKey(blk.name, usedNames), 'datasets', rep[blk.name].col, rep[blk.name].row, blk])), - ...copiedObj.contents.blocks - .map((blk) => ([generateNewKey(blk.name, usedNames), 'blocks', rep[blk.name].col, rep[blk.name].row, blk])), - ...copiedObj.contents.analyzers - .map((blk) => ([generateNewKey(blk.name, usedNames), 'analyzers', rep[blk.name].col, rep[blk.name].row, blk])), - ]; - - const nameMap = {}; - for(const b of newBlocksData){ - nameMap[b[4].name] = b[0]; - if(b[1] === 'blocks' || b[1] === 'analyzers') - b[4].synchronized_channel = nameMap[b[4].synchronized_channel]; - } - - const connections = copiedObj.contents.connections - .map(({ from, to, channel }) => { - const fromSplit = from.split('.'); - const toSplit = to.split('.'); - return { - from: `${ nameMap[fromSplit[0]] }.${ fromSplit[1] }`, - to: `${ nameMap[toSplit[0]] }.${ toSplit[1] }`, - channel: nameMap[channel], - }; - }); - - // reset the locations of all these blocks - make sure that the point (0,0) is at the top-left of the toolchain - const minX = Math.min(...newBlocksData.map(d => d[2])); - const minY = Math.min(...newBlocksData.map(d => d[3])); - for(const b of newBlocksData){ - b[2] -= minX; - b[3] -= minY; - b[4].name = b[0]; - } - - return { - blocks: newBlocksData, - connections, - }; - case 'protocols': - // add a block for each set in each protocol in the database - const newBlocks = obj.sets - // compile basic info for the set (the new name & the outputs for the block) - .map((set, i) => ({ - name: generateNewKey(`${ obj.name }_${ set.name }`, usedNames), - outputs: Object.keys(set.outputs), - })) - // convert the set's basic info into data arrs for addBlocks() - .map((setData, i) => [setData.name, 'datasets', 0, 0, { outputs: setData.outputs }]); - - // shift the y coord of each new block down according to the # of outputs - // accumulate this change so the blocks will all be x-aligned with 1 row between them - let yCount = 0; - for(const i in newBlocks){ - newBlocks[i][3] = yCount; - yCount += newBlocks[i][4].outputs.length + 3; - } - - return newBlocks; - case 'sets': - // add from database's protocol's set - const setBlock = [ - generateNewKey(`${ obj.protocol }_${ obj.set }`, usedNames), - 'datasets', - 0, - 0, - { outputs: Object.keys(obj.outputs) } - ]; - - return [setBlock]; - case 'normalAlgorithms': - // create a block compatible with the alg - const normalBlock = [ - generateNewKey(obj.name.replace(/\//g, '_'), usedNames), - 'blocks', - 0, - 0, - { - outputs: Object.keys(obj.contents.groups[0].outputs), - inputs: obj.contents.groups - .map(g => Object.keys(g.inputs)) - .reduce((arr, is) => [...arr, ...is], []), - synchronized_channel: '', - } - ]; - - return [normalBlock]; - case 'analyzerAlgorithms': - // create a block compatible with the alg - const analyzerBlock = [ - generateNewKey(obj.name.replace(/\//g, '_'), usedNames), - 'analyzers', - 0, - 0, - { - inputs: obj.contents.groups - .map(g => Object.keys(g.inputs)) - .reduce((arr, is) => [...arr, ...is], []), - synchronized_channel: '', - } - ]; - - return [analyzerBlock]; - default: - return []; - } - } - - render = () => { - return ( - <Modal - size='lg' - isOpen={this.props.active} - toggle={this.props.toggle} - fade={true} - onOpened={e => { - /* - const f = document.querySelector('#tcModalInitFocus'); - if(f && f.focus) - f.focus(); - */ - }} - > - <ModalHeader toggle={this.props.toggle}> - Insert blocks from an existing object - </ModalHeader> - <ModalBody> - <FormGroup row> - <Col> - <span className='text-muted'> - Insert the blocks from a compatible BEAT object into this toolchain. You may insert an existing toolchain or blocks generated from a database protocol, database protocol set, or algorithm. - </span> - </Col> - </FormGroup> - <FormGroup row> - <Col> - </Col> - <Col sm='auto'> - <ButtonGroup> - { - options.map((o, i) => { - const isCurrentOption = this.state.searchFilter === o; - return ( - <Button - key={i} - onClick={e => this.updateSearchFilter(o)} - color={isCurrentOption ? 'primary' : 'secondary'} - > - { optionText[o] } - </Button> - ); - }) - } - - </ButtonGroup> - </Col> - <Col> - </Col> - </FormGroup> - <FormGroup row> - <Col sm={12}> - <Input - type='text' - placeholder='Search...' - onChange={e => this.search(e.target.value)} - autoFocus - /> - </Col> - </FormGroup> - <FormGroup row> - <Col sm={12}> - <ListGroup className='searchResults'> - { - this.state.searchResults && - this.state.searchResults.map((res, i) => - <ListGroupItem - key={i} - tag='button' - action - onClick={e => { - const newData = this.generateNewBlockData(res); - if(Array.isArray(newData)) - this.props.addNewBlocks( - this.state.searchFilter, - newData, - ); - else - this.props.addNewBlocks( - this.state.searchFilter, - newData.blocks, - newData.connections, - ); - this.props.toggle(); - }} - > - { this.stringifyResultName(res) } - {' '} - <small className='text-muted'> - { this.stringifyResult(res, this.state.searchFilter) } - </small> - </ListGroupItem> - ) - } - </ListGroup> - </Col> - </FormGroup> - </ModalBody> - </Modal> - ); - } -} - -export default InsertObjectModal; diff --git a/conda/js/src/components/toolchain/RenameGroupModal.jsx b/conda/js/src/components/toolchain/RenameGroupModal.jsx deleted file mode 100644 index bdee3cf3..00000000 --- a/conda/js/src/components/toolchain/RenameGroupModal.jsx +++ /dev/null @@ -1,93 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Modal, ModalBody, ModalHeader, ModalFooter, - Button, - Form, -} from 'reactstrap'; - -import { generateNewKey } from '@helpers'; - -import CacheInput from '../CacheInput.jsx'; - -type Props = { - // func to close modal - toggle: () => any, - // is the modal active? - active: boolean, - currentName: string, - usedNames: string[], - saveNewName: (newName: string) => any, -}; - -type State = { - newName: string, -}; - -class RenameGroupModal extends React.PureComponent<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - newName: this.props.currentName, - } - - componentDidUpdate = (prevProps: Props) => { - if(this.props.currentName !== prevProps.currentName){ - this.setState({ newName: this.props.currentName }); - } - } - - validateFunc = (str: string) => { - if(str === this.props.currentName) - return true; - if(!this.props.usedNames.includes(str)) - return true; - return <span>The group name must be unique across all block & group names in the toolchain</span>; - } - - saveNewName = () => { - this.props.saveNewName(this.state.newName); - this.props.toggle(); - } - - render = () => { - return ( - <Modal - isOpen={this.props.active} - toggle={this.props.toggle} - fade={true} - > - <ModalHeader toggle={this.props.toggle}> - Rename Group { `"${ this.props.currentName }"` } - </ModalHeader> - <ModalBody> - <Form - onSubmit={this.saveNewName} - > - <CacheInput - delay={0} - autoFocus - fieldTest - value={this.state.newName} - validateFunc={this.validateFunc} - onChange={e => this.setState({ newName: e.target.value })} - /> - </Form> - </ModalBody> - <ModalFooter> - <Button - block - onClick={this.saveNewName} - > - Save Changes - </Button> - </ModalFooter> - </Modal> - ); - } -} - -export default RenameGroupModal; diff --git a/conda/js/src/components/toolchain/ToolchainBlock.jsx b/conda/js/src/components/toolchain/ToolchainBlock.jsx deleted file mode 100644 index b06ea775..00000000 --- a/conda/js/src/components/toolchain/ToolchainBlock.jsx +++ /dev/null @@ -1,308 +0,0 @@ -// @flow -import * as React from 'react'; -import { - Container, - Row, - Col, - Button, - ButtonGroup, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, - Navbar, - Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, - Badge, -} from 'reactstrap'; -import { ContextMenuTrigger } from 'react-contextmenu'; -import cn from 'classnames'; -import type { BlockSet, BlockCoords } from '@helpers/toolchainTypes'; - -export type Props = { - name: string, - // provides the location & dimensions of the svg elements of the block - // (the block itself & its inputs/outputs) - locMap: { - block: BlockCoords, - inputs?: { [string]: BlockCoords }, - outputs?: { [string]: BlockCoords }, - }, - // the block data (name, i/os, channel, etc.) - data: any, - // the set the block belongs to ('blocks', 'datasets', or 'analyzers') - set: BlockSet, - // handler for the user clicking the block - handleClick: (name: string, set: BlockSet) => any, - // handler for the user clicking the block - handleShiftClick: (name: string, set: BlockSet) => any, - // the color of the channel the block is sync'd to - channelColor: string, - // highlighted blocks have a dashed border (see the 'highlighted' CSS class styling in GraphicalEditor.css) - highlighted: boolean, - // string to show at the bottom of the block - // used to display the selected dataset/algorithm in the experiment editor - experimentString?: string, - errors: string[], - handleContextMenu?: (e: any, name: string, set: string) => any, -}; - -export const blockNameToId = (name: string) => `block_${ name }`; - -class ToolchainBlock extends React.Component<Props> { - constructor(props: Props){ - super(props); - } - - /* - * Custom implementation of shouldComponentUpdate for performance reasons! - * "Why not just use PureComponent??" - * PureComponent implements a default shouldComponentUpdate that shallowly compares - * all current & next props/state values. - * Because the click handlers are always not equal (since they're dynamically generated in the loop in - * GraphicalEditor.jsx), blocks are *always* rerendered. - * Also, the locMap object of every block is technically somehow a different object whenever - * a subset of the blocks are moved. - * This means that every block change means rerendering all the blocks. - * By writing a custom shouldComponentUpdate, we can use more detailed logic that prevents - * the unnecessary rerenders. - * A couple things to keep in mind: - * - the click handlers dont functionally change if the block data doesnt change. - * - the locMap's inputs&outputs values dont change if the block's locMap or data hasnt changed - * - the errors array is a different array every time technically, so check the values - */ - shouldComponentUpdate(nextProps: Props){ - for(const key in nextProps){ - if(key === 'locMap' || key === 'handleClick' || key === 'handleShiftClick' || key === 'handleContextMenu'){ - continue; - } else if(key === 'errors'){ - if(nextProps[key].length !== this.props.errors.length) - return true; - for(const i in nextProps[key]){ - if(nextProps[key][i] !== this.props[key][i]) - return true; - } - } else if(nextProps[key] !== this.props[key]){ - return true; - } - } - - const nowLoc = this.props.locMap.block; - const nextLoc = nextProps.locMap.block; - if(nowLoc.x !== nextLoc.x) - return true; - if(nowLoc.y !== nextLoc.y) - return true; - if(nowLoc.width !== nextLoc.width) - return true; - if(nowLoc.height !== nextLoc.height) - return true; - - return false; - } - - render = () => { - const name = this.props.name; - const {x, y, height, width} = this.props.locMap.block; - - const hasInputs = this.props.data && this.props.data.hasOwnProperty('inputs'); - const hasOutputs = this.props.data && this.props.data.hasOwnProperty('outputs'); - const inputs = hasInputs ? this.props.data.inputs : []; - const outputs = hasOutputs ? this.props.data.outputs : []; - const nameText = name.length > 17 ? `${ name.slice(0, 17) }…` : name; - const expStr = this.props.experimentString; - - return ( - <g className='tcBlock'> - {/* white fill background */} - <rect - className='tcBlockWhiteFill' - x={x} y={y} height={height} width={width} - fill='white' - /> - {/* color background tint */} - <rect className={cn('tcBlockBackground', {highlighted: this.props.highlighted})} - x={x} y={y} height={height} width={width} - fill={this.props.channelColor} - fillOpacity={0.05} - stroke='black' - /> - {/* block name */} - <text - x={x} - y={y + 16} - width={width} - className='tcBlockTitle' - > - { nameText } - </text> - {/* line below name */} - <line - x1={x} - y1={y + 20} - x2={x + width} - y2={y + 20} - stroke='grey' - /> - {/* the little upper-right block showing the color of the currently sync'd channel */} - <rect - x={x + width - 20} - y={y} - width={20} - height={20} - fill={this.props.channelColor} - /> - {/* exp string */} - { expStr && - <text - x={x} - y={y + 36} - fill='slategray' - > - { expStr.length > 19 ? `${ expStr.slice(0, 19) }…` : expStr } - </text> - } - - { - /* inputs - * draws the inputs (both the black rects for connections and the corresponding input name) - */ - inputs.map((inp, i) => { - // get the location/dimensions of the input - const loc = this.props.locMap.inputs[inp]; - // width changes between half the block and the full block depending if theres outputs or not - const varWidth = hasOutputs ? width / 2 : width; - // the shown text needs to be truncated based on the available space - // easy to calculate because the text is monospace! - const maxlen = hasOutputs ? 8 : 19; - // truncate text, add ellipsis if it's too long - const text = inp.length > maxlen ? `${ inp.slice(0, maxlen) }…` : inp; - return ( - <g - key={i} - x={loc.x} - y={loc.y} - > - <rect - className='iBlock' - id={`${ name }-input-${ inp }`} - key={i} - {...loc} - fill='black' - /> - <text - x={loc.x + loc.width} - y={loc.y + loc.height * 0.75} - width={varWidth} - > - { text } - </text> - </g> - ); - }) - } - { - /* outputs - * draws the inputs (both the black rects for connections and the corresponding input name) - */ - outputs.map((out, i) => { - const loc = this.props.locMap.outputs[out]; - // width changes between half the block and the full block depending if theres inputs or not - const varWidth = hasInputs ? width / 2 : width; - // the shown text needs to be truncated based on the available space - // easy to calculate because the text is monospace! - const maxlen = hasInputs ? 9 : 19; - // truncate text, add ellipsis if it's too long - const text = out.length > maxlen ? `${ out.slice(0, maxlen) }…` : out; - // to align output text to the output blocks (the right side of the block), - // calculate the x-offset needed, in character count - const offsetCharacterCount = (hasInputs ? 10 : 20) - text.length; - // a monospace char @font-size=16px is apparently 10px wide - const charWidthPx = 10; - // put it all together, offset 1px to the left to avoid chars overlapping with block border - const x = ((loc.x - varWidth) + offsetCharacterCount * charWidthPx) - 1; - return ( - <g - key={i} - > - <rect - className='oBlock' - id={`${ name }-output-${ out }`} - key={i} - {...loc} - fill='black' - /> - <text - x={x} - y={loc.y + loc.height * 0.75} - > - { text } - </text> - </g> - ); - }) - } - {/* block errors for the experiment editor */} - { this.props.errors.length > 0 && - <React.Fragment> - <rect className='errors' - x={x} y={y} height={height} width={width} - fill='crimson' - opacity='0.8' - stroke='crimson' - /> - <text - x={x + width / 2 - 5} - y={y + 40} - fontSize={50} - fill='white' - > - ! - </text> - <text - x={x + 2} - y={y + height - 6} - fill='white' - fontSize={12} - > - { this.props.errors[0] } - </text> - </React.Fragment> - } - {/* the background rectangle with the click handler */} - <rect id={blockNameToId(name)} className='fo' - x={x} y={y} height={height} width={width} - fill='white' - opacity={0.0001} - onClick={e => { - if(!(e.button === 0 || e.button === undefined)) - return; - if(e.shiftKey) - this.props.handleShiftClick(name, this.props.set); - else - this.props.handleClick(name, this.props.set); - e.stopPropagation(); - e.preventDefault(); - }} - onContextMenu={e => this.props.handleContextMenu && this.props.handleContextMenu(e, this.props.name, this.props.set)} - > - <title> - { name } synchronized to the {this.props.data.synchronized_channel || name} channel - { this.props.experimentString ? ` with "${ this.props.experimentString }" assigned to it` : ''} - </title> - </rect> - </g> - ); - } -} - -export default ToolchainBlock; diff --git a/conda/js/src/components/toolchain/ToolchainConnection.jsx b/conda/js/src/components/toolchain/ToolchainConnection.jsx deleted file mode 100644 index 400474f9..00000000 --- a/conda/js/src/components/toolchain/ToolchainConnection.jsx +++ /dev/null @@ -1,134 +0,0 @@ -// @flow -import * as React from 'react'; -import { ContextMenu, MenuItem, ContextMenuTrigger } from 'react-contextmenu'; -import cn from 'classnames'; - -import type { BlockCoords, ConnectionType } from '@helpers/toolchainTypes'; - -type Props = { - fromLocMap: BlockCoords, - toLocMap: BlockCoords, - // provides the location of the ends of the connection - connection: ConnectionType, - // the color of the channel the connection is sync'd to - channelColor: string, - errors: string[], - handleContextMenu?: (e: any, ConnectionType) => any, -}; - -// gets a unique id for the connection -export const connectionToId = ({ from, to, channel }: {from: string, to: string, channel: string}) => - `${ from.replace('.', '-') }-${ to.replace('.', '-') }`; - -class ToolchainConnection extends React.Component<Props> { - constructor(props: Props){ - super(props); - } - - /* - * Custom implementation of shouldComponentUpdate for performance reasons! - * "Why not just use PureComponent??" - * PureComponent implements a default shouldComponentUpdate that shallowly compares - * all current & next props/state values. - * Because the click handlers are always not equal (since they're dynamically generated in the loop in - * GraphicalEditor.jsx), blocks are *always* rerendered. - * Also, the locMap objects are technically somehow a different object whenever - * a subset of the blocks are moved. - * This means that every block change means rerendering all the blocks. - * By writing a custom shouldComponentUpdate, we can use more detailed logic that prevents - * the unnecessary rerenders. - * A couple things to keep in mind: - * - the click handlers dont functionally change if the block data doesnt change. - * - the errors array is a different array every time technically, so check the values - * - only the positions (x & y) of the locmap data matters - * - the channel in the connection data can change, but not the to/from - */ - shouldComponentUpdate(nextProps: Props){ - for(const key in nextProps){ - if(key === 'fromLocMap' || key === 'toLocMap' || key === 'handleContextMenu'){ - continue; - } else if(key === 'errors'){ - if(nextProps[key].length !== this.props.errors.length) - return true; - for(const i in nextProps[key]){ - if(nextProps[key][i] !== this.props[key][i]) - return true; - } - } else if(key === 'connection'){ - if(nextProps[key].channel !== this.props[key].channel - || nextProps[key].from !== this.props[key].from - || nextProps[key].to !== this.props[key].to - ) - return true; - } else if(nextProps[key] !== this.props[key]){ - return true; - } - } - - const fromLoc = this.props.fromLocMap; - const toLoc = this.props.toLocMap; - const fromLocNext = nextProps.fromLocMap; - const toLocNext = nextProps.toLocMap; - - if(fromLoc.x !== fromLocNext.x) - return true; - if(fromLoc.y !== fromLocNext.y) - return true; - if(toLoc.x !== toLocNext.x) - return true; - if(toLoc.y !== toLocNext.y) - return true; - - return false; - } - - render = () => { - const conn = this.props.connection; - const connectionId = `${ connectionToId(conn) }`; - const fromLoc = this.props.fromLocMap; - const toLoc = this.props.toLocMap; - //console.log(`connecting "${ connId }" from ${ fromInfo } to ${ toInfo }`); - //x & y coords for the beginning and end of the connection - - /* the right-click menu wraps the actual lines */ - return ( - <g className='tcConnection' - onContextMenu={e => this.props.handleContextMenu ? this.props.handleContextMenu(e, conn) : {}} - > - {/* the first line is almost invisible to widen the space for the mouse events (so its easier for users to do stuff */} - <line - id={connectionId} - stroke={this.props.channelColor} - strokeOpacity={0.005} - strokeWidth={10} - x1={fromLoc.x + 2} - y1={fromLoc.y + 9} - x2={toLoc.x + 2} - y2={toLoc.y + 9} - > - <title> - Connection from {conn.from} to {conn.to} synchronized to the {conn.channel} channel{' '} - { this.props.errors[0] } - </title> - </line> - {/* the second line is just for show */} - <line - className={cn({ error: this.props.errors.length > 0 })} - stroke={this.props.channelColor} - strokeWidth={2} - x1={fromLoc.x + 2} - y1={fromLoc.y + 6} - x2={toLoc.x + 2} - y2={toLoc.y + 6} - > - <title> - Connection from {conn.from} to {conn.to} synchronized to the {conn.channel} channel{' '} - { (this.props.errors || [])[0] } - </title> - </line> - </g> - ); - } -} - -export default ToolchainConnection; diff --git a/conda/js/src/components/toolchain/ToolchainConnection.spec.jsx b/conda/js/src/components/toolchain/ToolchainConnection.spec.jsx deleted file mode 100644 index 4fca253d..00000000 --- a/conda/js/src/components/toolchain/ToolchainConnection.spec.jsx +++ /dev/null @@ -1,117 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import C from './ToolchainConnection.jsx'; - -describe('<ToolchainConnection />', () => { - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - const testLocMap = { - block1: { - inputs: { - input1: { - x: 1, - y: 1, - width: 0, - height: 0, - }, - }, - outputs: { - output1: { - x: 5, - y: 1, - width: 0, - height: 0, - }, - }, - }, - block2: { - inputs: { - input2: { - x: 1, - y: 6, - width: 0, - height: 0, - }, - }, - outputs: { - output2: { - x: 5, - y: 6, - width: 0, - height: 0, - }, - }, - }, - }; - - const testConn = { - from: 'block1.output1', - to: 'block2.input2', - channel: 'testChannel', - }; - - const testChannelColor = 'pink'; - const fromLocMap = testLocMap.block1.outputs.output1; - const toLocMap = testLocMap.block2.inputs.input2; - - it('accepts the test connection with the right props', () => { - wrapper = mount( - <svg width='10' height='10'> - <C - fromLocMap={fromLocMap} - toLocMap={toLocMap} - connection={testConn} - channelColor={testChannelColor} - errors={[]} - /> - </svg> - ); - const c = wrapper.children(); - - expect(c).to.have.props( - ['fromLocMap', 'toLocMap', 'connection', 'channelColor'] - ).deep.equal( - [fromLocMap, toLocMap, testConn, testChannelColor] - ); - }); - - it('correctly styles the visible line', () => { - wrapper = mount( - <svg width='10' height='10'> - <C - fromLocMap={fromLocMap} - toLocMap={toLocMap} - connection={testConn} - channelColor={testChannelColor} - errors={[]} - /> - </svg> - ); - const c = wrapper.children().find('line + line'); - - const expectedProps = { - stroke: 'pink', - strokeWidth: 2, - x1: 5 + 2, - y1: 1 + 6, - x2: 1 + 2, - y2: 6 + 6, - }; - - expect(c).to.have.props( - Object.keys(expectedProps) - ).deep.equal( - Object.values(expectedProps) - ); - }); -}); diff --git a/conda/js/src/components/toolchain/ToolchainEditor.css b/conda/js/src/components/toolchain/ToolchainEditor.css deleted file mode 100644 index 1926a309..00000000 --- a/conda/js/src/components/toolchain/ToolchainEditor.css +++ /dev/null @@ -1,18 +0,0 @@ -.toolchainEditor svg { - cursor: pointer; -} - -.toolchainEditor text:hover { - clip-path: none; -} - -/* .iBlock:hover, */ -.toolchainEditor .oBlock:hover { - stroke: black; - stroke-width: 3; -} - -.toolchainEditor .tcConnection > line:hover + line, -.toolchainEditor .tcConnection > line + line:hover { - stroke-width: 5; -} diff --git a/conda/js/src/components/toolchain/ToolchainEditor.jsx b/conda/js/src/components/toolchain/ToolchainEditor.jsx deleted file mode 100644 index 3e321381..00000000 --- a/conda/js/src/components/toolchain/ToolchainEditor.jsx +++ /dev/null @@ -1,1520 +0,0 @@ -// @flow -import './ToolchainEditor.css'; -import * as React from 'react'; -import { - Container, - Row, - Col, - Button, - ButtonGroup, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, - Navbar, - Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, - Badge, -} from 'reactstrap'; - -import { connect } from 'react-redux'; -import { ContextMenu, MenuItem, ContextMenuTrigger, SubMenu } from 'react-contextmenu'; - -import { getRandomBrightColor, generateNewKey, copyObj } from '@helpers'; -import { - getValidToolchainObj as getValidObj, - nameValidator, nameSegmentsForEntity, getTcFromExpName, getValidAlgorithmObj -} from '@helpers/beat'; -import type { BeatObject } from '@helpers/beat'; -import { fetchLayout, genModuleApiFuncs } from '@helpers/api'; -import Validate, { VALIDATORS } from '@helpers/schema'; - -import * as Actions from '@store/actions.js'; -import * as Selectors from '@store/selectors.js'; -import type { FlattenedDatabaseEntry } from '@store/selectors'; - -import Block from './ToolchainBlock.jsx'; -import type { NormalBlock, AnalyzerBlock, BlockType, ConnectionType, BlockSet, Group, Contents } from '@helpers/toolchainTypes'; -import { connectionToId } from './ToolchainConnection.jsx'; -import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; -import CacheInput from '../CacheInput.jsx'; -import EditModal from './ToolchainModal.jsx'; -import type { ModalCache, ModalAction } from './ToolchainModal.jsx'; -import GraphicalEditor, { - blockWidth, - gridDistance, - convertWorldToDataCoords, - clampCoordsToGrid, -} from './GraphicalEditor.jsx'; -import type { Protocol, Set as ProtocolSet } from '../database/DatabaseEditor.jsx'; -import InsertObjectModal from './InsertObjectModal.jsx'; -import RenameGroupModal from './RenameGroupModal.jsx'; - -type Props = { - // saved data for the current toolchain - data: { - name: string, - contents: Contents, - extraContents: { - groups: Group[] - }, - }, - // all toolchains - toolchains: BeatObject[], - // all databases - databases: BeatObject[], - // sets of protocols of databases - // get protocols for InsertObjectModal - protocols: any, - sets: FlattenedDatabaseEntry[], - normalAlgorithms: BeatObject[], - analyzerAlgorithms: BeatObject[], - // func to save changes on the current tc - saveFunc: (BeatObject) => any, - updateFunc: (BeatObject) => any, - // creates an algorithm from block data from the ToolchainModal - createAlgorithmFromBlock: (data: NormalBlock | AnalyzerBlock, conns: ConnectionType[]) => any, -}; - -// represents a timeline of state changes -// the current state sits between the paste & future states -// enables very fast redo/undo -type History = { - // past states - past: BeatObject[], - // future states - future: BeatObject[], -}; - -type State = { - // info for the modal for editing blocks - // if the fields are undefined, the modal shouldnt be up - modalBlockInfo: { - // navigating to a specific block in the JSON - // requires a set and a name - set: ?BlockSet, - name: ?string, - active: boolean, - }, - // the clipboard for copy/pasting blocks - clipboard?: BlockType[], - // is the object insertion modal active? - insertModalActive: boolean, - // is the modal for renaming groups active? - renameGroupModalInfo: ?string, - // the current history for the editor - history: History, -}; - -// generates a new history object whenever the user does an action that changes state -const generateNewHistory = (state: State, data: any): History => { - return { - past: [ - ...state.history.past, - copyObj(data), - ], - future: [], - }; -}; - - -const generateConnectionRepresentations = (connections: ConnectionType[]) => Object.assign({}, ...connections.map(c => ({[`${ c.from }/${ c.to }`]: []}))); - -// helper func for addBlocks() -// generates all the new data necessary for a new block, -// including the representation (location & dimensions), -// the channel color, -// and an initial block object -const generateNewBlockData = (blockName: string, set: BlockSet, x: number, y: number, copyBlock?: ?BlockType) => { - let newBlock = copyBlock ? { ...copyBlock } : undefined; - if(newBlock === undefined){ - newBlock = {}; - if(set === 'blocks' || set === 'analyzers'){ - newBlock.inputs = [ - 'input', - ]; - newBlock.synchronized_channel = ''; - } - if(set === 'blocks' || set === 'datasets'){ - newBlock.outputs = [ - 'output', - ]; - } - } - newBlock.name = blockName; - - const repBlock = { - col: x, - row: y, - height: 3, - width: blockWidth / gridDistance, - }; - - let newChannelColor = set === 'datasets' ? getRandomBrightColor() : null; - - return { - block: newBlock, - rep: repBlock, - channelColor: newChannelColor, - }; -}; - -// finds a block by name from the three block sub-arrays: -// blocks (normal blocks), datasets (dataset blocks), analyzers (analyzer blocks) -const findBlock = (contents: any, name: string): BlockType => { - const b = contents.blocks.find(b => b.name === name) || - contents.datasets.find(b => b.name === name) || - contents.analyzers.find(b => b.name === name) - ; - if(!b) - throw new Error(`invalid block name: ${ name }`); - - return b; -}; - - -export class ToolchainEditor extends React.PureComponent<Props, State> { - constructor(props: Props) { - super(props); - } - - state = { - modalBlockInfo: { - name: undefined, - set: undefined, - active: false, - }, - clipboard: undefined, - insertModalActive: false, - renameGroupModalInfo: undefined, - history: { - past: [], - future: [], - }, - } - - /* HELPERS */ - - // helper to set the contents (this.props.data.contents) object - setContents = (newContents: any) => { - this.setState((prevState, props) => ({ - history: generateNewHistory(prevState, props.data), - })); - - this.props.updateFunc({ - ...this.props.data, - contents: { - ...this.props.data.contents, - ...newContents, - } - }); - } - - // helper to set the groups (this.props.data.extraContents.groups) - setGroups = (groups: Group[]) => { - this.setState((prevState, props) => ({ - history: generateNewHistory(prevState, props.data), - })); - - this.props.updateFunc({ - ...this.props.data, - extraContents: { - ...this.props.data.extraContents, - groups, - } - }); - } - - // finds a block by name from the three block sub-arrays: - // blocks (normal blocks), datasets (dataset blocks), analyzers (analyzer blocks) - findBlock = (name: string): BlockType => findBlock(this.props.data.contents, name); - - // gets possible channels the block can sync to - getPossibleChannels = (blockName: string) => { - const relConns = this.props.data.contents.connections.filter(c => c.to.split('.')[0] === blockName) || []; - const possibleChannels = Array.from(new Set(relConns.map(c => c.channel))) - .reduce((o, channel) => ({...o, [channel]: this.props.data.contents.representation.channel_colors[channel]}), {}); - - return possibleChannels; - } - - /* HISTORY */ - - // undoes history by saving the current state to the future - // and switching to the latest history state - undoHistory = () => { - if(this.state.history.past.length === 0) - return this.state; - - const newPast = [...this.state.history.past]; - const newData = newPast.pop(); - - const newFuture = [...this.state.history.future, copyObj(this.props.data)]; - this.setState({ - history: { - past: newPast, - future: newFuture, - }, - }); - - if(!newData){ - console.error(`No past state found!`); - return; - } - - this.props.updateFunc(newData); - }; - - // redoes history by putting the current state in the past - // and switching to the earliest future state - redoHistory = () => { - if(this.state.history.future.length === 0) - return this.state; - - const newFuture = [...this.state.history.future]; - const newData = newFuture.pop(); - - const newPast = [...this.state.history.past, copyObj(this.props.data)]; - this.setState({ - history: { - past: newPast, - future: newFuture, - }, - }); - - if(!newData){ - console.error(`No future state found!`); - return; - } - - this.props.updateFunc(newData); - }; - - /* MODALS */ - - // toggles whether the object insert modal is active or not - toggleInsertModal = () => { - this.setState((prevState) => ({ insertModalActive: !prevState.insertModalActive })); - } - - // toggles whether the group rename modal is active or not - toggleRenameGroupModal = (val: ?string) => { - this.setState((prevState) => ({ renameGroupModalInfo: val })); - } - - closeEditModal = () => { - this.setState({ - modalBlockInfo: { - ...this.state.modalBlockInfo, - active: false, - } - }); - } - - /* GROUPS */ - - // renames a group from an old name to a new one - renameGroup = (oldName: string, newName: string) => { - this.setGroups(this.props.data.extraContents.groups.map(g => g.name === oldName ? {...g, name: newName} : g)); - } - - /* CONNECTIONS */ - - // creates a connection between a block's output and a block's input with a specific channel - createConnections = (connectionData: ConnectionType[]) => { - const rep = this.props.data.contents.representation; - - // assign empty synchronized_channel vals on blocks that are getting their first connection - const toBlockNamesAndChannels = connectionData.map(c => [c.to.split('.')[0], c.channel]); - const assignBlockChannels = (blocks: BlockType[]) => { - return blocks.map(b => { - if(this.props.data.contents.connections.find(c => c.to.startsWith(`${ b.name }.`)) && b.synchronized_channel !== '') - return b; - const tbnc = toBlockNamesAndChannels.find(([n, c]) => n === b.name); - if(!tbnc) - return b; - return { - ...b, - synchronized_channel: tbnc[1], - }; - }) - ; - }; - - const newBlocks = assignBlockChannels(this.props.data.contents.blocks); - const newAnalyzers = assignBlockChannels(this.props.data.contents.analyzers); - - - const newRepConns = generateConnectionRepresentations(connectionData); - this.setContents({ - blocks: newBlocks, - analyzers: newAnalyzers, - connections: [ - ...this.props.data.contents.connections, - ...connectionData, - ], - representation: { - ...rep, - connections: { - ...rep.connections, - ...newRepConns, - } - } - }); - } - - // deletes a connection - // looks at the representation object and the connections array - deleteConnection = (cn: ConnectionType) => { - const rep = {...this.props.data.contents.representation}; - - rep.connections = Object.entries(rep.connections).filter(([name, rep]) => { - const [from, to] = name.split('/'); - if(from === cn.from && to === cn.to) - return false; - return true; - }) - .reduce((cs, [name, rep]) => ({...cs, [name]: rep}), {}) - ; - - const newConns = this.props.data.contents.connections.filter(c => { - if(c.from === cn.from && c.to === cn.to) - return false; - return true; - }); - - // if the given block has no conns to it, the syncd channel should become '' - const removeInvalidChannels = (b: NormalBlock | AnalyzerBlock): NormalBlock | AnalyzerBlock => { - if(newConns.find(c => c.to.split('.')[0] == b.name)) - return b; - - return { - ...b, - synchronized_channel: '', - }; - }; - - const newContents = { - connections: newConns, - blocks: this.props.data.contents.blocks.map(b => removeInvalidChannels(b)), - analyzers: this.props.data.contents.analyzers.map(b => removeInvalidChannels(b)), - representation: rep, - }; - - this.setContents(newContents); - } - - /* BLOCKS */ - - // adds new blocks at a certain location via an array of arrays of info about the new block(s) - // it will also copy connections via looking for connections between copied blocks and copying them to the related new blocks - // Parameters: - // blockData: each array is info about a new block: - // - the first string is the new name - // - the BlockSet is the set to put the block in - // - the numbers are the x & y coords of the new block - // - last entry is an optional block object to copy from - // connections: - // if you are inserting blocks from different toolchains, give the new connections as the second arg! - // these new connections should already be updated to have the new syncd channel names - addBlocks = (blockData: [string, BlockSet, number, number, ?BlockType][], connections: ConnectionType[]) => { - const newBlocks = blockData.map(d => generateNewBlockData(...d)); - const sets = blockData.map(b => b[1]); - - const rep = { - ...this.props.data.contents.representation, - blocks: { - ...this.props.data.contents.representation.blocks, - ...newBlocks.reduce((newReps, b) => ({...newReps, [b.block.name]: b.rep}), {}), - }, - channel_colors: { - ...this.props.data.contents.representation.channel_colors, - ...newBlocks.filter(b => b.channelColor !== null) - .reduce((newColors, b) => ({...newColors, [b.block.name]: b.channelColor}), {}), - } - }; - - - const newContents = { - blocks: [...this.props.data.contents.blocks, ...newBlocks.filter((b, i) => sets[i] === 'blocks').map(b => b.block)], - datasets: [...this.props.data.contents.datasets, ...newBlocks.filter((b, i) => sets[i] === 'datasets').map(b => b.block)], - analyzers: [...this.props.data.contents.analyzers, ...newBlocks.filter((b, i) => sets[i] === 'analyzers').map(b => b.block)], - representation: rep, - connections: this.props.data.contents.connections, - }; - - // if the blocks werent copied from an external toolchain, - // check for connection info from the copied blocks and create new connections between the new blocks - if(!connections){ - const copyBlocks = blockData.filter(bd => bd.length > 4); - const newConnections: ConnectionType[] = [...this.props.data.contents.connections].map(({ from, to, channel }) => { - const fromBlock = copyBlocks.find(bd => from.startsWith(`${ bd[4].name }.`)); - const toBlock = copyBlocks.find(bd => to.startsWith(`${ bd[4].name }.`)); - if(!fromBlock || !toBlock) - return false; - const newFromBlockData = newBlocks.find(b => b.block.name === fromBlock[0]); - if(!newFromBlockData) - return false; - else { - return { - from: from.replace(`${ fromBlock[4].name }.`, `${ fromBlock[0] }.`), - to: to.replace(`${ toBlock[4].name }.`, `${ toBlock[0] }.`), - channel: newFromBlockData.block.synchronized_channel || newFromBlockData.block.name, - }; - } - }) - .filter(c => c); - newContents.connections = [...this.props.data.contents.connections, ...newConnections]; - const newRepConns = generateConnectionRepresentations(newConnections); - newContents.representation.connections = {...rep.connections, ...newRepConns}; - } else { - // add the new connections from the copied toolchain - const newConnections = connections; - newContents.connections = [...this.props.data.contents.connections, ...newConnections]; - const newRepConns = generateConnectionRepresentations(newConnections); - newContents.representation.connections = {...rep.connections, ...newRepConns}; - } - - this.setContents(newContents); - } - - // updates a blocks location in the graphical editor by providing an x & y offset relative to the current location. - updateBlockLocations = (bLocs: {blockName: string, x: number, y: number}[]) => { - const rep = this.props.data.contents.representation; - const newReps = bLocs - .map(bLoc => ({ [bLoc.blockName]: { ...rep.blocks[bLoc.blockName], col: bLoc.x, row: bLoc.y }})) - .reduce((o, bLoc) => ({ ...o, ...bLoc }), {});; - this.setContents({ - representation: { - ...rep, - blocks: { - ...rep.blocks, - ...newReps, - } - } - }); - } - - // deletes a block from the toolchain, - // as well as any connections to/from it - // if it was the sole member of a group, deletes the group too - deleteBlocks = (names: string[]) => { - const rep = copyObj(this.props.data.contents.representation); - - names.forEach(name => { - delete rep.blocks[name]; - delete rep.channel_colors[name]; - }); - - rep.connections = Object.entries(rep.connections).filter(([name, rep]) => { - const [from, to] = name.split('/'); - if(names.find(blockName => to.startsWith(`${ blockName }.`) || from.startsWith(`${ blockName }.`))) - return false; - return true; - }) - .reduce((cs, [name, r]) => ({...cs, [name]: r}), {}) - ; - - const newContents = { - ...this.props.data.contents, - blocks: this.props.data.contents.blocks.filter(s => !names.includes(s.name)), - datasets: this.props.data.contents.datasets.filter(s => !names.includes(s.name)), - analyzers: this.props.data.contents.analyzers.filter(s => !names.includes(s.name)), - connections: this.props.data.contents.connections.filter(c => { - if(names.find(blockName => c.to.startsWith(`${ blockName }.`) || c.from.startsWith(`${ blockName }.`))) - return false; - return true; - }), - representation: rep, - }; - - const newGroups = this.props.data.extraContents.groups - .map(({ name, blocks }) => ({ name, blocks: blocks.filter(n => !names.includes(n)) })) - .filter(g => g.blocks.length !== 0); - - this.setState({ - history: generateNewHistory(this.state, this.props.data), - }); - - this.props.updateFunc({ - ...this.props.data, - contents: newContents, - extraContents: { - ...this.props.data.extraContents, - groups: newGroups, - }, - }); - } - - /* BLOCK EDIT MODAL */ - - // updates the block data for a given block - // by sequentially applying all updates made from the ToolchainModal editor - // to the data of the toolchain. - updateBlockData = (data: ModalCache) => { - const set = this.state.modalBlockInfo.set; - const name = this.state.modalBlockInfo.name; - if(!set || !name){ - console.error(`Modal not open for update for ${ data.name }`); - return; - } - - const oldData = this.props.data; - const oldBlock = oldData.contents[set].find(b => b.name === name); - if(!oldBlock){ - console.error(`cannot find block ${ name }`); - return; - } - - let newData = copyObj(oldData); - - // update name - if(name !== data.name) { - newData = this.updateBlockNameFunc(newData, set, name, data.name); - } - - // update channel - if(data.synchronized_channel && oldBlock.synchronized_channel !== data.synchronized_channel){ - newData = this.updateBlockChannelFunc(newData, data.name, set, data.synchronized_channel); - } - - const findNewBlock = () => newData.contents[set].find(b => b.name === data.name); - let newBlock = findNewBlock(); - - // update inputs - if(Array.isArray(data.inputs)){ - // first change names - // when the modal opens, - // a new "change" operation is added to the cache - // for each input/output already in the block, with a name === original - // to avoid extra processing, skip these if they exist - const [oldNames, newNames] = data.inputs.filter(o => o.action === 'change' && o.original !== o.name) - .reduce(([oldNames, newNames], o) => [[...oldNames, o.original], [...newNames, o.name]], [[], []]); - - newData = this.updateBlockIONamesFunc(newData, newBlock.name, set, 'input', oldNames, newNames); - newBlock = findNewBlock(); - - data.inputs.filter(o => o.action !== 'change') - .forEach(o => { - switch(o.action){ - case 'delete': - newData = this.deleteBlockIOFunc(newData, newBlock.name, set, 'input', o.original); - break; - case 'add': - newData = this.addBlockIOFunc(newData, newBlock.name, set, 'input', o.name); - break; - default: - break; - } - newBlock = findNewBlock(); - }); - } - - // update outputs - if(Array.isArray(data.outputs)){ - const [oldNames, newNames] = data.outputs.filter(o => o.action === 'change' && o.original !== o.name) - .reduce(([oldNames, newNames], o) => [[...oldNames, o.original], [...newNames, o.name]], [[], []]); - - newData = this.updateBlockIONamesFunc(newData, newBlock.name, set, 'output', oldNames, newNames); - newBlock = findNewBlock(); - - data.outputs.filter(o => o.action !== 'change') - .forEach(o => { - switch(o.action){ - case 'delete': - newData = this.deleteBlockIOFunc(newData, newBlock.name, set, 'output', o.original); - break; - case 'add': - newData = this.addBlockIOFunc(newData, newBlock.name, set, 'output', o.name); - break; - default: - break; - } - newBlock = findNewBlock(); - }); - } - - this.setState((prevState, props) => ({ - history: generateNewHistory(prevState, props.data), - })); - - this.props.updateFunc(newData); - } - - // changes a block's name given the set it belongs to, the old name, and the new name - updateBlockNameFunc = (oldData: any, set: BlockSet, oldName: string, newName: string): any => { - // func to update from/to strings with old names to new names - const updateConn = (from, to): string[] => { - const fromSplit = from.split('.'); - fromSplit[0] = fromSplit[0] === oldName ? newName : fromSplit[0]; - const toSplit = to.split('.'); - toSplit[0] = toSplit[0] === oldName ? newName : toSplit[0]; - return [fromSplit.join('.'), toSplit.join('.')]; - }; - - // update the block & conn representation with the new names - const rep = {...oldData.contents.representation}; - rep.blocks = {...rep.blocks}; - rep.blocks[newName] = rep.blocks[oldName]; - delete rep.blocks[oldName]; - rep.connections = Object.entries(rep.connections).map(([name, rep]) => { - if(!name.includes(oldName)) - return [name, rep]; - - const [from, to] = name.split('/'); - const updated = updateConn(from, to); - - return [updated.join('/'), rep]; - }) - .reduce((cs, c) => ({...cs, [c[0]]: c[1]}), {}) - ; - // update the channel colors - if(set === 'datasets'){ - rep.channel_colors[newName] = rep.channel_colors[oldName]; - delete rep.channel_colors[oldName]; - } - - // update blocks & connections - const newContents = { - ...oldData.contents, - [set]: oldData.contents[set].map(s => s.name === oldName ? {...s, name: newName} : s), - // update the conns, both the names of the blocks and the channel - connections: oldData.contents.connections.map(c => { - if(!c.from.includes(oldName) && !c.to.includes(oldName) && c.channel !== oldName) - return c; - - const newChannel = c.channel === oldName ? newName : c.channel; - - const updated = updateConn(c.from, c.to); - return { - channel: newChannel, - from: updated[0], - to: updated[1], - }; - }), - representation: rep, - }; - - // if the changed block is a dataset, update the synchronized_channel on all blocks using its old name - if(set === 'datasets'){ - newContents['blocks'] = oldData.contents.blocks - .map(s => s.synchronized_channel === oldName ? {...s, synchronized_channel: newName} : s) - ; - - newContents['analyzers'] = oldData.contents.analyzers - .map(s => s.synchronized_channel === oldName ? {...s, synchronized_channel: newName} : s) - ; - } - - const newGroups = oldData.extraContents.groups - .map(({ name, blocks }) => ({ name, blocks: blocks.map(n => n === oldName ? newName : n) })); - this.setState((prevState, props) => ({ - history: generateNewHistory(prevState, props.data), - modalBlockInfo: { - active: true, - name: newName, - set - } - })); - - return { - ...oldData, - contents: newContents, - extraContents: { - ...oldData.extraContents, - groups: newGroups, - }, - }; - } - - // update multiple block names at once - updateBlockIONamesFunc = (oldData: any, blockName: string, set: BlockSet, ioType: 'input' | 'output', oldNames: string[], newNames: string[]) => { - const combinedNames = oldNames.map(oldName => `${ blockName }.${ oldName }`); - // gets the new name for the i/o from the old name OR from the old combined name (in the form `${blockName}.${oldName}`) - const getNewFromOld = (oldName: string): ?string => { - const foundCombined = combinedNames.findIndex(cn => cn === oldName); - const found = oldNames.findIndex(o => o === oldName); - if(foundCombined > -1){ - return newNames[foundCombined]; - } else if(found > -1){ - return newNames[found]; - } else { - return undefined; - } - }; - - // updates a connection to use the new names - const updateConn = (from, to): string[] => { - const fromSplit = from.split('.'); - const toSplit = to.split('.'); - - if(ioType === 'output') - fromSplit[1] = getNewFromOld(from) || fromSplit[1]; - else if(ioType === 'input') - toSplit[1] = getNewFromOld(to) || toSplit[1]; - - return [fromSplit.join('.'), toSplit.join('.')]; - }; - - const rep = {...oldData.contents.representation}; - // fix all the names in `contents.representation.connections` - const newRepConns = Object.entries(rep.connections).map(([name, crep]) => { - if(!oldNames.some(oldName => name.includes(`.${ oldName }`))) - return [name, crep]; - - const [from, to] = name.split('/'); - const updated = updateConn(from, to); - - return [updated.join('/'), crep]; - }) - .reduce((cs, [name, crep]) => ({...cs, [name]: crep}), {}) - ; - - // fix all the connection objects in `contents.connections` - const newConns = oldData.contents.connections.map(c => { - const updated = updateConn(c.from, c.to); - return { - ...c, - from: updated[0], - to: updated[1], - }; - }); - - const newContents = { - ...oldData.contents, - [set]: oldData.contents[set].map(s => { - if(s.name !== blockName) - return s; - const newBlock = { - ...s, - }; - if(ioType === 'input') - newBlock.inputs = newBlock.inputs.map(str => getNewFromOld(str) || str); - if(ioType === 'output') - newBlock.outputs = newBlock.outputs.map(str => getNewFromOld(str) || str); - return newBlock; - }), - connections: newConns, - representation: { - ...rep, - connections: newRepConns, - }, - }; - - return { - ...oldData, - contents: newContents, - }; - } - - // add a new input or output to a block - addBlockIOFunc = (oldData: any, blockName: string, set: BlockSet, ioType: 'input' | 'output', newName: string) => { - const newContents = { - ...oldData.contents, - [set]: oldData.contents[set].map(s => { - if(s.name !== blockName) - return s; - const newBlock = { - ...s, - }; - if(ioType === 'input') - newBlock.inputs = [...newBlock.inputs, newName]; - if(ioType === 'output') - newBlock.outputs = [...newBlock.outputs, newName]; - return newBlock; - }), - }; - - return { - ...oldData, - contents: newContents, - }; - } - - // deletes an input or output from a block, - // as well as any connections connected to it - deleteBlockIOFunc = (oldData: any, blockName: string, set: BlockSet, ioType: 'input' | 'output', ioName: string) => { - const rep = {...oldData.contents.representation}; - - const connectionLabel = `${ blockName }.${ ioName }`; - - rep.connections = Object.entries(rep.connections).filter(([name, rep]) => { - if(!name.includes(ioName)) - return true; - - const [from, to] = name.split('/'); - if(ioType === 'input' && to === connectionLabel) - return false; - if(ioType === 'output' && from === connectionLabel) - return false; - return true; - }) - .reduce((cs, [name, rep]) => ({...cs, [name]: rep}), {}) - ; - const newContents = { - ...oldData.contents, - [set]: oldData.contents[set].map(s => { - if(s.name !== blockName) - return s; - const newBlock = { - ...s, - }; - if(ioType === 'input') - newBlock.inputs = newBlock.inputs.filter(str => str !== ioName); - if(ioType === 'output') - newBlock.outputs = newBlock.outputs.filter(str => str !== ioName); - return newBlock; - }), - connections: oldData.contents.connections.filter(c => { - if(ioType === 'input' && c.to === connectionLabel) - return false; - if(ioType === 'output' && c.from === connectionLabel) - return false; - return true; - }), - }; - - return { - ...oldData, - contents: newContents, - }; - } - - // changes the block's sync'd channel - // also updates all connections from the block - updateBlockChannelFunc = (oldData: any, blockName: string, set: BlockSet, channel: string) => { - const queue = [oldData.contents[set].find(b => b.name === blockName)]; - const oldChannel = `${ queue[0].synchronized_channel }`; - const bNames = Object.keys(oldData.contents.representation.blocks); - const conns = oldData.contents.connections; - const updatedBlocks: { [string]: BlockType } = {}; - const updatedConnections: { [string]: ConnectionType } = {}; - while(queue.length > 0){ - const b = queue.shift(); - if(b.synchronized_channel === oldChannel){ - updatedBlocks[b.name] = { - ...b, - synchronized_channel: channel, - }; - - conns - .filter(c => c.from.startsWith(`${ b.name }.`)) - .forEach(c => { - const curr = c.to.split('.')[0]; - // if theres more than one connection to this block - // that is synced to the old channel, - // dont change the channel of this block - // because the old channel is still valid - if( - conns - .filter(c => c.to.startsWith(`${ curr }.`) && c.channel === oldChannel) - .length === 1 - ) - queue.push(findBlock(oldData.contents, curr)); - - updatedConnections[connectionToId(c)] = { - ...c, - channel, - }; - }); - } - } - - const newContents = { - ...oldData.contents, - datasets: oldData.contents.datasets.map(b => updatedBlocks[b.name] || b), - blocks: oldData.contents.blocks.map(b => updatedBlocks[b.name] || b), - analyzers: oldData.contents.analyzers.map(b => updatedBlocks[b.name] || b), - connections: oldData.contents.connections.map(c => updatedConnections[connectionToId(c)] || c), - }; - - return { - ...oldData, - contents: newContents, - }; - } - - createAlgorithmFromBlock = async (algName: string) => { - const {active, name, set} = this.state.modalBlockInfo; - const data = this.props.data.contents[set].find(b => b.name === name); - - if(!data){ - console.error(`cannot find ${ name } to create ${ algName } in blocks or analyzers`); - return; - } - - const conns = this.props.data.contents.connections - .filter(c => c.to.startsWith(`${ name }.`)) - ; - - await this.props.createAlgorithmFromBlock({ ...data, name: algName }, conns); - } - - /* CONTEXT MENUS */ - - svgContextMenuLocation: ?[number, number] = undefined - - // handles the left click on the svg's background - // shows a menu to add/paste blocks at the click location - handleSvgContextMenu = (e: any, data: { x: number, y: number, selectBlocks: (string[]) => any, clicked: string }) => { - const {blocks, datasets, analyzers, representation} = this.props.data.contents; - const { x, y, selectBlocks, clicked } = data; - let newBlockName = ''; - const usedNames = this.getUsedNames(); - switch(clicked){ - case 'addBlock': - newBlockName = generateNewKey('block', usedNames); - this.addBlocks([[newBlockName, 'blocks', x, y]]); - break; - case 'addDataset': - newBlockName = generateNewKey('dataset', usedNames); - this.addBlocks([[newBlockName, 'datasets', x, y]]); - break; - case 'addAnalyzer': - newBlockName = generateNewKey('analyzer', usedNames); - this.addBlocks([[newBlockName, 'analyzers', x, y]]); - break; - case 'addObject': - this.svgContextMenuLocation = [x, y]; - this.toggleInsertModal(); - break; - case 'paste': - if(!this.state.clipboard || this.state.clipboard.length === 0) - return; - const blocksToCopy = this.state.clipboard; - - const sets = blocksToCopy.map(b => { - if(!b.hasOwnProperty('inputs')) - return 'datasets'; - if(!b.hasOwnProperty('outputs')) - return 'analyzers'; - return 'blocks'; - }); - //first element in the blocksToCopy array is the one used to offset the other blocks - const b0 = blocksToCopy[0]; - const b0Rep = representation.blocks[b0.name]; - const offsetX = x - b0Rep.col; - const offsetY = y - b0Rep.row; - const newBlockData = blocksToCopy.map((b, i, bs) => { - const bRep = representation.blocks[b.name]; - const set = sets[i]; - const newX = bRep.col + offsetX; - const newY = bRep.row + offsetY; - const newName = generateNewKey(b.name, usedNames); - return [newName, set, newX, newY, {...b}]; - }); - this.addBlocks(newBlockData); - selectBlocks(newBlockData.map(d => d[0])); - break; - default: - break; - } - } - - // copy either a block or array of blocks to the clipboard - copyToClipboard = (data: any[]) => { - this.setState({ - clipboard: data, - }); - } - - // handles a right click on a block - handleBlockContextMenu = (e: any, data: { name: string, clicked: string }) => { - const {name, clicked} = data; - switch(clicked){ - case 'delete': - this.deleteBlocks([name]); - break; - case 'copy': - this.copyToClipboard([this.findBlock(name)]); - break; - default: - break; - } - } - - // handles a right click on a connection - handleConnectionContextMenu = (e: any, data: { connection: ConnectionType, clicked: string }) => { - const {connection, clicked} = data; - switch(clicked){ - case 'delete': - this.deleteConnection(connection); - break; - default: - break; - } - } - - // handles a right click on a group - handleGroupContextMenu = (e: any, data: { group: string, selectBlocks: (BlockType[]) => any, clicked: string }) => { - const {group, clicked, selectBlocks} = data; - const groups = this.props.data.extraContents.groups; - const g = groups.find(g => g.name === group); - switch(clicked){ - case 'delete': - this.setGroups(groups.filter(g => g.name !== group)); - break; - case 'copy': - this.copyToClipboard(g.blocks.map(b => this.findBlock(b)).filter(b => b)); - break; - case 'select': - selectBlocks(g.blocks.map(b => this.findBlock(b)).filter(b => b)); - break; - case 'collapse': - this.setGroups(groups.map(g => g.name === group ? { ...g, collapsed: !g.collapsed } : g)); - break; - case 'rename': - this.toggleRenameGroupModal(group); - break; - default: - break; - } - } - - // gets all the used names in the toolchain: - // group names & block names - getUsedNames = (): string[] => [ - ...this.props.data.extraContents.groups.map(g => g.name), - ...Object.keys(this.props.data.contents.representation.blocks) - ]; - - // handles a right click on an area selection - handleAreaSelectContextMenu = (e: any, data: { selection: BlockType[], clicked: string }) => { - const {selection, clicked} = data; - const groups = this.props.data.extraContents.groups; - switch(clicked){ - case 'createGroup': - const newGroupName = generateNewKey('group', this.getUsedNames()); - this.setGroups([ - ...groups, - { - name: newGroupName, - blocks: selection.map(b => b.name), - collapsed: false, - } - ]); - break; - case 'copy': - this.copyToClipboard(selection); - break; - case 'delete': - this.deleteBlocks(selection.map(b => b.name)); - break; - default: - break; - } - } - - lastClickBlockName = '' - lastClickMs = 0 - // handles left clicking on a block - handleBlockClick = (blockName: string, set: BlockSet) => { - const currTime = Date.now(); - // 1sec throttling - const delay = 1000; - if(currTime - this.lastClickMs > delay || blockName !== this.lastClickBlockName){ - this.lastClickBlockName = blockName; - const newMBI = { - set, - name: blockName, - active: true, - }; - this.setState({ - modalBlockInfo: newMBI, - }); - } - this.lastClickBlockName = blockName; - this.lastClickMs = currTime; - } - - // uses the server's /layout endpoint to get a graphviz layout for this toolchain - autoLayout = async () => { - // first save the tc to the BEAT prefix - const serverSaveFunc = genModuleApiFuncs('toolchain').put; - await serverSaveFunc(this.props.data); - // then fetch the new layout - const json = await fetchLayout(this.props.data.name); - - // transform the received layout into objs for updateBlockLocations - const posRaw = json.objects - .filter(o => o.hasOwnProperty('pos')) - .map(o => { - const [x, y] = o.pos.split(',').map(n => Number.parseFloat(n)); - return { - blockName: o.name, - x, - y, - }; - }) - ; - - // flip the blocks' y-coord across the middle of the layout - // because graphviz's y-axis starts at the bottom while svg - // starts at the top - const midY = Math.max(...posRaw.map(o => o.y)) / 2; - const pos = posRaw.map(({blockName, x, y}) => { - const ry = y - (2 * (y - midY)); - return { - blockName, - // round to the nearest grid lines - x: Math.round(x / gridDistance), - y: Math.round(ry / gridDistance), - }; - }); - - // update locations - this.updateBlockLocations(pos); - // dont save locally because it kills the undo/redo stack! - } - - renderGraphicalEditor = () => { - return ( - <Container> - <Row> - </Row> - <Row> - <GraphicalEditor - interactable - repData={this.props.data.contents.representation} - blocks={this.props.data.contents.blocks} - datasets={this.props.data.contents.datasets} - analyzers={this.props.data.contents.analyzers} - connections={this.props.data.contents.connections} - groups={this.props.data.extraContents.groups} - handleBlockClick={this.handleBlockClick} - updateBlockLocations={this.updateBlockLocations} - createConnection={(from: string, to: string, channel: string) => this.createConnections([{ from, to, channel }])} - toolbarContent={ - <React.Fragment> - <Button - size='sm' - onClick={this.undoHistory} - disabled={this.state.history.past.length === 0} - > - Undo - </Button> - <Button - size='sm' - onClick={this.redoHistory} - disabled={this.state.history.future.length === 0} - > - Redo - </Button> - <Button - size='sm' - onClick={this.autoLayout} - title={'This will use Graphviz to generate a more visually understandable layout for your toolchain.'} - disabled={!!Validate(VALIDATORS['toolchain'], this.props.data)} - > - Layout - </Button> - </React.Fragment> - } - divChildren={ - <React.Fragment> - <ContextMenu - id='blockContextMenu' - hideOnLeave={true} - > - <MenuItem - data={{ clicked: 'delete'}} - onClick={this.handleBlockContextMenu} - > - Delete Block - </MenuItem> - <MenuItem - data={{ clicked: 'copy'}} - onClick={this.handleBlockContextMenu} - > - Copy Block - </MenuItem> - </ContextMenu> - <ContextMenu - id='connectionContextMenu' - hideOnLeave={true} - > - <MenuItem - data={{ clicked: 'delete'}} - onClick={this.handleConnectionContextMenu} - > - Delete Connection - </MenuItem> - </ContextMenu> - <ContextMenu - id='svgContextMenu' - hideOnLeave={true} - > - { - this.state.clipboard !== undefined && - <MenuItem - data={{ clicked: 'paste'}} - onClick={this.handleSvgContextMenu} - > - Paste Here - </MenuItem> - } - <MenuItem - data={{ clicked: 'addBlock'}} - onClick={this.handleSvgContextMenu} - > - Add Block Here - </MenuItem> - <MenuItem - data={{ clicked: 'addDataset'}} - onClick={this.handleSvgContextMenu} - > - Add Dataset Here - </MenuItem> - <MenuItem - data={{ clicked: 'addAnalyzer'}} - onClick={this.handleSvgContextMenu} - > - Add Analyzer Here - </MenuItem> - <MenuItem - data={{ clicked: 'addObject'}} - onClick={this.handleSvgContextMenu} - > - Insert Object Here - </MenuItem> - </ContextMenu> - <ContextMenu - id='groupContextMenu' - hideOnLeave={true} - > - <MenuItem - data={{ clicked: 'copy'}} - onClick={this.handleGroupContextMenu} - > - Copy Group Blocks - </MenuItem> - <MenuItem - data={{ clicked: 'select'}} - onClick={this.handleGroupContextMenu} - > - Select Group Blocks - </MenuItem> - <MenuItem - data={{ clicked: 'collapse'}} - onClick={this.handleGroupContextMenu} - > - Toggle Collapsed - </MenuItem> - <MenuItem - data={{ clicked: 'rename'}} - onClick={this.handleGroupContextMenu} - > - Rename - </MenuItem> - <MenuItem - data={{ clicked: 'delete'}} - onClick={this.handleGroupContextMenu} - > - Delete Group - </MenuItem> - </ContextMenu> - <ContextMenu - id='areaSelectContextMenu' - hideOnLeave={true} - > - <MenuItem - data={{ clicked: 'copy'}} - onClick={this.handleAreaSelectContextMenu} - > - Copy Blocks - </MenuItem> - <MenuItem - data={{ clicked: 'createGroup'}} - onClick={this.handleAreaSelectContextMenu} - > - Create Group - </MenuItem> - <MenuItem - data={{ clicked: 'delete'}} - onClick={this.handleAreaSelectContextMenu} - > - Delete Blocks - </MenuItem> - </ContextMenu> - </React.Fragment> - } - > - </GraphicalEditor> - </Row> - </Container> - ); - } - - // modal that pops up when left clicking a block - renderEditModal = () => { - const {active, name, set} = this.state.modalBlockInfo; - if(!name || !set) - return null; - const possibleChannels = active ? this.getPossibleChannels(name) : {}; - return ( - <EditModal - data={this.props.data.contents[set].find(d => d.name === name)} - active={active} - toggle={() => this.closeEditModal()} - blockNames={Object.keys(this.props.data.contents.representation.blocks) || []} - deleteBlock={() => this.deleteBlocks([name])} - possibleChannels={possibleChannels} - updateBlockData={this.updateBlockData} - createAlgorithmFromBlock={this.createAlgorithmFromBlock} - /> - ); - } - - renderInsertModal = () => { - return ( - <InsertObjectModal - toolchains={this.props.toolchains} - protocols={this.props.protocols} - sets={this.props.sets} - normalAlgorithms={this.props.normalAlgorithms} - analyzerAlgorithms={this.props.analyzerAlgorithms} - active={this.state.insertModalActive} - toggle={this.toggleInsertModal} - addNewBlocks={(type, newBlocksData, newConnections) => { - if(!this.svgContextMenuLocation) - return; - const [x, y] = this.svgContextMenuLocation; - for(const b of newBlocksData){ - b[2] += x; - b[3] += y; - } - - this.addBlocks(newBlocksData, newConnections); - }} - usedNames={this.getUsedNames()} - /> - ); - } - - renderRenameGroupModal = () => { - return ( - <RenameGroupModal - active={this.state.renameGroupModalInfo !== undefined} - toggle={this.toggleRenameGroupModal} - usedNames={this.getUsedNames()} - currentName={this.state.renameGroupModalInfo || ''} - saveNewName={(name) => { - const oldName = this.state.renameGroupModalInfo; - if(!oldName) - return; - this.renameGroup(oldName, name); - }} - /> - ); - } - - render = () => ( - <div className='toolchainEditor'> - <div className='d-flex'> - <Button - className='mx-auto' - outline - color='secondary' - onClick={() => this.props.saveFunc(this.props.data)} - > - Save Changes (Changes are <ValidSchemaBadge entity='toolchain' obj={this.props.data} />) - </Button> - </div> - <Form onSubmit={(e) => e.preventDefault()}> - <FormGroup tag='fieldset'> - <FormGroup> - <Label>Short Description</Label> - <Input - type='text' - className='tcDescription' - placeholder='Toolchain description...' - value={this.props.data.contents['description']} - onChange={e => this.setContents({ ...this.props.data.contents, 'description': e.target.value})} - /> - </FormGroup> - </FormGroup> - { this.renderGraphicalEditor() } - { this.renderEditModal() } - { this.renderInsertModal() } - { this.renderRenameGroupModal() } - </Form> - </div> - ); -} - -const mapStateToProps = (state, ownProps) => { - const tcs = Selectors.toolchainGet(state); - const obj = { - toolchains: tcs, - databases: Selectors.databaseGet(state), - sets: Selectors.flattenedDatabases(state), - protocols: Selectors.databaseProtocols(state), - normalAlgorithms: Selectors.normalBlocks(state), - analyzerAlgorithms: Selectors.analyzerBlocks(state), - data: tcs[ownProps.index] || getValidObj() - }; - return obj; -}; - -const mapDispatchToProps = (dispatch, ownProps) => ({ - // replace the obj in the Redux store with the new object - updateFunc: (obj) => { - console.log(`dispatching for ${ obj.name }`); - dispatch(Actions[`toolchainUpdate`](obj.name, obj)); - }, - createAlgorithmFromBlock: async (data: NormalBlock | AnalyzerBlock, conns: ConnectionType[]) => { - let newObj = getValidAlgorithmObj({ name: data.name, contents: {} }); - - // generate the alg obj - // first, separate into groups - // look at all connections to block, each different channel is a different group - // put the inputs in the corresponding groups as well - const inputGroups = conns.reduce((groups, c) => { - const input = c.to.split('.')[1]; - const channel: string = c.channel; - if(Array.isArray(groups[channel])){ - groups[channel].push(input); - } else { - groups[channel] = [input]; - } - return groups; - }, {}); - - // coverts a list of input names to the format needed for algorithm groups - const groupListToObj = (iList: string[]): {[string]: any} => - iList.reduce((o, i) => ({...o, [i]: { type: '' }}), {}); - - // generate group objs from the inputs split between groups - newObj.contents.groups = Object.entries(inputGroups) - .map(([gName, inputs], i) => ({ name: gName, inputs: groupListToObj(inputs) }) ); - - // is normal block - if(Array.isArray(data.outputs)){ - // all block outputs only go to first group - if(Array.isArray(data.outputs) && newObj.contents.groups.length > 0){ - newObj.contents.groups[0].outputs = groupListToObj(data.outputs); - } - } - // is analyzer block - else { - // make it an analyzer - delete newObj.contents['splittable']; - newObj.contents.results = {}; - } - - console.log(newObj); - - await dispatch(Actions.createObject('algorithm', newObj)()); - } -}); - -export default connect(mapStateToProps, mapDispatchToProps)(ToolchainEditor); diff --git a/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx b/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx deleted file mode 100644 index 0fc44c5e..00000000 --- a/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx +++ /dev/null @@ -1,1103 +0,0 @@ -// @flow -import React from 'react'; -import chai, { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; -// sometimes we dont care about order of items in arrays when comparing objects deeply -import deepEqualInAnyOrder from 'deep-equal-in-any-order'; - -import { getValidToolchainObj as getValidObj, getValidDatabaseObj, getValidAlgorithmObj } from '@helpers/beat'; -import { ToolchainEditor as C } from '.'; -import * as Selectors from '@store/selectors'; -import reducer from '@store/reducers'; - -import testTcs from '@test/test_tcs.json'; -import testDbs from '@test/test_dbs.json'; -import testAlgs from '@test/test_algs.json'; - -const getIrisTc = (color1: string = '#008000', color2: string = '#FF0000') => { - return { - 'name': 'test/iris/1', - 'contents': { - 'description': '', - 'datasets': [ - { - 'name': 'training_data', - 'outputs': [ - 'measurements', - 'species' - ] - }, - { - 'name': 'testing_data', - 'outputs': [ - 'measurements', - 'species' - ] - } - ], - 'blocks': [ - { - 'inputs': [ - 'measurements', - 'species' - ], - 'name': 'training_alg', - 'outputs': [ - 'lda_machine' - ], - 'synchronized_channel': 'training_data' - }, - { - 'inputs': [ - 'lda_machine', - 'measurements' - ], - 'name': 'testing_alg', - 'outputs': [ - 'scores' - ], - 'synchronized_channel': 'testing_data' - } - ], - 'analyzers': [ - { - 'inputs': [ - 'scores', - 'species' - ], - 'name': 'analyzer', - 'synchronized_channel': 'testing_data' - } - ], - 'connections': [ - { - 'channel': 'testing_data', - 'from': 'testing_alg.scores', - 'to': 'analyzer.scores' - }, - { - 'channel': 'training_data', - 'from': 'training_alg.lda_machine', - 'to': 'testing_alg.lda_machine' - }, - { - 'channel': 'testing_data', - 'from': 'testing_data.measurements', - 'to': 'testing_alg.measurements' - }, - { - 'channel': 'training_data', - 'from': 'training_data.measurements', - 'to': 'training_alg.measurements' - }, - { - 'channel': 'training_data', - 'from': 'training_data.species', - 'to': 'training_alg.species' - }, - { - 'channel': 'testing_data', - 'from': 'testing_data.species', - 'to': 'analyzer.species' - } - ], - 'representation': { - 'blocks': { - 'analyzer': { - 'col': 46, - 'height': 3, - 'row': 4, - 'width': 10 - }, - 'testing_alg': { - 'col': 32, - 'height': 3, - 'row': 3, - 'width': 10 - }, - 'testing_data': { - 'col': 6, - 'height': 3, - 'row': 5, - 'width': 10 - }, - 'training_alg': { - 'col': 19, - 'height': 3, - 'row': 0, - 'width': 10 - }, - 'training_data': { - 'col': 6, - 'height': 3, - 'row': 0, - 'width': 10 - } - }, - 'channel_colors': { - 'testing_data': color2, - 'training_data': color1 - }, - 'connections': { - 'testing_alg.scores/analyzer.scores': [], - 'testing_data.measurements/testing_alg.measurements': [], - 'testing_data.species/analyzer.species': [], - 'training_alg.lda_machine/testing_alg.lda_machine': [], - 'training_data.measurements/training_alg.measurements': [], - 'training_data.species/training_alg.species': [] - } - } - }, - 'extraContents': { - 'groups': [] - } - }; -}; - -chai.use(deepEqualInAnyOrder); - -describe('<ToolchainEditor />', function() { - // these tests might take a long time, comparatively - this.timeout(10000); - - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - describe('accepts', () => { - const tcs = testTcs.map(tc => getValidObj(tc)); - const dbs = testDbs.map(db => getValidDatabaseObj(db)); - const algs = testAlgs.map(alg => getValidAlgorithmObj(alg)); - - const state = { - ...reducer({}, { type: '', payload: {}}), - toolchain: tcs, - database: dbs, - algorithm: algs, - }; - - const sets = Selectors.flattenedDatabases(state); - const protocols = Selectors.databaseProtocols(state); - const normalAlgorithms = Selectors.normalBlocks(state); - const analyzerAlgorithms = Selectors.analyzerBlocks(state); - - tcs.forEach(function(tc){ - const saveFunc = () => {}; - const updateFunc = () => {}; - it(`${ tc.name }`, () => { - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'sets', 'protocols', 'toolchains', 'databases', 'normalAlgorithms', 'analyzerAlgorithms', 'saveFunc', 'updateFunc'] - ).deep.equal( - [tc, sets, protocols, tcs, state.database, normalAlgorithms, analyzerAlgorithms, saveFunc, updateFunc] - ); - }); - }); - }); - - describe('creates', () => { - const tcs = []; - const dbs = testDbs.map(db => getValidDatabaseObj(db)); - const algs = testAlgs.map(alg => getValidAlgorithmObj(alg)); - - const state = { - ...reducer({}, { type: '', payload: {}}), - toolchain: tcs, - database: dbs, - algorithm: algs, - }; - - const sets = Selectors.flattenedDatabases(state); - const normalAlgorithms = Selectors.normalBlocks(state); - const protocols = Selectors.databaseProtocols(state); - const analyzerAlgorithms = Selectors.analyzerBlocks(state); - - it(`test/iris/1`, () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const tcName = 'test/iris/1'; - const tc = getValidObj({name: tcName, contents: {}}); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'sets', 'protocols', 'toolchains', 'databases', 'normalAlgorithms', 'analyzerAlgorithms', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', tcName); - - // add lots of blocks - const _selectBlocks = (bNames: string[]) => { return; }; - const selectBlocks = sinon.spy(_selectBlocks); - - - /* add blocks via contextmenu handler */ - - // pretend to right click at a spot by calling the event handler - // dataset 1 training_data @ 6,0 - wrapper.instance().handleSvgContextMenu({}, { clicked: 'addDataset', x: 6, y: 0, selectBlocks }); - wrapper.update(); - expect(updateFunc.callCount).to.equal(1); - expect(wrapper.props().data.contents.datasets.length).to.equal(1); - - // dataset 2 @ 6,5 - wrapper.instance().handleSvgContextMenu({}, { clicked: 'addDataset', x: 6, y: 5, selectBlocks }); - wrapper.update(); - expect(updateFunc.callCount).to.equal(2); - expect(wrapper.props().data.contents.datasets.length).to.equal(2); - - // block 1 (training) @ 19,0 - wrapper.instance().handleSvgContextMenu({}, { clicked: 'addBlock', x: 19, y: 0, selectBlocks }); - wrapper.update(); - expect(updateFunc.callCount).to.equal(3); - expect(wrapper.props().data.contents.blocks.length).to.equal(1); - - // block 2 (testing) @ 32,3 - wrapper.instance().handleSvgContextMenu({}, { clicked: 'addBlock', x: 32, y: 3, selectBlocks }); - wrapper.update(); - expect(updateFunc.callCount).to.equal(4); - expect(wrapper.props().data.contents.blocks.length).to.equal(2); - - // block 3 (analyzer) @ 46,4 - wrapper.instance().handleSvgContextMenu({}, { clicked: 'addAnalyzer', x: 46, y: 4, selectBlocks }); - wrapper.update(); - expect(updateFunc.callCount).to.equal(5); - expect(wrapper.props().data.contents.analyzers.length).to.equal(1); - - /* open edit modal for each & edit blocks via input onChange stuff */ - - // training_data - wrapper.find('rect#block_dataset').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - expect(wrapper.find('.modal').find('CacheInput#tcModalInitFocus').props().value).to.equal('dataset'); - wrapper.find('.modal').find('CacheInput#tcModalInitFocus').prop('onChange')( { target: { value: 'training_data' }}); - wrapper.update(); - /* - wrapper.find('.modal button.btn-secondary').simulate('click'); - wrapper.update(); - */ - wrapper.find('.modal button.btn-secondary').simulate('click'); - wrapper.update(); - wrapper.find('.modal CacheInput[value="output"]').prop('onChange')( { target: { value: 'measurements' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="output0"]').prop('onChange')( { target: { value: 'species' }}); - wrapper.update(); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(false); - - expect(wrapper.props().data.contents.datasets[0]).to.deep.equal({ - 'name': 'training_data', - 'outputs': [ - 'measurements', - 'species' - ] - }); - - // testing_data - wrapper.find('rect#block_dataset0').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - wrapper.update(); - expect(wrapper.find('.modal').find('CacheInput#tcModalInitFocus').props().value).to.equal('dataset0'); - wrapper.find('.modal').find('CacheInput#tcModalInitFocus').prop('onChange')( { target: { value: 'testing_data' }}); - wrapper.update(); - /* - wrapper.find('.modal button.btn-secondary').simulate('click'); - wrapper.update(); - */ - wrapper.find('.modal button.btn-secondary').simulate('click'); - wrapper.update(); - wrapper.find('.modal CacheInput[value="output"]').prop('onChange')( { target: { value: 'measurements' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="output0"]').prop('onChange')( { target: { value: 'species' }}); - wrapper.update(); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - - expect(wrapper.props().data.contents.datasets[1]).to.deep.equal({ - 'name': 'testing_data', - 'outputs': [ - 'measurements', - 'species' - ] - }); - - // training_alg - wrapper.find('rect#block_block').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - expect(wrapper.find('.modal').find('CacheInput#tcModalInitFocus').props().value).to.equal('block'); - wrapper.find('.modal').find('CacheInput#tcModalInitFocus').prop('onChange')( { target: { value: 'training_alg' }}); - wrapper.update(); - wrapper.find('.modal button.btn-secondary').at(1).simulate('click'); - wrapper.update(); - /* - wrapper.find('.modal button.btn-secondary').at(0).simulate('click'); - wrapper.update(); - wrapper.find('.modal button.btn-secondary').at(1).simulate('click'); - wrapper.update(); - */ - wrapper.find('.modal CacheInput[value="input"]').prop('onChange')( { target: { value: 'measurements' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="input0"]').prop('onChange')( { target: { value: 'species' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="output"]').prop('onChange')( { target: { value: 'lda_machine' }}); - wrapper.update(); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - - expect(wrapper.props().data.contents.blocks[0]).to.deep.equal({ - 'name': 'training_alg', - 'inputs': [ - 'measurements', - 'species' - ], - 'outputs': [ - 'lda_machine' - ], - 'synchronized_channel': '', - }); - - // testing_alg - wrapper.find('rect#block_block0').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - expect(wrapper.find('.modal').find('CacheInput#tcModalInitFocus').props().value).to.equal('block0'); - wrapper.find('.modal').find('CacheInput#tcModalInitFocus').prop('onChange')( { target: { value: 'testing_alg' }}); - wrapper.update(); - wrapper.find('.modal button.btn-secondary').at(1).simulate('click'); - wrapper.update(); - /* - wrapper.find('.modal button.btn-secondary').at(0).simulate('click'); - wrapper.update(); - wrapper.find('.modal button.btn-secondary').at(1).simulate('click'); - wrapper.update(); - */ - wrapper.find('.modal CacheInput[value="input"]').prop('onChange')( { target: { value: 'measurements' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="input0"]').prop('onChange')( { target: { value: 'lda_machine' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="output"]').prop('onChange')( { target: { value: 'scores' }}); - wrapper.update(); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - - expect(wrapper.props().data.contents.blocks[1]).to.deep.equal({ - 'name': 'testing_alg', - 'inputs': [ - 'measurements', - 'lda_machine' - ], - 'outputs': [ - 'scores' - ], - 'synchronized_channel': '', - }); - - // analyzer - wrapper.find('rect#block_analyzer').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - expect(wrapper.find('.modal').find('CacheInput#tcModalInitFocus').props().value).to.equal('analyzer'); - /* - wrapper.find('.modal button.btn-secondary').simulate('click'); - wrapper.update(); - */ - wrapper.find('.modal button.btn-secondary').at(1).simulate('click'); - wrapper.update(); - wrapper.find('.modal CacheInput[value="input"]').prop('onChange')( { target: { value: 'scores' }}); - wrapper.update(); - wrapper.find('.modal CacheInput[value="input0"]').prop('onChange')( { target: { value: 'species' }}); - wrapper.update(); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - - expect(wrapper.props().data.contents.analyzers[0]).to.deep.equal({ - 'name': 'analyzer', - 'inputs': [ - 'scores', - 'species' - ], - 'synchronized_channel': '', - }); - - /* connect stuff via createConnections() */ - // channel: training_data - wrapper.instance().createConnections([{ from: 'training_data.measurements', to: 'training_alg.measurements', channel: 'training_data' }]); - // channel: training_data - wrapper.instance().createConnections([{ from: 'training_data.species', to: 'training_alg.species', channel: 'training_data' }]); - // channel: testing_data - wrapper.instance().createConnections([{ from: 'testing_data.measurements', to: 'testing_alg.measurements', channel: 'testing_data' }]); - // channel: training_data - wrapper.instance().createConnections([{ from: 'training_alg.lda_machine', to: 'testing_alg.lda_machine', channel: 'training_data' }]); - // channel: testing_data - wrapper.instance().createConnections([{ from: 'testing_data.species', to: 'analyzer.species', channel: 'testing_data' }]); - // channel: testing_data - wrapper.instance().createConnections([{ from: 'testing_alg.scores', to: 'analyzer.scores', channel: 'testing_data' }]); - - /* fix channels */ - /* - // testing_alg - wrapper.find('rect#block_testing_alg').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - wrapper.find('.modal #channelSelector DropdownItem#channel-testing_data').simulate('click'); - wrapper.update(); - wrapper.find('button.close').simulate('click'); - wrapper.update(); - */ - - expect(wrapper.props().data.contents.blocks[1]).to.deep.equal({ - 'name': 'testing_alg', - 'inputs': [ - 'measurements', - 'lda_machine' - ], - 'outputs': [ - 'scores' - ], - 'synchronized_channel': 'testing_data', - }); - - // analyzer - /* - wrapper.find('rect#block_analyzer').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - wrapper.find('.modal #channelSelector DropdownItem#channel-testing_data').simulate('click'); - wrapper.update(); - wrapper.find('button.close').simulate('click'); - wrapper.update(); - */ - - expect(wrapper.props().data.contents.analyzers[0]).to.deep.equal({ - 'name': 'analyzer', - 'inputs': [ - 'scores', - 'species' - ], - 'synchronized_channel': 'testing_data', - }); - - /* theres alot of expect statements here for a reason: - * each statement checks a sub-part of the toolchain - * its redundant when the test passes but helpful when somethings off, - * you can narrow the part of the tc that isn't right alot quicker - */ - const data = wrapper.props().data; - const ch1 = data.contents.representation.channel_colors['training_data']; - const ch2 = data.contents.representation.channel_colors['testing_data']; - expect(data.contents.datasets).to.deep.equalInAnyOrder( [ - { - 'name': 'training_data', - 'outputs': [ - 'measurements', - 'species' - ] - }, - { - 'name': 'testing_data', - 'outputs': [ - 'measurements', - 'species' - ] - } - ]); - - expect(data.contents.blocks).to.deep.equalInAnyOrder([ - { - 'inputs': [ - 'measurements', - 'species' - ], - 'name': 'training_alg', - 'outputs': [ - 'lda_machine' - ], - 'synchronized_channel': 'training_data' - }, - { - 'inputs': [ - 'lda_machine', - 'measurements' - ], - 'name': 'testing_alg', - 'outputs': [ - 'scores' - ], - 'synchronized_channel': 'testing_data' - } - ]); - - expect(data.contents.analyzers).to.deep.equalInAnyOrder([ - { - 'inputs': [ - 'scores', - 'species' - ], - 'name': 'analyzer', - 'synchronized_channel': 'testing_data' - } - ]); - - expect(data.contents.connections).to.deep.equalInAnyOrder([ - { - 'channel': 'testing_data', - 'from': 'testing_alg.scores', - 'to': 'analyzer.scores' - }, - { - 'channel': 'training_data', - 'from': 'training_alg.lda_machine', - 'to': 'testing_alg.lda_machine' - }, - { - 'channel': 'testing_data', - 'from': 'testing_data.measurements', - 'to': 'testing_alg.measurements' - }, - { - 'channel': 'training_data', - 'from': 'training_data.measurements', - 'to': 'training_alg.measurements' - }, - { - 'channel': 'training_data', - 'from': 'training_data.species', - 'to': 'training_alg.species' - }, - { - 'channel': 'testing_data', - 'from': 'testing_data.species', - 'to': 'analyzer.species' - } - ]); - - expect(data.contents.representation).to.deep.equalInAnyOrder({ - 'blocks': { - 'analyzer': { - 'col': 46, - 'height': 3, - 'row': 4, - 'width': 10 - }, - 'testing_alg': { - 'col': 32, - 'height': 3, - 'row': 3, - 'width': 10 - }, - 'testing_data': { - 'col': 6, - 'height': 3, - 'row': 5, - 'width': 10 - }, - 'training_alg': { - 'col': 19, - 'height': 3, - 'row': 0, - 'width': 10 - }, - 'training_data': { - 'col': 6, - 'height': 3, - 'row': 0, - 'width': 10 - } - }, - 'channel_colors': { - 'testing_data': ch2, - 'training_data': ch1 - }, - 'connections': { - 'testing_alg.scores/analyzer.scores': [], - 'testing_data.measurements/testing_alg.measurements': [], - 'testing_data.species/analyzer.species': [], - 'training_alg.lda_machine/testing_alg.lda_machine': [], - 'training_data.measurements/training_alg.measurements': [], - 'training_data.species/training_alg.species': [] - } - }); - - expect(data).to.deep.equalInAnyOrder(getIrisTc(ch1, ch2)); - }); - }); - - describe('Insert Object Modal', () => { - const timeout = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - const tcs = testTcs.map(tc => getValidObj(tc)); - const dbs = testDbs.map(db => getValidDatabaseObj(db)); - const algs = testAlgs.map(alg => getValidAlgorithmObj(alg)); - - const state = { - ...reducer({}, { type: '', payload: {}}), - toolchain: tcs, - database: dbs, - algorithm: algs, - }; - - const sets = Selectors.flattenedDatabases(state); - const normalAlgorithms = Selectors.normalBlocks(state); - const protocols = Selectors.databaseProtocols(state); - const analyzerAlgorithms = Selectors.analyzerBlocks(state); - - it(`inserts test/iris_advanced/1`, async () => { - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const tcName = 'test/iom/1'; - const tc = getValidObj({name: tcName, contents: {}}); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - expect(wrapper).to.have.props( - ['data', 'sets', 'protocols', 'toolchains', 'databases', 'normalAlgorithms', 'analyzerAlgorithms', 'saveFunc', 'updateFunc'] - ); - - expect(wrapper.props().data).to.have.property('name', tcName); - - const _selectBlocks = (bNames: string[]) => { return; }; - const selectBlocks = sinon.spy(_selectBlocks); - - // context-menu insert obj modal - // insert at x:6 because thats where the original toolchain has its first block on the x-axis - wrapper.instance().handleSvgContextMenu({}, { clicked: 'addObject', x: 6, y: 0, selectBlocks }); - wrapper.update(); - expect(wrapper.find('InsertObjectModal').props().active).to.equal(true); - expect(updateFunc.callCount).to.equal(0); - - // search for "test/iris" in toolchain list - wrapper.find('InsertObjectModal Input[placeholder="Search..."]').prop('onChange')( { target: { value: 'test/iris' }}); - wrapper.update(); - - // wait for fuse process to search & return result list - await timeout(1000); - wrapper.update(); - - // click on the iris_advanced one, which should be first - const res = wrapper.find('ListGroup.searchResults ListGroupItem'); - expect(res).to.have.lengthOf(4); - expect(res.at(0).html()).to.include('test/iris_advanced/1'); - res.at(0).simulate('click'); - wrapper.update(); - - const data = wrapper.props().data; - const ch1 = data.contents.representation.channel_colors['training_data']; - const ch2 = data.contents.representation.channel_colors['testing_data']; - - // make sure the toolchain was inserted - // basically make sure the toolchain is the same as test/iris_advanced/1 but w different name - expect(data.contents).to.deep.equalInAnyOrder({ - 'analyzers': [ - { - 'inputs': [ - 'scores', - 'species' - ], - 'name': 'analyzer', - 'synchronized_channel': 'testing_data' - } - ], - 'blocks': [ - { - 'inputs': [ - 'measurements', - 'species' - ], - 'name': 'training_alg', - 'outputs': [ - 'lda_machine' - ], - 'synchronized_channel': 'training_data' - }, - { - 'inputs': [ - 'lda_machine', - 'measurements' - ], - 'name': 'testing_alg', - 'outputs': [ - 'scores' - ], - 'synchronized_channel': 'testing_data' - }, - { - 'inputs': [ - 'measurements' - ], - 'name': 'pre_training', - 'outputs': [ - 'measurements' - ], - 'synchronized_channel': 'training_data' - }, - { - 'inputs': [ - 'measurements' - ], - 'name': 'pre_testing', - 'outputs': [ - 'measurements' - ], - 'synchronized_channel': 'testing_data' - } - ], - 'connections': [ - { - 'channel': 'testing_data', - 'from': 'testing_alg.scores', - 'to': 'analyzer.scores' - }, - { - 'channel': 'training_data', - 'from': 'training_alg.lda_machine', - 'to': 'testing_alg.lda_machine' - }, - { - 'channel': 'testing_data', - 'from': 'testing_data.species', - 'to': 'analyzer.species' - }, - { - 'channel': 'training_data', - 'from': 'training_data.species', - 'to': 'training_alg.species' - }, - { - 'channel': 'training_data', - 'from': 'training_data.measurements', - 'to': 'pre_training.measurements' - }, - { - 'channel': 'training_data', - 'from': 'pre_training.measurements', - 'to': 'training_alg.measurements' - }, - { - 'channel': 'testing_data', - 'from': 'testing_data.measurements', - 'to': 'pre_testing.measurements' - }, - { - 'channel': 'testing_data', - 'from': 'pre_testing.measurements', - 'to': 'testing_alg.measurements' - } - ], - 'datasets': [ - { - 'name': 'training_data', - 'outputs': [ - 'measurements', - 'species' - ] - }, - { - 'name': 'testing_data', - 'outputs': [ - 'measurements', - 'species' - ] - } - ], - 'description': '', - 'representation': { - 'blocks': { - 'analyzer': { - 'col': 59, - 'height': 3, - 'row': 6, - 'width': 10 - }, - 'pre_testing': { - 'col': 19, - 'height': 3, - 'row': 5, - 'width': 10 - }, - 'pre_training': { - 'col': 19, - 'height': 3, - 'row': 0, - 'width': 10 - }, - 'testing_alg': { - 'col': 46, - 'height': 3, - 'row': 5, - 'width': 10 - }, - 'testing_data': { - 'col': 6, - 'height': 3, - 'row': 6, - 'width': 10 - }, - 'training_alg': { - 'col': 32, - 'height': 3, - 'row': 1, - 'width': 10 - }, - 'training_data': { - 'col': 6, - 'height': 3, - 'row': 1, - 'width': 10 - } - }, - 'channel_colors': { - 'testing_data': ch2, - 'training_data': ch1 - }, - 'connections': { - 'pre_testing.measurements/testing_alg.measurements': [], - 'pre_training.measurements/training_alg.measurements': [], - 'testing_alg.scores/analyzer.scores': [], - 'testing_data.measurements/pre_testing.measurements': [], - 'testing_data.species/analyzer.species': [], - 'training_alg.lda_machine/testing_alg.lda_machine': [], - 'training_data.measurements/pre_training.measurements': [], - 'training_data.species/training_alg.species': [] - } - } - }); - }); - }); - - describe('Regression Tests', () => { - const timeout = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); - }; - - const tcs = testTcs.map(tc => getValidObj(tc)); - const dbs = testDbs.map(db => getValidDatabaseObj(db)); - const algs = testAlgs.map(alg => getValidAlgorithmObj(alg)); - - const state = { - ...reducer({}, { type: '', payload: {}}), - toolchain: tcs, - database: dbs, - algorithm: algs, - }; - - const sets = Selectors.flattenedDatabases(state); - const normalAlgorithms = Selectors.normalBlocks(state); - const protocols = Selectors.databaseProtocols(state); - const analyzerAlgorithms = Selectors.analyzerBlocks(state); - - const saveFunc = sinon.spy(); - const _updateFunc = (obj) => { - wrapper.setProps && wrapper.setProps({ data: obj }); - }; - const updateFunc = sinon.spy(_updateFunc); - const tcName = 'test/iris/1'; - - it('Properly changes connection names when renaming an input', () => { - const tc = getValidObj(getIrisTc()); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - // change testing_alg.lda_machine to testing_alg.lda - wrapper.find('rect#block_testing_alg').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - wrapper.find('.modal CacheInput[value="lda_machine"]').prop('onChange')( { target: { value: 'lda' }}); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - expect(wrapper.find('.modal CacheInput[value="lda"]').props().value).to.equal('lda'); - - const data = wrapper.props().data; - expect(data.contents.representation.connections).to.not.have.property('training_alg.lda_machine/testing_alg.lda_machine'); - expect(data.contents.representation.connections).to.have.property('training_alg.lda_machine/testing_alg.lda'); - }); - - it('Properly changes connection names when renaming an output', () => { - const tc = getValidObj(getIrisTc()); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - // change testing_alg.lda_machine to testing_alg.lda - wrapper.find('rect#block_training_alg').simulate('click'); - wrapper.update(); - expect(wrapper.find('ToolchainModal').props().active).to.equal(true); - wrapper.find('.modal CacheInput[value="lda_machine"]').prop('onChange')( { target: { value: 'lda' }}); - wrapper.find('.modal button.btn-success').simulate('click'); - wrapper.update(); - expect(wrapper.find('.modal CacheInput[value="lda"]').props().value).to.equal('lda'); - - const data = wrapper.props().data; - expect(data.contents.representation.connections).to.not.have.property('training_alg.lda_machine/testing_alg.lda_machine'); - expect(data.contents.representation.connections).to.have.property('training_alg.lda/testing_alg.lda_machine'); - }); - - it('Properly deletes the training_data.species/training_alg.species connection', async () => { - const conToDel = { from: 'training_data.species', to: 'training_alg.species', channel: 'training_data' }; - const tc = getValidObj(getIrisTc()); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - // change testing_alg.lda_machine to testing_alg.lda - expect(wrapper.exists('#training_data-species-training_alg-species')).to.equal(true); - wrapper.instance().handleConnectionContextMenu({}, { clicked: 'delete', connection: conToDel }); - wrapper.update(); - expect(wrapper.exists('#training_data-species-training_alg-species')).to.equal(false); - - const data = wrapper.props().data; - expect(data.contents.representation.connections).to.not.have.property('training_data.species/training_data.species'); - expect(data.contents.connections.findIndex(c => c.from == conToDel.from && c.to == conToDel.to)).to.equal(-1); - }); - - it('Properly deletes conns between training_data & training_alg, and clears training_alg sync channel', async () => { - const conToDel = { from: 'training_data.species', to: 'training_alg.species', channel: 'training_data' }; - const conToDel2 = { from: 'training_data.measurements', to: 'training_alg.measurements', channel: 'training_data' }; - const tc = getValidObj(getIrisTc()); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - // change testing_alg.lda_machine to testing_alg.lda - expect(wrapper.exists('#training_data-species-training_alg-species')).to.equal(true); - expect(wrapper.exists('#training_data-measurements-training_alg-measurements')).to.equal(true); - wrapper.instance().handleConnectionContextMenu({}, { clicked: 'delete', connection: conToDel }); - wrapper.update(); - wrapper.instance().handleConnectionContextMenu({}, { clicked: 'delete', connection: conToDel2 }); - wrapper.update(); - expect(wrapper.exists('#training_data-species-training_alg-species')).to.equal(false); - expect(wrapper.exists('#training_data-measurements-training_alg-measurements')).to.equal(false); - - const data = wrapper.props().data; - expect(data.contents.blocks.find(b => b.name == 'training_alg')).to.have.property('synchronized_channel', ''); - }); - - it('Disables the layout button when the toolchain is invalid', async () => { - const conToDel = { from: 'training_data.species', to: 'training_alg.species', channel: 'training_data' }; - const conToDel2 = { from: 'training_data.measurements', to: 'training_alg.measurements', channel: 'training_data' }; - const tc = getValidObj(getIrisTc()); - wrapper = mount( - <C - data={tc} - sets={sets} - protocols={protocols} - toolchains={state.toolchain} - databases={state.database} - normalAlgorithms={normalAlgorithms} - analyzerAlgorithms={analyzerAlgorithms} - saveFunc={saveFunc} - updateFunc={updateFunc} - /> - ); - - // change testing_alg.lda_machine to testing_alg.lda - expect(wrapper.exists('#training_data-species-training_alg-species')).to.equal(true); - expect(wrapper.exists('#training_data-measurements-training_alg-measurements')).to.equal(true); - expect(wrapper.find('Button[title="This will use Graphviz to generate a more visually understandable layout for your toolchain."]')) - .to.have.prop('disabled', false); - wrapper.instance().handleConnectionContextMenu({}, { clicked: 'delete', connection: conToDel }); - wrapper.update(); - wrapper.instance().handleConnectionContextMenu({}, { clicked: 'delete', connection: conToDel2 }); - wrapper.update(); - expect(wrapper.exists('#training_data-species-training_alg-species')).to.equal(false); - expect(wrapper.exists('#training_data-measurements-training_alg-measurements')).to.equal(false); - - const data = wrapper.props().data; - expect(data.contents.blocks.find(b => b.name == 'training_alg')).to.have.property('synchronized_channel', ''); - expect(wrapper.find('Button[title="This will use Graphviz to generate a more visually understandable layout for your toolchain."]')) - .to.have.prop('disabled', true); - }); - }); -}); diff --git a/conda/js/src/components/toolchain/ToolchainModal.jsx b/conda/js/src/components/toolchain/ToolchainModal.jsx deleted file mode 100644 index 972393d6..00000000 --- a/conda/js/src/components/toolchain/ToolchainModal.jsx +++ /dev/null @@ -1,522 +0,0 @@ -// @flow -import * as React from 'react'; -import { Link } from 'react-router-dom'; -import { - Container, - Row, - Col, - Button, - ButtonGroup, - Form, - FormGroup, - Label, - Input, - InputGroup, - FormText, - Collapse, - Card, - CardHeader, - CardBody, - TabContent, TabPane, - Navbar, - Nav, NavItem, NavLink, CardTitle, CardText, - FormFeedback, - Alert, - InputGroupAddon, - Badge, - Modal, ModalBody, ModalHeader, ModalFooter, - UncontrolledDropdown, UncontrolledButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, -} from 'reactstrap'; - -import CacheInput from '../CacheInput.jsx'; -import DeleteInputBtn from '../DeleteInputBtn.jsx'; -import { generateNewKey, copyObj } from '@helpers'; -import { toUrl } from '@helpers/api'; -import type { BlockType } from '@helpers/toolchainTypes'; - -type Props = { - // is the modal active? - active: boolean, - // block data - data: BlockType, - // name of all blocks - blockNames: string[], - // possible channels the block can be sync'd to (an obj w keys as channel names & vals as colours) - possibleChannels: { [string]: string }, - // func to close modal - toggle: () => any, - // delete the block - deleteBlock: () => any, - // updates the block info - updateBlockData: (data: ModalCache) => any, - // creates an Algorithm based on the current block given the new alg's name - createAlgorithmFromBlock: (algName: string) => any, -}; - -export type ModalAction = 'delete' | 'add' | 'change'; - -type IO = { name: string, action: ?ModalAction, original: string }; - -export type ModalCache = { - name: string, - synchronized_channel: ?string, - inputs: ?IO[], - outputs: ?IO[], -}; - -type State = { - // name, synchronized_channel, inputs, outputs - cache: ModalCache, - // name of the algorithm to create using this block's data - algName: string, - // are there unsaved changes for the block? - unsavedChanges: boolean, - // whether the alg creation was successful or not - wasSuccessful: ?boolean, -}; - -const newCacheFromData = (data: BlockType): ModalCache => { - return { - synchronized_channel: data.synchronized_channel || undefined, - name: data.name, - inputs: data.inputs ? data.inputs.map(i => ({ name: i, action: 'change', original: i })) : undefined, - outputs: data.outputs ? data.outputs.map(i => ({ name: i, action: 'change', original: i })) : undefined, - }; -}; - -const getCurrentObjs = (arr: any) => arr -.filter((o, i, os) => o.action !== 'delete' && !os.slice(i).find(p => p.action === 'delete' && p.name === o.name)); - -const getCurrentNames = (arr: any) => getCurrentObjs(arr).map(o => o.name); - -class ToolchainModal extends React.Component<Props, State> { - constructor(props: Props){ - super(props); - } - - state = { - cache: newCacheFromData(this.props.data), - algName: '/', - unsavedChanges: false, - wasSuccessful: null, - } - - componentDidUpdate = (prevProps: Props, prevState: State) => { - if(this.props.data && prevProps.data !== this.props.data){ - this.setState({ cache: newCacheFromData(this.props.data) }); - } - } - - updateAlgName = (newName: string) => { - this.setState({ algName: newName }); - } - - addIO = (io: boolean) => { - const arr = io ? 'inputs' : 'outputs'; - const newKey = generateNewKey(io ? 'input' : 'output', getCurrentNames(this.state.cache[arr])); - this.setState({ - cache: { - ...this.state.cache, - [arr]: [ - ...this.state.cache[arr], - { - name: newKey, - action: 'add', - original: newKey, - } - ] - }, - unsavedChanges: true, - }); - } - - deleteIO = (io: boolean, name: string) => { - const arr = io ? 'inputs' : 'outputs'; - this.setState({ - cache: { - ...this.state.cache, - [arr]: [ - ...this.state.cache[arr], - { - name: name, - action: 'delete', - original: name, - } - ] - }, - unsavedChanges: true, - - }); - } - - changeIO = (io: boolean, oldObj: IO, newName: string) => { - const arr = io ? 'inputs' : 'outputs'; - const newObj = {...oldObj, name: newName}; - const newArr = this.state.cache[arr].map(o => { - if(o.original === oldObj.original){ - return newObj; - } else { - return o; - } - }); - - this.setState({ - cache: { - ...this.state.cache, - [arr]: newArr, - }, - unsavedChanges: true, - - }); - } - - changeName = (newName: string) => { - this.setState({ - cache: { - ...this.state.cache, - name: newName, - }, - unsavedChanges: newName !== this.props.data.name, - - }); - } - - changeChannel = (channel: string) => { - //console.log(`changing channel from ${ this.state.cache.synchronized_channel } to ${ channel }`); - this.setState({ - cache: { - ...this.state.cache, - synchronized_channel: channel, - }, - unsavedChanges: channel !== this.props.data.synchronized_channel, - - }); - } - - saveBlock = () => { - this.props.updateBlockData(this.state.cache); - this.setState({ unsavedChanges: false }); - } - - // creates an Algorithm from the (potentially unsaved) block data - // and gives the user a link to go edit it in a new tab - createAlgorithmFromBlock = async () => { - const algName = `${ this.state.algName }/1`; - try { - await this.props.createAlgorithmFromBlock(algName); - this.setState({ wasSuccessful: true }); - } catch(e) { - this.setState({ wasSuccessful: false }); - } - //window.open(, '_blank'); - } - - resetCaches = () => { - this.setState({ cache: newCacheFromData(this.props.data), unsavedChanges: false, algName: '/', wasSuccessful: null }); - } - - renderAlgorithmCreator = () => { - const segs = this.state.algName.split('/'); - const user = segs[0]; - const name = segs[1]; - const unsavedChanges = this.state.unsavedChanges; - const algStr = user == '' || name == '' ? '' : `"${ this.state.algName }"`; - - return ( - <React.Fragment> - <Alert color='secondary'> - <Label> - Create an Algorithm from this Block - </Label> - <Row> - <Col sm='4 mr-0 pr-0'> - <CacheInput - fieldTest - value={user} - onChange={(e) => this.updateAlgName(`${ e.target.value }/${ name }`)} - placeholder={'Username...'} - disabled={unsavedChanges} - /> - </Col> - <Col sm='4 mr-0 pr-0'> - <CacheInput - fieldTest - value={name} - onChange={(e) => this.updateAlgName(`${ user }/${ e.target.value }`)} - placeholder={'Name...'} - disabled={unsavedChanges} - /> - </Col> - <Col sm='4'> - <Button - block - color='secondary' - onClick={() => { - this.createAlgorithmFromBlock(); - }} - disabled={user == '' || name == '' || unsavedChanges} - > - Create { algStr } - </Button> - </Col> - </Row> - { unsavedChanges && user !== '' && name !== '' && - <Row> - <Col> - <span className='text-danger'> - Please save your changes before creating an algorithm! - </span> - </Col> - </Row> - } - { this.state.wasSuccessful && - <Row> - <Col> - <span> - The algorithm was created!{' '} - <Link - rel="noopener noreferrer" - target='_blank' - to={`/algorithm/${ this.state.algName }/1`} - > - Edit it here - </Link> - . - If you do not see it, please refresh your browser tab or window. - </span> - </Col> - </Row> - } - { this.state.wasSuccessful === false && - <Row> - <Col> - <span className='text-danger'> - The algorithm could not be created. Please create it manually. - </span> - </Col> - </Row> - } - - </Alert> - </React.Fragment> - ); - } - - render = () => { - const data = this.state.cache; - if(!data) - return null; - - const hasInputs = Array.isArray(data.inputs); - const hasOutputs = Array.isArray(data.outputs); - // TODO: right now this is just an escape hatch for channel changing not propogating throughout the network. this needs to be fixed - const channelSelectDisabled = false; //Object.keys(this.props.possibleChannels).length === 1; - - const currChannel: string = data.synchronized_channel || ''; - - const formatChannel = (channel: string) => { - return ( - <span> - <span style={{backgroundColor: this.props.possibleChannels[channel] || '#000000'}}> - - </span> - - { channel === '' ? '<none>' : channel } - </span> - ); - }; - - const inputNames = hasInputs ? getCurrentNames(data.inputs) : []; - const outputNames = hasOutputs ? getCurrentNames(data.outputs) : []; - const inputDup = inputNames.slice().sort().find((n, i, ns) => i !== 0 && n === ns[i - 1]); - const outputDup = outputNames.slice().sort().find((n, i, ns) => i !== 0 && n === ns[i - 1]); - const hasInputDups = inputDup != undefined; - const hasOutputDups = outputDup != undefined; - - return ( - <Modal - size='lg' - isOpen={this.props.active} - toggle={this.props.toggle} - fade={true} - onOpened={e => { - const f = document.querySelector('#tcModalInitFocus'); - if(f && f.focus) - f.focus(); - this.resetCaches(); - }} - > - <ModalHeader toggle={this.props.toggle}> - Editing <pre className='preInline'>{data.name}</pre> - {' '} - </ModalHeader> - <ModalBody> - <Form> - <FormGroup> - { - hasInputs && this.renderAlgorithmCreator() - } - </FormGroup> - <FormGroup row> - <Col> - <Label>Block Name</Label> - <CacheInput - delay={200} - id='tcModalInitFocus' - value={data.name || ''} - fieldTest={true} - onChange={(e) => { - this.changeName(e.target.value); - }} - validateFunc={(str) => { - if(str === this.props.data.name){ - return true; - } - if(this.props.blockNames.includes(str)){ - return <span>This name is already taken by an existing block</span>; - } - if(str.includes('-')){ - return <span>{`Cannot include the dash ("-") character`}</span>; - } - return true; - }} - /> - </Col> - { data.synchronized_channel !== undefined - && - <Col> - <Label>Synchronized channel</Label> - <div> - <UncontrolledDropdown - id='channelSelector' - disabled={channelSelectDisabled} - > - <DropdownToggle caret outline block> - { formatChannel(currChannel || '') } - </DropdownToggle> - <DropdownMenu> - { - Array.from(new Set([...Object.keys(this.props.possibleChannels), currChannel || ''])) - .filter(c => c !== '') - .map((c, i) => - <DropdownItem - id={`channel-${ c }`} - key={i} - onClick={e => this.changeChannel(c)} - > - { formatChannel(c) } - </DropdownItem> - ) - } - </DropdownMenu> - </UncontrolledDropdown> - </div> - </Col> - } - </FormGroup> - <Row> - { - hasInputs && - <Col sm={hasOutputs ? 6 : 12}> - <Label>Inputs</Label> - { - getCurrentObjs(data.inputs) - .map((obj, i, inputs) => { - const input = obj.name; - return ( - <FormGroup - key={i} - > - <CacheInput - value={input} - fieldTest={true} - onChange={(e) => { - this.changeIO(true, obj, e.target.value); - }} - invalid={input === inputDup} - > - <DeleteInputBtn - deleteFunc={e => { - this.deleteIO(true, input); - }} - /> - </CacheInput> - </FormGroup> - ); - }) - } - <Button - onClick={e => { - this.addIO(true); - }} - > - Add Input - </Button> - </Col> - } - { - hasOutputs && - <Col sm={hasInputs ? 6 : 12}> - <Label>Outputs</Label> - { - getCurrentObjs(data.outputs) - .map((obj, i, outputs) => { - const output = obj.name; - return ( - <FormGroup - key={i} - > - <CacheInput - value={output} - fieldTest={true} - onChange={(e) => { - this.changeIO(false, obj, e.target.value); - }} - > - <DeleteInputBtn - deleteFunc={e => { - this.deleteIO(false, output); - }} - /> - </CacheInput> - </FormGroup> - ); - }) - } - <Button - onClick={e => { - this.addIO(false); - }} - > - Add Output - </Button> - </Col> - } - </Row> - </Form> - </ModalBody> - <ModalFooter> - <Button color='danger' - onClick={(e) => { - this.props.deleteBlock(); - this.props.toggle(); - }} - > - Delete Block - </Button> - <Button color='success' - disabled={hasInputDups || hasOutputDups} - onClick={(e) => { - this.saveBlock(); - this.props.toggle(); - }} - > - Save Changes - </Button> - </ModalFooter> - </Modal> - ); - } -} - -export default ToolchainModal; diff --git a/conda/js/src/components/toolchain/ToolchainModal.spec.jsx b/conda/js/src/components/toolchain/ToolchainModal.spec.jsx deleted file mode 100644 index cb6a8d25..00000000 --- a/conda/js/src/components/toolchain/ToolchainModal.spec.jsx +++ /dev/null @@ -1,172 +0,0 @@ -// @flow -import React from 'react'; -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { spies } from '@test'; - -import C from './ToolchainModal.jsx'; - -// sleep for a bit, to wait for async things -const sleep = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); -}; - -describe('<ToolchainModal />', function () { - this.timeout(10000); - - let wrapper; - - afterEach(() => { - if(wrapper && wrapper.unmount) - wrapper.unmount(); - }); - - const testBlockData = { - name: 'block1', - inputs: [ - 'input1', - ], - outputs: [ - 'output1', - ], - synchronized_channel: 'dataset1', - }; - - const testBlockData2 = { - name: 'block1', - inputs: [ - 'input0', - 'input1', - ], - outputs: [ - 'output1', - ], - synchronized_channel: 'dataset1', - }; - - const testChannels = { 'dataset1': '#880000' }; - - const testBlockNames = ['block1']; - - it('accepts the test data with the right props', () => { - wrapper = mount( - <C - active={true} - data={testBlockData} - blockNames={testBlockNames} - possibleChannels={testChannels} - toggle={() => {}} - deleteBlock={() => {}} - updateBlockData={() => {}} - createAlgorithmFromBlock={() => {}} - /> - ); - expect(wrapper).to.have.props([ - 'active', - 'data', - 'blockNames', - 'possibleChannels', - 'toggle', - 'deleteBlock', - 'updateBlockData', - 'createAlgorithmFromBlock', - ]); - }); - - it('lets you change the name to another valid name', async () => { - const newBlockName = 'block2'; - wrapper = mount( - <C - active={true} - data={testBlockData} - blockNames={testBlockNames} - possibleChannels={testChannels} - toggle={() => {}} - deleteBlock={() => {}} - updateBlockData={() => {}} - createAlgorithmFromBlock={() => {}} - /> - ); - wrapper.find('input#tcModalInitFocus').prop('onChange')( { target: { value: newBlockName }}); - wrapper.update(); - await sleep(300); - wrapper.update(); - expect(wrapper.exists('.input-group-append .text-danger')).to.equal(false); - }); - - it('doesnt let you change the name to a valid name with a dash ("-") in it', async () => { - const newBlockName = 'block-2'; - wrapper = mount( - <C - active={true} - data={testBlockData} - blockNames={testBlockNames} - possibleChannels={testChannels} - toggle={() => {}} - deleteBlock={() => {}} - updateBlockData={() => {}} - createAlgorithmFromBlock={() => {}} - /> - ); - wrapper.find('input#tcModalInitFocus').prop('onChange')( { target: { value: newBlockName }}); - wrapper.update(); - await sleep(300); - wrapper.update(); - expect(wrapper.exists('.input-group-append .text-danger')).to.equal(true); - }); - - it('lets you switch the names of inputs (test 1)', async () => { - const newBlockName = 'block'; - wrapper = mount( - <C - active={true} - data={testBlockData2} - blockNames={testBlockNames} - possibleChannels={testChannels} - toggle={() => {}} - deleteBlock={() => {}} - updateBlockData={() => {}} - createAlgorithmFromBlock={() => {}} - /> - ); - wrapper.find('input[value="input0"]').prop('onChange')( { target: { value: 'input1' }}); - wrapper.update(); - await sleep(1000); - wrapper.find('input[value="input1"]').at(1).prop('onChange')( { target: { value: 'input0' }}); - wrapper.update(); - await sleep(1000); - wrapper.update(); - expect(wrapper.state('cache')).to.have.deep.property('inputs', [ - { action: 'change', name: 'input1', original: 'input0' }, - { action: 'change', name: 'input0', original: 'input1' }, - ]); - }); - - it('lets you switch the names of inputs (test 2)', async () => { - const newBlockName = 'block'; - wrapper = mount( - <C - active={true} - data={testBlockData2} - blockNames={testBlockNames} - possibleChannels={testChannels} - toggle={() => {}} - deleteBlock={() => {}} - updateBlockData={() => {}} - createAlgorithmFromBlock={() => {}} - /> - ); - wrapper.find('input[value="input1"]').prop('onChange')( { target: { value: 'input0' }}); - wrapper.update(); - await sleep(1000); - wrapper.find('input[value="input0"]').at(0).prop('onChange')( { target: { value: 'input1' }}); - wrapper.update(); - await sleep(1000); - wrapper.update(); - expect(wrapper.state('cache')).to.have.deep.property('inputs', [ - { action: 'change', name: 'input1', original: 'input0' }, - { action: 'change', name: 'input0', original: 'input1' }, - ]); - }); -}); diff --git a/conda/js/src/components/toolchain/index.js b/conda/js/src/components/toolchain/index.js deleted file mode 100644 index 307b7492..00000000 --- a/conda/js/src/components/toolchain/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import ConnectedToolchainEditor, {ToolchainEditor} from './ToolchainEditor.jsx'; -import GraphicalEditor from './GraphicalEditor.jsx'; - -export { - ToolchainEditor, - GraphicalEditor, -}; - -export default ConnectedToolchainEditor; diff --git a/conda/js/src/helpers/api.js b/conda/js/src/helpers/api.js deleted file mode 100644 index 618229ba..00000000 --- a/conda/js/src/helpers/api.js +++ /dev/null @@ -1,114 +0,0 @@ -// @flow -// API helpers not tied to any specific library -import { pluralize } from './beat.js'; -import type { BeatEntity } from './beat.js'; -import type { StringObject } from '.'; - -export type Fetchable = BeatEntity | 'settings' | 'environments'; - -const fetchConfig = { - mode: 'cors' -}; - -let port = '5000'; - -export const toUrl = (str: string) => `http://127.0.0.1:${ port }/${ str }`; - -// curried func for calling the REST API -// basically: -// <response> = genApiCall(<http rest verb>)(<endpoint>)(<payload if any>) -const genApiCall = (method) => (be: Fetchable) => async (obj: any) => { - const validMethods = ['GET', 'POST', 'PUT', 'DELETE']; - if(!validMethods.includes(method)) - throw new Error(`invalid method: ${ method }`); - const headers = new Headers(); - if(method !== 'GET') - headers.append('Content-Type', 'application/json'); - const config = { - headers, - ...fetchConfig, - ...{ - method, - body: obj ? JSON.stringify(obj) : obj - } - }; - - const seg = be === 'settings' || be === 'environments' ? be : pluralize(be); - let res = await fetch(toUrl(seg), config); - let json = await res.json(); - console.log(json); - return json; -}; - -// sets the port number for api calls -export const setPort = (newPort: number) => { - port = newPort; -}; - -// gens all the default API funcs for an endpoint -export const genModuleApiFuncs = (be: Fetchable) => { - return { - get: genApiCall('GET')(be), - post: genApiCall('POST')(be), - put: genApiCall('PUT')(be), - delete: genApiCall('DELETE')(be), - }; -}; - -// fetches layout info from graphviz for a toolchain -const layoutUrl = toUrl('layout'); -export const fetchLayout = async (tcName: string) => { - const layoutConfig = { - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - method: 'POST', - body: JSON.stringify({ toolchain: tcName }), - }; - const res = await fetch(layoutUrl, layoutConfig); - const json = await res.json(); - return JSON.parse(json); -}; - -// generates a python file from a template given some args payload -const templatesUrl = toUrl('templates'); -// given the BEAT entity and a dict of args, tries to generate a python file from a template -// returns either the response if successful or `false` if the python file already exists -const generateTemplate = async (be: string, args: {[string]: any}) => { - const templatesConfig = { - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - method: 'POST', - body: JSON.stringify({ entity: be, ...args}), - }; - const res = await fetch(templatesUrl, templatesConfig); - if(res.status === 200){ - // okay - const json = await res.json(); - return JSON.parse(json); - } else { - if(res.status === 409){ - // python file already exists, return false to let callers know - return false; - } - } -}; - -export const generateDatabaseTemplate = async (name: string, confirm: boolean, views: string[]) => { - return generateTemplate('databases', {name, views, confirm}); -}; - -export const generateAlgorithmTemplate = async (name: string, confirm: boolean, contents: any) => { - return generateTemplate('algorithms', {name, contents, confirm}); -}; - -export const generateLibraryTemplate = async (name: string, confirm: boolean, uses: StringObject) => { - return generateTemplate('libraries', {name, uses, confirm}); -}; - -export const generatePlotterTemplate = async (name: string, confirm: boolean, uses: StringObject) => { - return generateTemplate('plotters', {name, uses, confirm}); -}; diff --git a/conda/js/src/helpers/beat.js b/conda/js/src/helpers/beat.js deleted file mode 100644 index 77d15e8f..00000000 --- a/conda/js/src/helpers/beat.js +++ /dev/null @@ -1,525 +0,0 @@ -// @flow -// BEAT-specific helpers -import { copyObj } from '.'; -import type { Contents as ToolchainContents, Group } from './toolchainTypes'; -// all the BEAT entities -export type BeatEntity = 'database' | 'library' | 'dataformat' | 'algorithm' | 'toolchain' | 'experiment' | 'plotter' | 'plotterparameter'; - -// format of an instance of a beat entity in redux store -export type BeatObject = {| - // name of the object - name: string, - // contents (whats stored in the JSON files in the beat prefix) - contents: any, - // extra contents that are additions, arent relevant to the web platform, and dont conform to the BEAT schemas - extraContents?: { - groups: Group[] - }, -|}; - -// format for the settings object -export type BeatSettings = {| - prefix: string -|}; - -// format for an environment object (info about the available docker envs) -export type BeatEnvironment = {| - name: string, - packages: { [string]: string }, - queues: { - [string]: { - memory_limit: number, - nb_slots: number, - max_slots_per_user: number, - nb_cores_per_slot: number, - time_limit: number, - }, - }, - accessibility: string, - languages: [ string ], - version: string, - short_description: string, -|}; - -export const BEAT_ENTITIES: BeatEntity[] = [ - 'database', - 'library', - 'dataformat', - 'algorithm', - 'toolchain', - 'experiment', - 'plotter', - 'plotterparameter', -]; - -// types auto-recognized by beat.core -export const BUILTIN_TYPES = [ - 'int8', - 'int16', - 'int32', - 'int64', - 'uint8', - 'uint16', - 'uint32', - 'uint64', - 'float32', - 'float64', - 'complex64', - 'complex128', - 'bool', - 'string', - 'array', - 'object', -]; - -// result types for analyzers -export const ANALYZER_RESULT_TYPES = [ - 'int32', - 'float32', - 'bool', - 'string' -]; - -Object.freeze(BEAT_ENTITIES); -Object.freeze(BUILTIN_TYPES); -Object.freeze(ANALYZER_RESULT_TYPES); - -// get toolchain name from experiment name -export const getTcFromExpName = (expName: string) => expName.split('/').slice(1, 4).join('/'); - -// default object for beat entity instances -export const getDefaultEntityObject = () => ({name: '', contents: {}}); - -// most fields/name of/in beat objects need to conform to this regex -export const rxField = /^[a-zA-Z_][a-zA-Z0-9_-]*$/; - -// how many segments (separated by '/') are in an entity's name -export const nameSegmentsForEntity = (entity: BeatEntity) => { - if(entity === 'database') - return 2; - if(entity === 'experiment') - return 5; - return 3; -}; - -// pluralizes an entity -export const pluralize = (be: BeatEntity): string => { - switch(be) { - case 'database': - return 'databases'; - case 'library': - return 'libraries'; - case 'dataformat': - return 'dataformats'; - case 'algorithm': - return 'algorithms'; - case 'toolchain': - return 'toolchains'; - case 'experiment': - return 'experiments'; - case 'plotter': - return 'plotters'; - case 'plotterparameter': - return 'plotterparameters'; - default: - throw new Error(`Cannot pluralize invalid BE: "${ be }"`); - } -}; - -// validates that a name for beat object of an entity is fine, given the names for all objects of that entity -export const nameValidator = (be: BeatEntity, allNames?: string[] = []) => (name: string): boolean => { - if(allNames.includes(name)){ - return false; - } - - const rxThreeSeg = /^[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+\/\d+$/; - const rxTwoSeg = /^[A-Za-z0-9_]+\/\d+$/; - const rxFiveSeg = /^[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+\/\d+\/[A-Za-z0-9_-]+$/; - if(be !== 'database' && be !== 'experiment' && !rxThreeSeg.test(name)) - return false; - if(be === 'database' && !rxTwoSeg.test(name)) - return false; - if(be === 'experiment' && !rxFiveSeg.test(name)) - return false; - - const segs = name.split('/'); - if(segs.length < 2){ - return false; - } - if(segs[0] === '/') { - return false; - } - if(segs[segs.length - 1] === '/'){ - return false; - } - - return true; -}; - -// some editors are prime targets for better/additional validation - -export type ValidatorObjectField = boolean | boolean[]; - -// only algs & libs have this extra validation right now -export type ValidatorObject = AlgorithmValidatorObject | LibraryValidatorObject; - -export type ValidatorFunc = (obj: BeatObject, allObjs: BeatObject[]) => ValidatorObject; - -// algorithm validator info -export type AlgorithmValidatorObject = { - // is algorithm name valid? - name: ValidatorObjectField, - // is there at least one endpoint group? - endpoint0Exists: ValidatorObjectField, - // does the first endpoint have at least 1 input field? - endpoint0InputExists: ValidatorObjectField, - // does the first endpoint have at least 1 output field? - endpoint0OutputExists: ValidatorObjectField, - // does each endpoint have a unique name? - endpointNamesUnique: ValidatorObjectField, - // is there at least 1 result? - result0Exists: ValidatorObjectField, -}; - -// lots of checks for algs -export const algorithmValidator = (obj: BeatObject, allObjs: BeatObject[]): AlgorithmValidatorObject => { - - let name = false; - try { - name = nameValidator('algorithm', allObjs.map(o => o.name))(obj.name); - } catch(e){} - - let endpoint0Exists = false; - try { - endpoint0Exists = obj.contents.groups.length > 0; - } catch(e){} - - let endpoint0InputExists = false; - try { - endpoint0InputExists = Object.keys(obj.contents.groups[0].inputs).length > 0; - } catch(e){} - - let endpoint0OutputExists = false; - try { - endpoint0OutputExists = Object.keys(obj.contents.groups[0].outputs).length > 0; - } catch(e){} - - let endpointNamesUnique = false; - try { - endpointNamesUnique = Array.from(new Set(obj.contents.groups.map(g => g.name))).length === obj.contents.groups.length; - } catch(e){} - - let result0Exists = false; - try { - result0Exists = Object.keys(obj.contents.results).length > 0; - } catch(e){} - - const valid: AlgorithmValidatorObject = { - name, - endpoint0Exists, - endpoint0InputExists, - endpoint0OutputExists, - endpointNamesUnique, - result0Exists, - }; - - return valid; -}; - -// extra validation for libs -export type LibraryValidatorObject = { - // is library name valid? - name: ValidatorObjectField, - // is language valid? - language: ValidatorObjectField, -}; - -export const libraryValidator = (obj: BeatObject, allObjs: BeatObject[]): LibraryValidatorObject => { - let name = false; - try { - name = nameValidator('library', allObjs.map(o => o.name))(obj.name); - } catch(e) { - } - - let language = false; - try { - language = obj.contents.language === 'python'; - } catch(e) { - } - - return { - name, - language, - }; -}; - -// these next several funcs, the "getValid***Obj", returns a properly-formed JSON obj, -// optionally filling in fields with an existing obj. -// basically they exist to keep malformed JSON from breaking the editors. -// -export const getValidAlgorithmObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - const obj = { - ...getObj, - contents: { - parameters: {}, - uses: {}, - groups: [ - { - name: 'group', - inputs: {}, - outputs: {}, - } - ], - description: '', - language: 'python', - ...getObj.contents, - }, - }; - - if(!obj.contents.hasOwnProperty('results') && !obj.contents.hasOwnProperty('splittable')) - obj.contents.splittable = false; - - return obj; -}; - -export const getValidDatabaseObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - if(Array.isArray(getObj.contents.protocols)){ - getObj.contents.protocols = getObj.contents.protocols - .map(p => { - p.sets = p.sets.map(s => ({parameters: {}, ...s})); - return p; - }); - } - - const obj = { - ...getObj, - contents: { - 'description': '', - 'root_folder': '', - 'protocols': [], - ...getObj.contents, - }, - }; - - return obj; -}; - -export const getValidDataformatObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - const obj = { - ...getObj, - contents: { - '#description': '', - ...getObj.contents, - }, - }; - - return obj; -}; - -export type ParameterValue = number | string | boolean; - -// returns the default value for a specific parameter, given the parameter object -export const expGetDefaultParameterValue = (parameter: any): ParameterValue => { - const parsedDefault = Number.parseFloat(parameter.default); - if(parameter.default) - return Number.isNaN(parsedDefault) ? parameter.default : parsedDefault; - if(parameter.range) - return parameter.range[0]; - if(parameter.choice && parameter.choice.length > 0) - return parameter.choice.length[0]; - - switch(parameter.type){ - case 'string': - return ''; - case 'bool': - return false; - // number - default: - return 0; - } -}; - -export const getValidExperimentObj = (data: BeatObject = {name: '', contents: {}}, tc: BeatObject, algs: BeatObject[]) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - getObj.contents.datasets = getObj.contents.datasets || {}; - getObj.contents.blocks = getObj.contents.blocks || {}; - getObj.contents.analyzers = getObj.contents.analyzers || {}; - - const datasets = tc.contents.datasets - .map(ds => ({[ds.name]: getObj.contents.datasets[ds.name] || {set: '', protocol: '', database: ''}})) - .reduce((o, ods) => ({...o, ...ods}), {...getObj.contents.datasets}); - - const blocks = tc.contents.blocks - .map(b => ({ - [b.name]: { - algorithm: '', - inputs: b.inputs ? b.inputs.reduce((o, inp) => ({...o, [inp]: ''}), {}) : {}, - outputs: b.outputs ? b.outputs.reduce((o, out) => ({...o, [out]: ''}), {}) : {}, - parameters: {}, - ...(getObj.contents.blocks[b.name] || {}) - } - })) - .reduce((o, blk) => ({...o, ...blk}), {...getObj.contents.blocks}); - - const analyzers = tc.contents.analyzers - .map(a => ({ - [a.name]: { - algorithm: '', - inputs: a.inputs ? a.inputs.reduce((o, inp) => ({...o, [inp]: ''}), {}) : {}, - parameters: {}, - ...(getObj.contents.analyzers[a.name] || {}) - } - })) - .reduce((o, ana) => ({...o, ...ana}), {...getObj.contents.analyzers}); - - const paramAlgs = Object.entries({...blocks, ...analyzers}) - .map(([bName, block]) => algs.find(a => a.name === block.algorithm)) - .filter(a => a !== null && a !== undefined && a.contents.parameters !== undefined && Object.keys(a.contents.parameters).length > 0) - .map(a => ({ - [a.name]: Object.entries(a.contents.parameters) - .map(([pName, param]) => ({[pName]: expGetDefaultParameterValue(param)})) - .reduce((o, p) => ({...o, ...p}), {}) - })) - .reduce((o, p) => ({...o, ...p}), {}); - ; - - const globals = { - queue: 'Default', - environment: { - version: '0.0.4', - name: 'Scientific Python 2.7' - }, - ...paramAlgs, - ...getObj.contents.globals - }; - - - const obj = { - ...getObj, - contents: { - description: '', - ...getObj.contents, - globals, - datasets, - blocks, - analyzers, - }, - }; - - return obj; -}; - -export const getValidLibraryObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - const obj = { - ...getObj, - contents: { - 'description': '', - 'language': 'python', - 'uses': {}, - ...getObj.contents, - }, - }; - - return obj; -}; - -export const getValidToolchainObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - extraContents: {}, - ...copyObj(data) - }; - - const obj = { - ...getObj, - contents: { - 'description': '', - datasets: [], - blocks: [], - analyzers: [], - connections: [], - representation: { - connections: {}, - blocks: {}, - channel_colors: {}, - }, - ...getObj.contents, - }, - extraContents: { - groups: [], - ...getObj.extraContents - } - }; - - return obj; -}; - -export const getValidPlotterObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - const obj = { - ...getObj, - contents: { - description: '', - language: 'python', - parameters: {}, - dataformat: '', - uses: {}, - ...getObj.contents, - } - }; - - return obj; -}; - -export const getValidPlotterparameterObj = (data: BeatObject = {name: '', contents: {}}) => { - const getObj = { - name: '', - contents: {}, - ...copyObj(data) - }; - - const obj = { - ...getObj, - contents: { - description: '', - ...getObj.contents, - } - }; - - return obj; -}; diff --git a/conda/js/src/helpers/beat.spec.js b/conda/js/src/helpers/beat.spec.js deleted file mode 100644 index 9b4e62f0..00000000 --- a/conda/js/src/helpers/beat.spec.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import { expect } from 'chai'; -import sinon from 'sinon'; -import { spies } from '@test'; -import { nameValidator } from './beat.js'; - -describe('nameValidator', () => { - describe('database names', () => { - let be = 'database'; - let otherNames = []; - it('should not accept names with a "-" character', () => { - expect(nameValidator(be, otherNames)('replay-me/1')).to.equal(false); - }); - it('should accept names with a "_" character', () => { - expect(nameValidator(be, otherNames)('replay_me/1')).to.equal(true); - }); - it('should accept names with only ascii characters', () => { - expect(nameValidator(be, otherNames)('replayme/1')).to.equal(true); - }); - }); -}); diff --git a/conda/js/src/helpers/index.js b/conda/js/src/helpers/index.js deleted file mode 100644 index 34ab4b3a..00000000 --- a/conda/js/src/helpers/index.js +++ /dev/null @@ -1,58 +0,0 @@ -// @flow -// basic helpers - common bits of code refactored to DRY -import copy from 'fast-copy'; -export { debounce, throttle } from 'throttle-debounce'; - -// changes a field in an object to a different name -// only required because keys are often mutable -export const changeObjFieldName = (obj: {}, oldName: string, newName: string): {} => { - return Object.entries(obj) - .map(([name, val]) => [name === oldName ? newName : name, val]) - .reduce((o, [name, val]) => ({...o, [name]: val}), {}); -}; - -// generates a new unique key given a prefix (like "value" or "param") and possibly conflicting keys -export const generateNewKey = (keyPrefix: string = '', existingKeys: string[]) => { - if(!existingKeys.includes(keyPrefix)) - return keyPrefix; - let newKey = ''; - let v = 0; - while(true) { - const tryKey = `${ keyPrefix }${ v }`; - if(existingKeys.includes(tryKey)){ - v++; - continue; - } - newKey = tryKey; - break; - } - - return newKey; -}; - -/* - * Generates a random "bright" colour, ignoring extreme values (very close to white/black). - * Adapted from https://stackoverflow.com/a/1484514 - */ -export const getRandomBrightColor = () => { - var letters = '789ABCD'; - var color = '#'; - for (var i = 0; i < 6; i++) { - color += letters[Math.floor(Math.random() * letters.length)]; - } - return color; -}; - -// recursively sorts an object's keys in alphabetical order -// useful for comparing (deeply nested) objects in stringified form. -// probably would be better to use another dep specialized in deeply comparing objects? -export const sortObject = (o: any) => Object.entries(o) -.sort(([n1, v1], [n2, v2]) => n1 > n2 ? 1 : -1) -.reduce((o, [n, v]) => ({...o, [n]: Object((v: any)) === v ? sortObject(v) : v}), {}); - -export const copyObj = (any: any) => { - return copy(any); -}; - -export type GenericObject = {[string]: any}; -export type StringObject = {[string]: string}; diff --git a/conda/js/src/helpers/schema/algorithm.json b/conda/js/src/helpers/schema/algorithm.json deleted file mode 100644 index 55609d74..00000000 --- a/conda/js/src/helpers/schema/algorithm.json +++ /dev/null @@ -1,226 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "algorithm", - "title": "Algorithm descriptor", - "description": "This schema defines the properties of an algorithm", - - "oneOf": [ - { "$ref": "#/definitions/block" }, - { "$ref": "#/definitions/analyzer" } - ], - - "definitions": { - - "endpoints": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "type": "object", - "properties": { - "type": { "$ref": "common#/definitions/reference" }, - "description": { "type": "string" } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - }, - "uniqueItems": true, - "additionalProperties": false - }, - - "io_group": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "inputs": { "$ref": "#/definitions/endpoints" }, - "outputs": { "$ref": "#/definitions/endpoints" } - }, - "required": [ - "inputs", - "outputs" - ], - "additionalProperties": false - }, - - "input_group": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "inputs": { "$ref": "#/definitions/endpoints" } - }, - "required": [ - "inputs" - ], - "additionalProperties": false - }, - - "block_groups": { - "type": "array", - "items": [ - { "$ref": "#/definitions/io_group" } - ], - "additionalItems": { "$ref": "#/definitions/input_group" }, - "minItems": 1 - }, - - "range": { - "type": "array", - "items": { "$ref": "common#/definitions/value" }, - "minItems": 2, - "maxItems": 2 - }, - - "choice": { - "type": "array", - "items": { "$ref": "common#/definitions/value" }, - "minItems": 2 - }, - - "parameter": { - "type": "object", - "properties": { - "type": { "$ref": "common#/definitions/basetype" }, - "default": { "$ref": "common#/definitions/value" }, - "description": { "type": "string" } - }, - "required": [ - "type" - ] - }, - - "range_parameter": { - "allOf": [ - { "$ref": "#/definitions/parameter" }, - { - "properties": { - "range": { "$ref": "#/definitions/range" } - }, - "required": [ - "range" - ] - } - ], - "additionalProperties": false - }, - - "choice_parameter": { - "allOf": [ - { "$ref": "#/definitions/parameter" }, - { - "properties": { - "choice": { "$ref": "#/definitions/choice" } - }, - "required": [ - "choice" - ] - } - ], - "additionalProperties": false - }, - - "parameters": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "oneOf": [ - { "$ref": "#/definitions/parameter" }, - { "$ref": "#/definitions/range_parameter" }, - { "$ref": "#/definitions/choice_parameter" } - ] - } - }, - "uniqueItems": true, - "additionalProperties": false - }, - - "block": { - - "type": "object", - - "properties": { - "language": { "$ref": "common#/definitions/language" }, - "description": { "$ref": "common#/definitions/description" }, - "groups": { "$ref": "#/definitions/block_groups" }, - "parameters": { "$ref": "#/definitions/parameters" }, - "splittable": { "type": "boolean" }, - "uses": { "$ref": "common#/definitions/uses" }, - "schema_version": { "$ref": "common#/definitions/version" } - - }, - - "required": [ - "language", - "groups", - "splittable" - ], - - "additionalProperties": false - - }, - - "analyzer_groups": { - "type": "array", - "items": { "$ref": "#/definitions/input_group" }, - "minItems": 1 - }, - - "resulttype": { - "oneOf": [ - { "type": "string", "enum": [ "int32", "float32", "bool", "string" ] }, - { "type": "string", "pattern": "^system/[a-zA-Z0-9_-]+/[0-9]+$" }, - { "type": "string", "pattern": "^plot/[a-zA-Z0-9_-]+/[0-9]+$" } - ] - }, - - "result": { - "type": "object", - "properties": { - "type": { "$ref": "#/definitions/resulttype" }, - "display": { "type": "boolean" }, - "description": { "type": "string" } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - - "results": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "$ref": "#/definitions/result" - } - }, - "uniqueItems": true, - "additionalProperties": false - }, - - "analyzer": { - - "type": "object", - - "properties": { - "language": { "$ref": "common#/definitions/language" }, - "description": { "$ref": "common#/definitions/description" }, - "groups": { "$ref": "#/definitions/analyzer_groups" }, - "parameters": { "$ref": "#/definitions/parameters" }, - "results": { "$ref": "#/definitions/results" }, - "uses": { "$ref": "common#/definitions/uses" }, - "schema_version": { "$ref": "common#/definitions/version" } - }, - - "required": [ - "language", - "groups", - "results" - ], - - "additionalProperties": false - } - - } - -} diff --git a/conda/js/src/helpers/schema/common.json b/conda/js/src/helpers/schema/common.json deleted file mode 100644 index b9443dce..00000000 --- a/conda/js/src/helpers/schema/common.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "common", - "title": "Common definitions for BEAT", - "description": "This schema defines common properties of a BEAT objects", - - "definitions": { - - "reference": { - "type": "string", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_-]*/[a-zA-Z0-9_-]+/[0-9]+$" - }, - - "basetype": { - "type": "string", - "enum": [ - "int8", - "int16", - "int32", - "int64", - "uint8", - "uint16", - "uint32", - "uint64", - "float32", - "float64", - "complex64", - "complex128", - "bool", - "string" - ] - }, - - "value": { - "oneOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "boolean" } - ] - }, - - "description": { - "type": "string" - }, - - "language": { - - "type": "string", - "enum": [ - "unknown", - "python", - "cxx", - "matlab", - "r" - ] - - }, - - "uses": { - "type": "object", - "uniqueItems": true, - "additionalProperties": false, - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_]*$": { - "$ref": "#/definitions/reference" - } - } - }, - - "version": { - "type": "number", - "multipleOf": 1.0, - "minimum": 1.0 - } - - } - -} diff --git a/conda/js/src/helpers/schema/database.json b/conda/js/src/helpers/schema/database.json deleted file mode 100644 index d8a1cb0a..00000000 --- a/conda/js/src/helpers/schema/database.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "database", - "title": "Database descriptor", - "description": "This schema defines the properties of a BEAT database", - - "type": "object", - - "properties": { - - "root_folder": { - "type": "string", - "pattern": "^(/[^/]+)+$" - }, - - "protocols": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/definitions/protocol" } - }, - - "description": { "$ref": "common#/definitions/description" }, - - "schema_version": { "$ref": "common#/definitions/version" } - - }, - - "required": [ - "root_folder", - "protocols" - ], - - "additionalProperties": false, - - "definitions": { - - "identifier": { - "type": "string", - "pattern": "^[a-zA-Z0-9_-]+$" - }, - - "view": { - "type": "string", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" - }, - - "protocol": { - "type": "object", - "properties": { - "name": { "$ref": "#/definitions/protocol_name" }, - "template": { "$ref": "#/definitions/identifier" }, - "sets": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/definitions/set" } - } - }, - "required": ["name", "template", "sets"], - "additionalProperties": false - }, - - "protocol_name": { - "type": "string", - "pattern": "^[a-zA-Z0-9_][\\.a-zA-Z0-9_-]*$" - }, - - "set": { - "type": "object", - "properties": { - "name": { "$ref": "#/definitions/identifier" }, - "template": { "$ref": "#/definitions/identifier" }, - "view": { "$ref": "#/definitions/view" }, - "parameters": { "$ref": "#/definitions/parameters" }, - "outputs": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "$ref": "common#/definitions/reference" - } - }, - "minProperties": 0, - "uniqueItems": true, - "additionalProperties": false - } - }, - "required": ["name", "view", "outputs"], - "additionalProperties": false - }, - - "parameters": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "$ref": "#/definitions/parameter_value" - } - } - }, - - "parameter_value": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } - ] - } - - } - -} diff --git a/conda/js/src/helpers/schema/dataformat.json b/conda/js/src/helpers/schema/dataformat.json deleted file mode 100644 index e244fd7c..00000000 --- a/conda/js/src/helpers/schema/dataformat.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "dataformat", - "title": "Dataformat descriptor", - "description": "This schema defines the properties of a data format", - - "type": "object", - - "properties": { - "#extends": { "$ref": "common#/definitions/reference" }, - "#description": { "$ref": "common#/definitions/description" }, - "#schema_version": { "$ref": "common#/definitions/version" } - }, - - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "oneOf": [ - { "$ref": "common#/definitions/basetype" }, - { "$ref": "#/definitions/array1d" }, - { "$ref": "#/definitions/array2d" }, - { "$ref": "#/definitions/array3d" }, - { "$ref": "#/definitions/array4d" }, - { "$ref": "#/definitions/array5d" }, - { "$ref": "common#/definitions/reference" }, - { "$ref": "#" } - ] - } - }, - - "additionalProperties": false, - - "definitions": { - - "array1d": { - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": [ - { "type": "integer" }, - { - "oneOf": [ - { "$ref": "common#/definitions/basetype" }, - { "$ref": "common#/definitions/reference" }, - { "$ref": "#" } - ] - } - ], - "additionalItems": false - }, - - "array2d": { - "type": "array", - "minItems": 3, - "maxItems": 3, - "items": [ - { "type": "integer" }, - { "type": "integer" }, - { - "oneOf": [ - { "$ref": "common#/definitions/basetype" }, - { "$ref": "common#/definitions/reference" }, - { "$ref": "#" } - ] - } - ], - "additionalItems": false - }, - - "array3d": { - "type": "array", - "minItems": 4, - "maxItems": 4, - "items": [ - { "type": "integer" }, - { "type": "integer" }, - { "type": "integer" }, - { - "oneOf": [ - { "$ref": "common#/definitions/basetype" }, - { "$ref": "common#/definitions/reference" }, - { "$ref": "#" } - ] - } - ], - "additionalItems": false - }, - - "array4d": { - "type": "array", - "minItems": 5, - "maxItems": 5, - "items": [ - { "type": "integer" }, - { "type": "integer" }, - { "type": "integer" }, - { "type": "integer" }, - { - "oneOf": [ - { "$ref": "common#/definitions/basetype" }, - { "$ref": "common#/definitions/reference" }, - { "$ref": "#" } - ] - } - ], - "additionalItems": false - }, - - "array5d": { - "type": "array", - "minItems": 6, - "maxItems": 6, - "items": [ - { "type": "integer" }, - { "type": "integer" }, - { "type": "integer" }, - { "type": "integer" }, - { "type": "integer" }, - { - "oneOf": [ - { "$ref": "common#/definitions/basetype" }, - { "$ref": "common#/definitions/reference" }, - { "$ref": "#" } - ] - } - ], - "additionalItems": false - } - - } - -} diff --git a/conda/js/src/helpers/schema/execution.json b/conda/js/src/helpers/schema/execution.json deleted file mode 100644 index c6e0fa82..00000000 --- a/conda/js/src/helpers/schema/execution.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "execution", - "title": "Single algorithm execution descriptor", - "description": "This schema defines the properties of an execution block", - - "oneOf": [ - { "$ref": "#/definitions/block" }, - { "$ref": "#/definitions/analyzer" } - ], - - "definitions": { - - "hash": { - "type": "string", - "pattern": "^[a-fA-F0-9]{64}$" - }, - - "cache_path": { - "type": "string", - "pattern": "^[a-fA-F0-9]{2}/[a-fA-F0-9]{2}/[a-fA-F0-9]{2}/[a-fA-F0-9]{58}$" - }, - - "cache_input": { - "type": "object", - "properties": { - "path": { "$ref": "#/definitions/cache_path" }, - "hash": { "$ref": "#/definitions/hash" }, - "channel": { "$ref": "database#/definitions/identifier" }, - "endpoint": { "$ref": "toolchain#/definitions/identifier" } - }, - "required": [ - "path", - "hash", - "channel", - "endpoint" - ], - "additionalProperties": false - }, - - "dataset_input": { - "type": "object", - "properties": { - "database": { - "$ref": "experiment#/definitions/versioned_database" - }, - "protocol": { "$ref": "database#/definitions/protocol_name" }, - "set": { "$ref": "database#/definitions/identifier" }, - "output": { "$ref": "toolchain#/definitions/identifier" }, - "channel": { "$ref": "database#/definitions/identifier" }, - "path": { "$ref": "#/definitions/cache_path" }, - "hash": { "$ref": "#/definitions/hash" }, - "endpoint": { "$ref": "toolchain#/definitions/identifier" } - }, - "required": [ - "database", - "protocol", - "set", - "output", - "channel", - "hash", - "path", - "endpoint" - ], - "additionalProperties": false - }, - - "input": { - "oneOf": [ - { "$ref": "#/definitions/cache_input" }, - { "$ref": "#/definitions/dataset_input" } - ] - }, - - "output": { - "type": "object", - "properties": { - "path": { "$ref": "#/definitions/cache_path" }, - "hash": { "$ref": "#/definitions/hash" }, - "channel": { "$ref": "database#/definitions/identifier" }, - "endpoint": { "$ref": "toolchain#/definitions/identifier" } - }, - "required": [ - "path", - "hash", - "channel", - "endpoint" - ], - "additionalProperties": false - }, - - "input_map": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_]*$": { - "$ref": "#/definitions/input" - } - }, - "minProperties": 1, - "uniqueItems": true, - "additionalProperties": false - }, - - "range_value": { - "oneOf": [ - { "type": "null" }, - { - "type": "number", - "multipleOf": 1.0, - "minimum": 0.0 - } - ] - }, - - "range": { - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { "$ref": "#/definitions/range_value" } - }, - - "element": { - "type": "object", - "properties": { - "inputs": { "$ref": "#/definitions/input_map" }, - "channel": { "$ref": "database#/definitions/identifier" }, - "algorithm": { "$ref": "common#/definitions/reference" }, - "parameters": { "$ref": "experiment#/definitions/parameter_set" }, - "queue": { "$ref": "experiment#/definitions/queue" }, - "environment": { "$ref": "experiment#/definitions/environment" }, - "range": { "$ref": "#/definitions/range" }, - "schema_version": { "$ref": "common#/definitions/version" } - }, - "required": [ - "inputs", - "channel", - "algorithm", - "parameters", - "queue", - "environment" - ] - }, - - "output_map": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_]*$": { - "$ref": "#/definitions/output" - } - }, - "minProperties": 1, - "uniqueItems": true, - "additionalProperties": false - }, - - "block": { - "allOf": [ - { "$ref": "#/definitions/element" }, - { - "properties": { - "outputs": { "$ref": "#/definitions/output_map" }, - "nb_slots": { "$ref": "experiment#/definitions/slots" } - }, - "required": [ - "outputs", - "nb_slots" - ] - } - ] - }, - - "result": { - "type": "object", - "properties": { - "path": { "$ref": "#/definitions/cache_path" }, - "hash": { "$ref": "#/definitions/hash" } - }, - "required": [ - "path", - "hash" - ], - "additionalProperties": false - }, - - "analyzer": { - "allOf": [ - { "$ref": "#/definitions/element" }, - { - "properties": { - "result": { "$ref": "#/definitions/result" } - }, - "required": [ - "result" - ] - } - ] - } - - } - -} diff --git a/conda/js/src/helpers/schema/experiment.json b/conda/js/src/helpers/schema/experiment.json deleted file mode 100644 index dd909cfd..00000000 --- a/conda/js/src/helpers/schema/experiment.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "experiment", - "title": "Experiment descriptor", - "description": "This schema defines the properties of a experiment", - - "type": "object", - - "properties": { - - "description": { "$ref": "common#/definitions/description" }, - - "datasets": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { "$ref": "#/definitions/dataset" } - }, - "minProperties": 1, - "uniqueItems": true, - "additionalProperties": false - }, - - "blocks": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { "$ref": "#/definitions/block" } - }, - "uniqueItems": true, - "additionalProperties": false - }, - - "analyzers": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { "$ref": "#/definitions/analyzer" } - }, - "minProperties": 1, - "uniqueItems": true, - "additionalProperties": false - }, - - "globals": { - "type": "object", - "properties": { - "queue": { "$ref": "#/definitions/queue" }, - "environment": { "$ref": "#/definitions/environment" } - }, - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_]*/[a-zA-Z_][a-zA-Z0-9_-]*/[0-9]+$": { - "$ref": "#/definitions/parameter_set" - } - }, - "uniqueItems": true, - "additionalProperties": false - }, - - "schema_version": { "$ref": "common#/definitions/version" } - - }, - - "required": [ - "datasets", - "blocks", - "analyzers", - "globals" - ], - - "additionalProperties": false, - - "definitions": { - - "queue": { - "type": "string" - }, - - "environment": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "version": { "type": "string" } - }, - "required": [ - "name", - "version" - ], - "additionalProperties": false - }, - - "slots": { - "type": "integer", - "minimum": 1, - "exclusiveMinimum": false - }, - - "versioned_database": { - "type": "string", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*/[0-9]+$" - }, - - "dataset": { - "type": "object", - "properties": { - "set": { "$ref": "database#/definitions/identifier" }, - "protocol": { "$ref": "database#/definitions/protocol_name" }, - "database": { "$ref": "#/definitions/versioned_database" } - }, - "required": [ - "set", - "protocol", - "database" - ], - "additionalProperties": false - }, - - "connection_map": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_]*$": { - "$ref": "toolchain#/definitions/identifier" - } - }, - "minProperties": 1, - "uniqueItems": true, - "additionalProperties": false - }, - - "block": { - "type": "object", - "properties": { - "inputs": { "$ref": "#/definitions/connection_map" }, - "outputs": { "$ref": "#/definitions/connection_map" }, - "algorithm": { "$ref": "common#/definitions/reference" }, - "parameters": { "$ref": "#/definitions/parameter_set" }, - "queue": { "$ref": "#/definitions/queue" }, - "environment": { "$ref": "#/definitions/environment" }, - "nb_slots": { "$ref": "#/definitions/slots" } - }, - "required": [ - "inputs", - "outputs", - "algorithm" - ], - "additionalProperties": false - }, - - "analyzer": { - "type": "object", - "properties": { - "inputs": { "$ref": "#/definitions/connection_map" }, - "algorithm": { "$ref": "common#/definitions/reference" }, - "parameters": { "$ref": "#/definitions/parameter_set" }, - "queue": { "$ref": "#/definitions/queue" }, - "environment": { "$ref": "#/definitions/environment" }, - "nb_slots": { "$ref": "#/definitions/slots" } - }, - "required": [ - "inputs", - "algorithm" - ], - "additionalProperties": false - }, - - "parameter_set": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "$ref": "common#/definitions/value" - } - }, - "minProperties": 0, - "uniqueItems": true, - "additionalProperties": false - } - - } - -} diff --git a/conda/js/src/helpers/schema/index.js b/conda/js/src/helpers/schema/index.js deleted file mode 100644 index 03e33d6e..00000000 --- a/conda/js/src/helpers/schema/index.js +++ /dev/null @@ -1,44 +0,0 @@ -import Ajv from 'ajv'; - -import common from './common.json'; -import dataformat from './dataformat.json'; -import database from './database.json'; -import library from './library.json'; -import algorithm from './algorithm.json'; -import toolchain from './toolchain.json'; -import experiment from './experiment.json'; -import execution from './execution.json'; -import plotter from './plotter.json'; -import plotterparameter from './plotterparameter.json'; -import draft04 from 'ajv/lib/refs/json-schema-draft-04.json'; - -const ajv = new Ajv({ allErrors: true, schemaId: 'id' }); -ajv.addMetaSchema(draft04); -ajv.addSchema([common, dataformat, database, library, algorithm, toolchain, experiment, plotter, plotterparameter, execution]); - -export const VALIDATORS = { - dataformat: ajv.compile(dataformat), - database: ajv.compile(database), - library: ajv.compile(library), - algorithm: ajv.compile(algorithm), - toolchain: ajv.compile(toolchain), - experiment: ajv.compile(experiment), - plotter: ajv.compile(plotter), - plotterparameter: ajv.compile(plotterparameter), - execution: ajv.compile(execution), -}; -Object.freeze(VALIDATORS); - -export default function validate(validator, obj) { - const isValid = validator(obj.contents || obj); - const errs = validator.errors; - /* - if(!isValid) { - console.error(`Object "${ obj.name || obj }" not valid!:`); - console.log(obj); - console.log(validator.errors); - } - */ - - return isValid ? false : errs; -} diff --git a/conda/js/src/helpers/schema/library.json b/conda/js/src/helpers/schema/library.json deleted file mode 100644 index 2a5f0021..00000000 --- a/conda/js/src/helpers/schema/library.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "library", - "title": "Library descriptor", - "description": "This schema defines the properties of a library", - - "type": "object", - - "required": [ - "language" - ], - - "properties": { - "language": { "$ref": "common#/definitions/language" }, - "description": { "$ref": "common#/definitions/description" }, - "uses": { "$ref": "common#/definitions/uses" }, - "schema_version": { "$ref": "common#/definitions/version" } - }, - "additionalProperties": false -} diff --git a/conda/js/src/helpers/schema/plotter.json b/conda/js/src/helpers/schema/plotter.json deleted file mode 100644 index f5d32f2b..00000000 --- a/conda/js/src/helpers/schema/plotter.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "plotter", - "title": "Plotting algorithm descriptor", - "description": "This schema defines the properties of a plotting algorithm", - - "type": "object", - - "properties": { - "language": { "$ref": "common#/definitions/language" }, - "description": { "$ref": "common#/definitions/description" }, - "parameters": { "$ref": "algorithm#/definitions/parameters" }, - "dataformat": { - "type": "string", - "pattern": "^plot/[a-zA-Z0-9_-]+/[0-9]+$" - }, - "uses": { "$ref": "common#/definitions/uses" }, - "schema_version": { "$ref": "common#/definitions/version" } - }, - - "required": [ - "language", - "parameters", - "dataformat" - ], - - "additionalProperties": false -} diff --git a/conda/js/src/helpers/schema/plotterparameter.json b/conda/js/src/helpers/schema/plotterparameter.json deleted file mode 100644 index 59760635..00000000 --- a/conda/js/src/helpers/schema/plotterparameter.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "plotterparameter", - "title": "Plotter configurator descriptor", - "description": "This schema defines the properties of an instance of a plot configuration", - - "type": "object", - - "properties": { - "description": { - "type": "string" - }, - "plotter": { - "$ref": "common#/definitions/reference" - }, - "data": { - "$ref": "experiment#/definitions/parameter_set" - } - }, - "required": ["plotter"] -} diff --git a/conda/js/src/helpers/schema/toolchain.json b/conda/js/src/helpers/schema/toolchain.json deleted file mode 100644 index 7c14cc86..00000000 --- a/conda/js/src/helpers/schema/toolchain.json +++ /dev/null @@ -1,215 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "toolchain", - "title": "Toolchain descriptor", - "description": "This schema defines the properties of a toolchain", - - "type": "object", - - "properties": { - - "description": { "$ref": "common#/definitions/description" }, - - "datasets": { - "type": "array", - "uniqueItems": true, - "items": { "$ref": "#/definitions/dataset" } - }, - - "blocks": { - "type": "array", - "uniqueItems": true, - "items": { "$ref": "#/definitions/block" } - }, - - "analyzers": { - "type": "array", - "uniqueItems": true, - "items": { "$ref": "#/definitions/analyzer" } - }, - - "connections": { - "type": "array", - "uniqueItems": true, - "items": { "$ref": "#/definitions/connection" } - }, - - "representation": { - - "type": "object", - - "properties": { - - "connections": { - "$ref": "#/definitions/representation/connections" - }, - "blocks": { - "$ref": "#/definitions/representation/blocks" - }, - "channel_colors": { - "$ref": "#/definitions/representation/channel_colors" - } - - }, - - "required": [ - "connections", - "blocks", - "channel_colors" - ], - - "additionalProperties": false - - }, - - "schema_version": { "$ref": "common#/definitions/version" } - - }, - - "required": [ - "datasets", - "blocks", - "analyzers", - "connections", - "representation" - ], - - "additionalProperties": false, - - "definitions": { - - "identifier": { - "type": "string", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_-]*$" - }, - - "dataset": { - "type": "object", - "properties": { - "name": { "$ref": "database#/definitions/identifier" }, - "outputs": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "database#/definitions/identifier" } - } - }, - "required": ["name", "outputs"], - "additionalProperties": false - }, - - "block": { - "type": "object", - "properties": { - "name": { "$ref": "#/definitions/identifier" }, - "synchronized_channel": { - "$ref": "database#/definitions/identifier" - }, - "inputs": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/definitions/identifier" } - }, - "outputs": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/definitions/identifier" } - } - }, - "required": ["name", "synchronized_channel", "inputs", "outputs"], - "additionalProperties": false - }, - - "analyzer": { - "type": "object", - "properties": { - "name": { "$ref": "#/definitions/identifier" }, - "synchronized_channel": { - "$ref": "database#/definitions/identifier" - }, - "inputs": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/definitions/identifier" } - } - }, - "required": ["name", "synchronized_channel", "inputs"], - "additionalProperties": false - }, - - "endpoint": { - "type": "string", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_-]*.[a-zA-Z_][a-zA-Z0-9_-]*$" - }, - - "connection": { - "type": "object", - "properties": { - "from": { "$ref": "#/definitions/endpoint" }, - "to": { "$ref": "#/definitions/endpoint" }, - "channel": { "$ref": "#/definitions/identifier" } - }, - "required": ["from", "to", "channel"], - "additionalProperties": false, - "definitions": { - } - }, - - "representation": { - - "connections": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*.[a-zA-Z_][a-zA-Z0-9_-]*/[a-zA-Z_][a-zA-Z0-9_-]*.[a-zA-Z_][a-zA-Z0-9_-]*$": { - "type": "array", - "items": { - "type": "object", - "properties": { - "col": { "type": "integer" }, - "row": { "type": "integer" } - }, - "required": [ "col", "row" ], - "additionalProperties": false - } - } - }, - "additionalProperties": false - }, - - "blocks": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "type": "object", - "properties": { - "col": { "type": "integer" }, - "row": { "type": "integer" }, - "width": { "type": "integer" }, - "height": { "type": "integer" } - }, - "required": [ "col", "row", "width", "height" ], - "additionalProperties": false - } - }, - "additionalProperties": false - }, - - "channel_colors": { - "type": "object", - "patternProperties": { - "^[a-zA-Z_][a-zA-Z0-9_-]*$": { - "type": "string", - "pattern": "^#[0-9a-fA-F]{6}$" - } - }, - "additionalProperties": false - } - - } - - } - -} diff --git a/conda/js/src/helpers/search.worker.js b/conda/js/src/helpers/search.worker.js deleted file mode 100644 index ac1fed2f..00000000 --- a/conda/js/src/helpers/search.worker.js +++ /dev/null @@ -1,41 +0,0 @@ -// @flow -/* - * Uses Fuse.js to provide a fast & async search provider as a SharedWorker - */ - -import Fuse from 'fuse.js'; - -declare var self: DedicatedWorkerGlobalScope; - -let fuse; -let searchData; - -const updateFuseInstance = ({ data, options }) => { - searchData = data; - fuse = new Fuse(searchData, options); -}; - -const search = str => { - if(fuse && searchData) - return fuse.search(str); - else if(!searchData) - throw new Error(`searchData is not instantiated!`); - else if(!fuse) - throw new Error(`fuse is not instantiated!`); -}; - -self.onmessage = (msg: any) => { - const { type, payload } = msg.data; - switch (type) { - case 'dataChanged': - updateFuseInstance(payload); - break; - case 'search': - const result = search(payload); - self.postMessage(result); - break; - default: - console.error(`SearchWorker got undefined message: ${ type } with payload ${ payload }`); - break; - } -}; diff --git a/conda/js/src/helpers/toolchainTypes.js b/conda/js/src/helpers/toolchainTypes.js deleted file mode 100644 index 9e5c586f..00000000 --- a/conda/js/src/helpers/toolchainTypes.js +++ /dev/null @@ -1,65 +0,0 @@ -// @flow -export type ConnectionType = {| - from: string, - to: string, - channel: string, -|}; - -export type NormalBlock = {| - inputs: string[], - outputs: string[], - synchronized_channel: string, - name: string, -|}; - -export type DatasetBlock = {| - outputs: string[], - name: string, -|}; - -export type AnalyzerBlock = {| - inputs: string[], - synchronized_channel: string, - name: string, -|}; - -export type BlockType = NormalBlock | DatasetBlock | AnalyzerBlock; - -export type BlockSet = 'analyzers' | 'blocks' | 'datasets'; - -export type BlockCoords = {| - x: number, - y: number, - height: number, - width: number, -|}; - - -export type Group = {| - name: string, - blocks: string[], - collapsed: boolean, -|}; - -export type LocationMapEntry = {| - block: BlockCoords, - inputs?: { [string]: BlockCoords }, - outputs?: { [string]: BlockCoords }, -|}; - -export type LocationMap = {| - [string]: LocationMapEntry, -|}; - -export type Contents = {| - description: string, - datasets: DatasetBlock[], - blocks: NormalBlock[], - analyzers: AnalyzerBlock[], - connections: ConnectionType[], - representation: { - blocks: { [string]: BlockCoords }, - channel_colors: { [string]: string }, - connections: { [string]: any[] }, - } -|}; diff --git a/conda/js/src/store/actionTypes.js b/conda/js/src/store/actionTypes.js deleted file mode 100644 index 025b0004..00000000 --- a/conda/js/src/store/actionTypes.js +++ /dev/null @@ -1,65 +0,0 @@ -// @flow -// the action types (constants) are defined here -// if you want to add one, youll need to add the constant string to the ActionType below -// and also add a line for the constant -export type ActionType = 'FETCH_ALL' -| 'SAVE_DATABASE' | 'ADD_DATABASE' | 'DELETE_DATABASE' | 'UPDATE_DATABASE' -| 'SAVE_LIBRARY' | 'ADD_LIBRARY' | 'DELETE_LIBRARY' | 'UPDATE_LIBRARY' -| 'SAVE_DATAFORMAT' | 'ADD_DATAFORMAT' | 'DELETE_DATAFORMAT' | 'UPDATE_DATAFORMAT' -| 'SAVE_ALGORITHM' | 'ADD_ALGORITHM' | 'DELETE_ALGORITHM' | 'UPDATE_ALGORITHM' -| 'SAVE_TOOLCHAIN' | 'ADD_TOOLCHAIN' | 'DELETE_TOOLCHAIN' | 'UPDATE_TOOLCHAIN' -| 'SAVE_EXPERIMENT' | 'ADD_EXPERIMENT' | 'DELETE_EXPERIMENT' | 'UPDATE_EXPERIMENT' -| 'SAVE_PLOTTER' | 'ADD_PLOTTER' | 'DELETE_PLOTTER' | 'UPDATE_PLOTTER' -| 'SAVE_PLOTTERPARAMETER' | 'ADD_PLOTTERPARAMETER' | 'DELETE_PLOTTERPARAMETER' | 'UPDATE_PLOTTERPARAMETER' -| 'SAVE_SETTINGS' | 'UPDATE_SETTINGS' -| 'SAVE_ENVIRONMENTS' -| 'CLEAR_UNSAVED'; - -export const FETCH_ALL: ActionType = 'FETCH_ALL'; - -export const SAVE_DATABASE: ActionType = 'SAVE_DATABASE'; -export const ADD_DATABASE: ActionType = 'ADD_DATABASE'; -export const DELETE_DATABASE: ActionType = 'DELETE_DATABASE'; -export const UPDATE_DATABASE: ActionType = 'UPDATE_DATABASE'; - -export const SAVE_LIBRARY: ActionType = 'SAVE_LIBRARY'; -export const ADD_LIBRARY: ActionType = 'ADD_LIBRARY'; -export const DELETE_LIBRARY: ActionType = 'DELETE_LIBRARY'; -export const UPDATE_LIBRARY: ActionType = 'UPDATE_LIBRARY'; - -export const SAVE_DATAFORMAT: ActionType = 'SAVE_DATAFORMAT'; -export const ADD_DATAFORMAT: ActionType = 'ADD_DATAFORMAT'; -export const DELETE_DATAFORMAT: ActionType = 'DELETE_DATAFORMAT'; -export const UPDATE_DATAFORMAT: ActionType = 'UPDATE_DATAFORMAT'; - -export const SAVE_ALGORITHM: ActionType = 'SAVE_ALGORITHM'; -export const ADD_ALGORITHM: ActionType = 'ADD_ALGORITHM'; -export const DELETE_ALGORITHM: ActionType = 'DELETE_ALGORITHM'; -export const UPDATE_ALGORITHM: ActionType = 'UPDATE_ALGORITHM'; - -export const SAVE_TOOLCHAIN: ActionType = 'SAVE_TOOLCHAIN'; -export const ADD_TOOLCHAIN: ActionType = 'ADD_TOOLCHAIN'; -export const DELETE_TOOLCHAIN: ActionType = 'DELETE_TOOLCHAIN'; -export const UPDATE_TOOLCHAIN: ActionType = 'UPDATE_TOOLCHAIN'; - -export const SAVE_EXPERIMENT: ActionType = 'SAVE_EXPERIMENT'; -export const ADD_EXPERIMENT: ActionType = 'ADD_EXPERIMENT'; -export const DELETE_EXPERIMENT: ActionType = 'DELETE_EXPERIMENT'; -export const UPDATE_EXPERIMENT: ActionType = 'UPDATE_EXPERIMENT'; - -export const SAVE_PLOTTER: ActionType = 'SAVE_PLOTTER'; -export const ADD_PLOTTER: ActionType = 'ADD_PLOTTER'; -export const DELETE_PLOTTER: ActionType = 'DELETE_PLOTTER'; -export const UPDATE_PLOTTER: ActionType = 'UPDATE_PLOTTER'; - -export const SAVE_PLOTTERPARAMETER: ActionType = 'SAVE_PLOTTERPARAMETER'; -export const ADD_PLOTTERPARAMETER: ActionType = 'ADD_PLOTTERPARAMETER'; -export const DELETE_PLOTTERPARAMETER: ActionType = 'DELETE_PLOTTERPARAMETER'; -export const UPDATE_PLOTTERPARAMETER: ActionType = 'UPDATE_PLOTTERPARAMETER'; - -export const SAVE_ENVIRONMENTS: ActionType = 'SAVE_ENVIRONMENTS'; - -export const SAVE_SETTINGS: ActionType = 'SAVE_SETTINGS'; -export const UPDATE_SETTINGS: ActionType = 'UPDATE_SETTINGS'; - -export const CLEAR_UNSAVED: ActionType = 'CLEAR_UNSAVED'; diff --git a/conda/js/src/store/actions.js b/conda/js/src/store/actions.js deleted file mode 100644 index c6cc7510..00000000 --- a/conda/js/src/store/actions.js +++ /dev/null @@ -1,180 +0,0 @@ -// @flow -/* Actions for Redux - * all the actions for redux are defined here - * some actions are actually async action creators for async stuff (API calls) - * most are pretty simple and tied to a specific BEAT entity - * each entity has the same actions available, allowing lots of templating stuff - * these actions specify a type, using the constants in the ActionTypes -*/ -import type { - ActionType, -} from './actionTypes'; - -import * as Types from './actionTypes.js'; -import type { Dispatch } from 'redux'; -import { genModuleApiFuncs } from '@helpers/api'; -import { BEAT_ENTITIES } from '@helpers/beat'; - -import type { BeatEntity, BeatObject, BeatSettings, BeatEnvironment } from '@helpers/beat'; - -export type Action = {| - type: ActionType, - payload: any, - error?: boolean, - meta?: mixed, -|}; - -export type ActionCreator = (any, any) => Action; - -export type ActionThunkCreator = (any) => (dispatch: Dispatch<*>) => Promise<*>; - -// helper to sort of flatten api response objects to arrays -const objToArr = (data: any): any[] => { - if(!data) - throw new Error(`Invalid data "${ data }"`); - - if(Array.isArray(data)) - return data; - return Object.entries(data) - .map(([k, obj]) => objToArr(obj)) - .reduce((a: any[], objs: any[]) => [...a, ...objs], []) - ; -}; - -export const fetchAllObjects: ActionThunkCreator = () => async (dispatch: Dispatch<*>) => { - //console.log(`fetchAllObjects`); - const getFuncs = [...BEAT_ENTITIES].map(e => genModuleApiFuncs(e).get); - const jsons = await Promise.all(getFuncs.map(async (get): Promise<*> => get())); - const arrs = jsons.map((j, i, js) => objToArr(j)); - - //dispatch(settingsSave(arrs[8])); - - dispatch(databaseSave(arrs[0])); - dispatch(librarySave(arrs[1])); - dispatch(dataformatSave(arrs[2])); - dispatch(algorithmSave(arrs[3])); - dispatch(toolchainSave(arrs[4])); - dispatch(experimentSave(arrs[5])); - dispatch(plotterSave(arrs[6])); - dispatch(plotterparameterSave(arrs[7])); - dispatch(clearUnsaved()); - - const settingsGet = genModuleApiFuncs('settings').get; - const settingsJson = await settingsGet(); - dispatch(settingsSave(settingsJson)); - - const envGet = genModuleApiFuncs('environments').get; - const envJson = await envGet(); - dispatch(environmentsSave(envJson)); -}; - -export const deleteObject = (entity: BeatEntity, obj: BeatObject): ActionThunkCreator => () => async (dispatch: Dispatch<*>) => { - const del = genModuleApiFuncs(entity).delete; - const res = await del(obj); - - switch(entity){ - case 'database': - dispatch(databaseDelete(obj)); - break; - case 'library': - dispatch(libraryDelete(obj)); - break; - case 'dataformat': - dispatch(dataformatDelete(obj)); - break; - case 'algorithm': - dispatch(algorithmDelete(obj)); - break; - case 'toolchain': - dispatch(toolchainDelete(obj)); - break; - case 'experiment': - dispatch(experimentDelete(obj)); - case 'plotter': - dispatch(plotterDelete(obj)); - case 'plotterparameter': - dispatch(plotterparameterDelete(obj)); - break; - } -}; - -export const createObject = (entity: BeatEntity, obj: BeatObject, copiedObjName?: string): ActionThunkCreator => () => async (dispatch: Dispatch<*>) => { - const post = genModuleApiFuncs(entity).post; - const payload = { - obj, - copiedObjName: copiedObjName || '', - }; - const res = await post(payload); - - switch(entity){ - case 'database': - dispatch(databaseAdd(obj)); - break; - case 'library': - dispatch(libraryAdd(obj)); - break; - case 'dataformat': - dispatch(dataformatAdd(obj)); - break; - case 'algorithm': - dispatch(algorithmAdd(obj)); - break; - case 'toolchain': - dispatch(toolchainAdd(obj)); - break; - case 'experiment': - dispatch(experimentAdd(obj)); - case 'plotter': - dispatch(plotterAdd(obj)); - case 'plotterparameter': - dispatch(plotterparameterAdd(obj)); - break; - } -}; - -export const databaseSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_DATABASE, payload: objs, }); -const databaseAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_DATABASE, payload: obj, }); -const databaseDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_DATABASE, payload: obj, }); -export const databaseUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_DATABASE, payload: {oldName, obj}, }); - -export const librarySave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_LIBRARY, payload: objs, }); -const libraryAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_LIBRARY, payload: obj, }); -const libraryDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_LIBRARY, payload: obj, }); -export const libraryUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_LIBRARY, payload: {oldName, obj}, }); - -export const dataformatSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_DATAFORMAT, payload: objs, }); -const dataformatAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_DATAFORMAT, payload: obj, }); -const dataformatDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_DATAFORMAT, payload: obj, }); -export const dataformatUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_DATAFORMAT, payload: {oldName, obj}, }); - -export const algorithmSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_ALGORITHM, payload: objs, }); -const algorithmAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_ALGORITHM, payload: obj, }); -const algorithmDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_ALGORITHM, payload: obj, }); -export const algorithmUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_ALGORITHM, payload: {oldName, obj}, }); - -export const toolchainSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_TOOLCHAIN, payload: objs, }); -const toolchainAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_TOOLCHAIN, payload: obj, }); -const toolchainDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_TOOLCHAIN, payload: obj, }); -export const toolchainUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_TOOLCHAIN, payload: {oldName, obj}, }); - -export const experimentSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_EXPERIMENT, payload: objs, }); -const experimentAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_EXPERIMENT, payload: obj, }); -const experimentDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_EXPERIMENT, payload: obj, }); -export const experimentUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_EXPERIMENT, payload: {oldName, obj}, }); - -export const plotterSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_PLOTTER, payload: objs, }); -const plotterAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_PLOTTER, payload: obj, }); -const plotterDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_PLOTTER, payload: obj, }); -export const plotterUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_PLOTTER, payload: {oldName, obj}, }); - -export const plotterparameterSave: ActionCreator = (objs: BeatObject[]): Action => ({ type: Types.SAVE_PLOTTERPARAMETER, payload: objs, }); -const plotterparameterAdd: ActionCreator = (obj: BeatObject): Action => ({ type: Types.ADD_PLOTTERPARAMETER, payload: obj, }); -const plotterparameterDelete: ActionCreator = (obj: BeatObject): Action => ({ type: Types.DELETE_PLOTTERPARAMETER, payload: obj, }); -export const plotterparameterUpdate: ActionCreator = (oldName: string, obj: BeatObject): Action => ({ type: Types.UPDATE_PLOTTERPARAMETER, payload: {oldName, obj}, }); - -export const environmentsSave: ActionCreator = (objs: BeatEnvironment[]): Action => ({ type: Types.SAVE_ENVIRONMENTS, payload: objs, }); - -export const settingsSave: ActionCreator = (obj: BeatSettings): Action => ({ type: Types.SAVE_SETTINGS, payload: obj, }); -export const settingsUpdate: ActionCreator = (obj: BeatSettings): Action => ({ type: Types.UPDATE_SETTINGS, payload: obj, }); - -export const clearUnsaved: ActionCreator = (): Action => ({ type: Types.CLEAR_UNSAVED, payload: null, }); diff --git a/conda/js/src/store/index.js b/conda/js/src/store/index.js deleted file mode 100644 index 78296f71..00000000 --- a/conda/js/src/store/index.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import createStore from './store'; -import { fetchAllObjects } from './actions.js'; - -const store = createStore(); - -export default store; - -store.dispatch(fetchAllObjects()); diff --git a/conda/js/src/store/reducers.js b/conda/js/src/store/reducers.js deleted file mode 100644 index 9e8ca439..00000000 --- a/conda/js/src/store/reducers.js +++ /dev/null @@ -1,129 +0,0 @@ -// @flow -/* Reducers for Redux - * all the reducers are here. - * since most actions are similar (all entities have the same basic actions available) there's alot of templating that happens. -*/ -import { combineReducers } from 'redux'; - -import type { Action } from './actions.js'; - -import type { BeatObject, BeatSettings, BeatEnvironment } from '@helpers/beat.js'; - -export type State = {| - +database: BeatObject[], - +library: BeatObject[], - +dataformat: BeatObject[], - +algorithm: BeatObject[], - +toolchain: BeatObject[], - +experiment: BeatObject[], - +plotter: BeatObject[], - +plotterparameter: BeatObject[], - +settings: BeatSettings, - +environments: BeatEnvironment[], - +unsaved: boolean, -|}; - -export type Reducer = (state: State, action: Action) => State; - -const initialState: State = { - database: [], - library: [], - dataformat: [], - algorithm: [], - toolchain: [], - experiment: [], - plotter: [], - plotterparameter: [], - settings: { - prefix: '', - }, - environments: [], - unsaved: false, -}; - -const saveFunc = (state: BeatObject[], objs: BeatObject[]): BeatObject[] => [...objs].sort((a, b) => a.name > b.name ? 1 : -1); -const addFunc = (state: BeatObject[], obj: BeatObject): BeatObject[] => [obj, ...state]; -const deleteFunc = (state: BeatObject[], obj: BeatObject): BeatObject[] => state.filter(o => o.name !== obj.name); -const updateFunc = (state: BeatObject[], { oldName, obj }): BeatObject[] => state.map(o => o.name === oldName ? obj : o); - -const entityFunc = (state: BeatObject[], actionType: string, payload: any): BeatObject[] => { - let func; - switch(true){ - case (/^SAVE_/.test(actionType)): - func = saveFunc; - break; - case (/^ADD_/.test(actionType)): - func = addFunc; - break; - case (/^DELETE_/.test(actionType)): - func = deleteFunc; - break; - case (/^UPDATE_/.test(actionType)): - func = updateFunc; - break; - default: - throw new Error(`Invalid actionType "${ actionType }"`); - } - - return func(state, payload); -}; - -const database = (state: BeatObject[] = [], action: Action) => action.type.endsWith('DATABASE') ? entityFunc(state, action.type, action.payload) : state; -const library = (state: BeatObject[] = [], action: Action) => action.type.endsWith('LIBRARY') ? entityFunc(state, action.type, action.payload) : state; -const dataformat = (state: BeatObject[] = [], action: Action) => action.type.endsWith('DATAFORMAT') ? entityFunc(state, action.type, action.payload) : state; -const algorithm = (state: BeatObject[] = [], action: Action) => action.type.endsWith('ALGORITHM') ? entityFunc(state, action.type, action.payload) : state; -const toolchain = (state: BeatObject[] = [], action: Action) => action.type.endsWith('TOOLCHAIN') ? entityFunc(state, action.type, action.payload) : state; -const experiment = (state: BeatObject[] = [], action: Action) => action.type.endsWith('EXPERIMENT') ? entityFunc(state, action.type, action.payload) : state; -const plotter = (state: BeatObject[] = [], action: Action) => action.type.endsWith('PLOTTER') ? entityFunc(state, action.type, action.payload) : state; -const plotterparameter = (state: BeatObject[] = [], action: Action) => action.type.endsWith('PLOTTERPARAMETER') ? entityFunc(state, action.type, action.payload) : state; -const settings = (state: BeatSettings = {prefix: ''}, action: Action) => { - if(!action.type.endsWith('SETTINGS')) - return state; - const {type, payload} = action; - switch(type){ - case 'UPDATE_SETTINGS': - return { - ...state, - ...payload, - }; - case 'SAVE_SETTINGS': - return { - ...payload - }; - default: - throw new Error(`Invalid actionType "${ type }"`); - } -}; -const environments = (state: BeatEnvironment[] = [], action: Action) => { - if(!action.type.endsWith('ENVIRONMENTS')) - return state; - const {type, payload} = action; - switch(type){ - case 'SAVE_ENVIRONMENTS': - return payload; - default: - throw new Error(`Invalid actionType "${ type }"`); - } -}; -const unsaved = (state: boolean, action: Action) => { - if(action.type === 'CLEAR_UNSAVED') - return false; - else if(!action.type.startsWith('SAVE_')){ - return true; - } - return state; -}; - -export default combineReducers({ - database, - library, - dataformat, - algorithm, - toolchain, - experiment, - plotter, - plotterparameter, - settings, - environments, - unsaved, -}); diff --git a/conda/js/src/store/selectors.js b/conda/js/src/store/selectors.js deleted file mode 100644 index 7277cbb1..00000000 --- a/conda/js/src/store/selectors.js +++ /dev/null @@ -1,102 +0,0 @@ -// @flow -/* State selectors for our Redux store via Reselect - * basically a bunch of memoized shortcuts to certain state/derived state -*/ -import { createSelector } from 'reselect'; -import type { State } from './reducers.js'; -import { getTcFromExpName } from '@helpers/beat'; - -import { getValidDatabaseObj } from '@helpers/beat'; -import { getValidDataformatObj } from '@helpers/beat'; -import { getValidLibraryObj } from '@helpers/beat'; -import { getValidAlgorithmObj } from '@helpers/beat'; -import { getValidToolchainObj } from '@helpers/beat'; -import { getValidExperimentObj } from '@helpers/beat'; -import { getValidPlotterObj } from '@helpers/beat'; -import { getValidPlotterparameterObj } from '@helpers/beat'; - -const getObjs = { - database: getValidDatabaseObj, - dataformat: getValidDataformatObj, - library: getValidLibraryObj, - algorithm: getValidAlgorithmObj, - toolchain: getValidToolchainObj, - experiment: getValidExperimentObj, - plotter: getValidPlotterObj, - plotterparameter: getValidPlotterparameterObj, -}; - -export const databaseGet = (state: State) => state.database.map(o => getObjs['database'](o)); -export const dataformatGet = (state: State) => state.dataformat.map(o => getObjs['dataformat'](o)); -export const libraryGet = (state: State) => state.library.map(o => getObjs['library'](o)); -export const algorithmGet = (state: State) => state.algorithm.map(o => getObjs['algorithm'](o)); -export const toolchainGet = (state: State) => state.toolchain.map(o => getObjs['toolchain'](o)); -export const experimentGet = (state: State) => createSelector( - state => state.experiment, - algorithmGet, - toolchainGet, - (exps, algs, tcs) => exps.map(o => { - const tcName = getTcFromExpName(o.name); - const tc = tcs.find(tc => tc.name === tcName); - if(!tc) - throw new Error(`Could not find toolchain for experiment "${ o.name }`); - - return getObjs['experiment'](o, tc, algs); - }) -)(state); -export const plotterGet = (state: State) => state.plotter.map(o => getObjs['plotter'](o)); -export const plotterparameterGet = (state: State) => state.plotterparameter.map(o => getObjs['plotterparameter'](o)); -export const settingsGet = (state: State) => state.settings; -export const environmentsGet = (state: State) => state.environments; -export const unsavedGet = (state: State) => state.unsaved; - -export type FlattenedDatabaseEntry = {| - database: string, - protocol: string, - protocolTemplate: string, - set: string, - setTemplate: string, - outputs: { - [string]: string, - }, -|}; - -export const databaseProtocols: ((state: State) => any[]) = createSelector( - databaseGet, - (dbs) => dbs.map((db, i) => - db.contents.protocols ? db.contents.protocols.map(p => - ({ - ...p, - database: db.name, - }) - ) : [] - ).reduce((a, ps) => [...a, ...ps], []) -); - -export const flattenedDatabases: ((state: State) => FlattenedDatabaseEntry[]) = createSelector( - databaseGet, - (dbs) => dbs.map((db, i) => - db.contents.protocols ? db.contents.protocols.map(p => - p.sets.map(s => - ({ - database: dbs[i].name, - protocol: p.name, - protocolTemplate: p.template, - set: s.name, - setTemplate: s.template, - outputs: s.outputs, - }) - ) - ).reduce((a, ss) => [...a, ...ss], []) : [] - ).reduce((a, ss) => [...a, ...ss], []) -); - -export const normalBlocks = createSelector( - algorithmGet, - (alg) => alg.filter(alg => alg.contents.results === undefined) -); - -export const analyzerBlocks = createSelector( - algorithmGet, - (alg) => alg.filter(alg => alg.contents.results !== undefined) -); diff --git a/conda/js/src/store/store.js b/conda/js/src/store/store.js deleted file mode 100644 index 3c4fc9bd..00000000 --- a/conda/js/src/store/store.js +++ /dev/null @@ -1,32 +0,0 @@ -// @flow -// builds the store and fetches the objects -import { createStore, applyMiddleware, compose } from 'redux'; -import reducer from './reducers'; -import type { State } from './reducers'; -import thunk from 'redux-thunk'; - -const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; - -const createStoreFunc = (preloadedState?: State) => { - return preloadedState ? - createStore( - reducer, - preloadedState, - composeEnhancers( - applyMiddleware( - thunk, - ), - ), - ) - : - createStore( - reducer, - composeEnhancers( - applyMiddleware( - thunk, - ), - ), - ); -}; - -export default createStoreFunc; diff --git a/conda/js/test/index.js b/conda/js/test/index.js deleted file mode 100644 index d68aa5e7..00000000 --- a/conda/js/test/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import { configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -import chai from 'chai'; -import chaiEnzyme from 'chai-enzyme'; -configure({ adapter: new Adapter() }); -chai.use(chaiEnzyme()); -import 'bootstrap/dist/css/bootstrap.min.css'; - -function importAll (r) { - r.keys().forEach(r); -} - -export const spies = []; -afterEach(function masterAfterEach() { - while(spies.length > 0){ - const spy = spies.pop(); - if(spy && spy.restore) - spy.restore(); - } -}); - -// require all test files using special Webpack feature -// https://webpack.js.org/guides/dependency-management/#require-context -const componentTestsContext = require.context('../src/components', true, /\.spec.js(x)?$/); -const helperTestsContext = require.context('../src/helpers', true, /\.spec.js(x)?$/); -const storeTestsContext = require.context('../src/store', true, /\.spec.js(x)?$/); -const e2eTestsContext = require.context('.', true, /\.spec.js(x)?$/); - -importAll(componentTestsContext); -importAll(helperTestsContext); -importAll(storeTestsContext); -importAll(e2eTestsContext); diff --git a/conda/js/test/selenium_test.js b/conda/js/test/selenium_test.js deleted file mode 100644 index 31a49d7b..00000000 --- a/conda/js/test/selenium_test.js +++ /dev/null @@ -1,17 +0,0 @@ -const {Builder, By, Key, until} = require('selenium-webdriver'); -const firefox = require('selenium-webdriver/firefox'); - -const options = new firefox.Options(); -options.addArguments('-headless'); - -(async function example() { - let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build(); - try { - await driver.get('http://www.google.com/ncr'); - await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN); - await driver.wait(until.titleIs('webdriver - Google Search'), 10000); - console.log('it worked!'); - } finally { - await driver.quit(); - } -})(); diff --git a/conda/js/test/selenium_tutorial_test.js b/conda/js/test/selenium_tutorial_test.js deleted file mode 100644 index df6170de..00000000 --- a/conda/js/test/selenium_tutorial_test.js +++ /dev/null @@ -1,380 +0,0 @@ -// must have the rest server running with at least the contents of the tutorial prefix -const {Builder, By, Key, until} = require('selenium-webdriver'); -const firefox = require('selenium-webdriver/firefox'); - -// window size we're testing with -const winX = 1920, winY = 1080; -const options = new firefox.Options(); -// sometimes, selenium will hang forever in the middle of the test if the test is ran headlessly -// if you encounter this issue, comment out this headless flag -// (it doesn't seem to ever hang when running non-headlessly) -// the test shouldnt take more than a minute-ish either way -options.addArguments('-headless'); -options.addArguments(`--window-size=${ winX },${ winY }`); - -(async function example() { - let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build(); - await driver.manage().window().setRect({x: 0, y: 0, width: winX, height: winY}); - try { - await driver.get('http://localhost:9101/'); - - /************************************************************** - * MEANS EXP - */ - - // navigate to exp list - await driver.findElement(By.linkText('experiments')).click(); - //.sendKeys('webdriver', Key.RETURN); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search experiments..."]'), 2000)); - - // click the clone button next to test/test/iris/1/iris - let eLink = await driver.findElement(By.linkText('test/test/iris/1/iris')); - await eLink.findElement(By.xpath('../..')).findElement(By.css('button.btn-outline-success')).click(); - await driver.wait(until.elementLocated(By.css('.modal')), 2000); - - // make new exp - let eUser = await driver.findElement(By.css('input[placeholder="Experiment user..."]')); - await eUser.clear(); - await eUser.sendKeys('selenium'); - let eName = driver.findElement(By.css('input[placeholder="Experiment name..."]')); - await eName.clear(); - await eName.sendKeys('means'); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-primary')).click(); - await driver.wait(until.elementLocated(By.linkText('selenium/test/iris/1/means')), 2000); - await driver.sleep(1000); - - // go to new exp - await driver.findElement(By.linkText('selenium/test/iris/1/means')).click(); - await driver.wait(until.elementLocated(By.css('div.experimentEditor')), 2000); - - // click on training_alg block - await driver.findElement(By.css('rect#block_training_alg')).click(); - await driver.wait(until.elementLocated(By.css('div.block_training_alg')), 2000); - - // set the algorithm to the new one - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="test/means_training/1"]')).click(); - - // do same for testing_alg block - await driver.findElement(By.css('rect#block_testing_alg')).click(); - await driver.wait(until.elementLocated(By.css('div.block_testing_alg')), 2000); - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="test/means_testing/1"]')).click(); - - // make sure the exp is still valid - await driver.wait(until.elementLocated(By.css('.badge-success')), 2000); - - // save exp - await driver.findElement(By.css('div.experimentEditor > div.d-flex > button.btn-outline-secondary')).click(); - await driver.sleep(1000); - - /************************************************************** - * CLEANUP - */ - - // go back and delete exp - await driver.findElement(By.linkText('experiments')).click(); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search experiments..."]'), 2000)); - eLink = await driver.findElement(By.linkText('selenium/test/iris/1/means')); - await eLink.findElement(By.xpath('../..')).findElement(By.css('button.btn-outline-danger')).click(); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-danger')).click(); - await driver.sleep(1000); - - /************************************************************** - * ADVANCED IRIS TOOLCHAIN - */ - - // navigate to tc list - await driver.findElement(By.linkText('toolchains')).click(); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search toolchains..."]'), 2000)); - - // click the clone button next to test/iris/1 - let tLink = await driver.findElement(By.linkText('test/iris/1')); - await tLink.findElement(By.xpath('../..')).findElement(By.css('button.btn-outline-success + button.btn-outline-success')).click(); - await driver.wait(until.elementLocated(By.css('.modal')), 2000); - - // make new tc - const tUser = await driver.findElement(By.css('input[placeholder="Toolchain user..."]')); - await tUser.clear(); - await tUser.sendKeys('selenium'); - const tName = driver.findElement(By.css('input[placeholder="New toolchain name..."]')); - await tName.clear(); - await tName.sendKeys('iris_advanced'); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-primary')).click(); - await driver.wait(until.elementLocated(By.linkText('selenium/iris_advanced/1')), 2000); - await driver.sleep(1000); - - // go to new tc - await driver.findElement(By.linkText('selenium/iris_advanced/1')).click(); - await driver.wait(until.elementLocated(By.css('div.toolchainEditor')), 2000); - - // delete conn between training_data.measurements & training_alg.measurements - let rcEl = await driver.findElement(By.css('#\\#training_data-measurements-training_alg-measurements')); - await driver.actions().contextClick(rcEl).perform(); - await driver.sleep(1000); - await driver.findElement(By.css('nav.react-contextmenu--visible > div')).click(); - - // delete conn between testing_data.measurements & testing_alg.measurements - rcEl = await driver.findElement(By.css('#\\#testing_data-measurements-testing_alg-measurements')); - await driver.actions().contextClick(rcEl).perform(); - await driver.sleep(1000); - await driver.findElement(By.css('nav.react-contextmenu--visible > div')).click(); - - // add training preprocessor block way below the rest of the toolchain - let originEl = await driver.findElement(By.css('#block_testing_data')); - await driver.actions().move({x: 100, y: 100, origin: originEl}).pause(500).contextClick().perform(); - await driver.sleep(1000); - await driver.findElement(By.css('nav.react-contextmenu--visible > div:first-child')).click(); - - // edit training preprocessor - await driver.findElement(By.css('#block_block')).click(); - await driver.sleep(1000); - // name - let tbName = await driver.findElement(By.css('#tcModalInitFocus')); - tbName.clear(); - tbName.sendKeys('pre_training'); - // input - await driver.findElement(By.css('.modal-body .btn-secondary')).click(); - let tbiName = await driver.findElement(By.css('.modal-body > form > div.row input')); - await tbiName.clear(); - await tbiName.sendKeys('measurements'); - // output - await driver.findElement(By.css('.modal-body .col-sm-6 + .col-sm-6 .btn-secondary')).click(); - let tboName = await driver.findElement(By.css('.modal-body > form > div.row .col-sm-6 + .col-sm-6 input')); - await tboName.clear(); - await tboName.sendKeys('measurements'); - await driver.sleep(1000); - //close - await driver.findElement(By.css('.modal button.close')).click(); - await driver.sleep(1000); - - // copy the block - rcEl = await driver.findElement(By.css('#block_pre_training')); - await driver.actions().contextClick(rcEl).perform(); - await driver.sleep(1000); - await driver.findElement(By.css('nav.react-contextmenu--visible > div + div')).click(); - - // paste testing preprocessor block way below the rest of the toolchain - originEl = await driver.findElement(By.css('#block_pre_training')); - await driver.actions().move({x: 150, origin: originEl}).pause(500).contextClick().perform(); - await driver.sleep(1000); - await driver.findElement(By.css('nav.react-contextmenu--visible > div:first-child')).click(); - - // unselect pasted block - await driver.actions().move({y: 200, origin: originEl}).pause(500).click().pause(500).perform(); - - // edit the block name - await driver.findElement(By.css('#block_pre_training0')).click(); - await driver.sleep(1000); - tbName = await driver.findElement(By.css('#tcModalInitFocus')); - await tbName.clear(); - await tbName.sendKeys('pre_testing'); - await driver.sleep(1000); - //close - await driver.findElement(By.css('.modal button.close')).click(); - await driver.sleep(1000); - - // connect pre_training to rest of tc - // data to pre - let fromBox = await driver.findElement(By.css('rect#training_data-output-measurements')); - let toBox = await driver.findElement(By.css('rect#pre_training-input-measurements')); - await driver.actions().dragAndDrop(fromBox, toBox).pause(200).perform(); - // pre to alg - fromBox = await driver.findElement(By.css('rect#pre_training-output-measurements')); - toBox = await driver.findElement(By.css('rect#training_alg-input-measurements')); - await driver.actions().dragAndDrop(fromBox, toBox).pause(200).perform(); - - // connect pre_testing to rest of tc - // data to pre - fromBox = await driver.findElement(By.css('rect#testing_data-output-measurements')); - toBox = await driver.findElement(By.css('rect#pre_testing-input-measurements')); - await driver.actions().dragAndDrop(fromBox, toBox).pause(500).perform(); - // pre to alg - fromBox = await driver.findElement(By.css('rect#pre_testing-output-measurements')); - toBox = await driver.findElement(By.css('rect#testing_alg-input-measurements')); - await driver.actions().dragAndDrop(fromBox, toBox).pause(500).perform(); - - // fix the channel on pre_training - await driver.findElement(By.css('#block_pre_training')).click(); - await driver.sleep(1000); - await driver.findElement(By.css('.modal-body select.form-control')).click(); - await driver.findElement(By.css('.modal-body option[value="training_data"]')).click(); - await driver.sleep(500); - await driver.findElement(By.css('.modal button.close')).click(); - await driver.sleep(1000); - - // layout the tc - await driver.findElement(By.xpath('//button[contains(.,"Layout")]')).click(); - // needs to communicate w graphviz, give it some time - await driver.sleep(5000); - - // make sure the tc is still valid - await driver.wait(until.elementLocated(By.css('.badge-success')), 2000); - - // save - await driver.findElement(By.css('div.toolchainEditor > div.d-flex > button.btn-outline-secondary')).click(); - await driver.sleep(1000); - - /************************************************************** - * CLEANUP - */ - - /************************************************************** - * ADVANCED IRIS PREPROCESSOR ALGORITHM - */ - - // navigate to alg list - await driver.findElement(By.linkText('algorithms')).click(); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search algorithms..."]'), 2000)); - - // click the new button - await driver.findElement(By.css('.dropdown + div > .btn-outline-success')).click(); - await driver.wait(until.elementLocated(By.css('.modal')), 2000); - - // make new alg - const aUser = await driver.findElement(By.css('input[placeholder="Algorithm user..."]')); - await aUser.clear(); - await aUser.sendKeys('selenium'); - const aName = driver.findElement(By.css('input[placeholder="New algorithm name..."]')); - await aName.clear(); - await aName.sendKeys('iris_preprocessor'); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-primary')).click(); - await driver.wait(until.elementLocated(By.linkText('selenium/iris_preprocessor/1')), 2000); - await driver.sleep(1000); - - // go to new alg - await driver.findElement(By.linkText('selenium/iris_preprocessor/1')).click(); - await driver.wait(until.elementLocated(By.css('ul.nav-fill.nav.nav-tabs')), 2000); - - // add an input & output - await driver.findElement(By.css('#newInputBtn')).click(); - await driver.findElement(By.css('#newOutputBtn')).click(); - - // change input & output name to "measurements" - let aiDiv = await driver.findElement(By.css('#newInputBtn')).findElement(By.xpath('..')).findElement(By.css('div:first-child')); - let aoDiv = await driver.findElement(By.css('#newOutputBtn')).findElement(By.xpath('..')).findElement(By.css('div:first-child')); - let aiName = await aiDiv.findElement(By.css('input')); - await aiName.clear(); - await aiName.sendKeys('measurements'); - let aoName = await aoDiv.findElement(By.css('input')); - await aoName.clear(); - await aoName.sendKeys('measurements'); - - // select type system/array_1d_floats/1 - await aiDiv.findElement(By.css('select.custom-select')).click(); - await aiDiv.findElement(By.css('select.custom-select option[value="system/array_1d_floats/1"]')).click(); - await aoDiv.findElement(By.css('select.custom-select')).click(); - await aoDiv.findElement(By.css('select.custom-select option[value="system/array_1d_floats/1"]')).click(); - await driver.sleep(500); - - // save - await driver.findElement(By.css('.tab-pane.active > div > div.d-flex > button.btn-outline-secondary')).click(); - await driver.sleep(1000); - - /************************************************************** - * ADVANCED IRIS EXPERIMENT - */ - - // navigate to exp list - await driver.findElement(By.linkText('experiments')).click(); - //.sendKeys('webdriver', Key.RETURN); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search experiments..."]'), 2000)); - - // click the new button - await driver.findElement(By.css('.dropdown + div > .btn-outline-success')).click(); - await driver.wait(until.elementLocated(By.css('.modal')), 2000); - - // make new exp - eUser = await driver.findElement(By.css('input[placeholder="Experiment user..."]')); - await eUser.clear(); - await eUser.sendKeys('selenium'); - let eTc = await driver.findElement(By.css('.modal select')); - await eTc.click(); - await eTc.findElement(By.css('select option[value="selenium/iris_advanced/1"]')).click(); - eName = driver.findElement(By.css('input[placeholder="Experiment name..."]')); - await eName.clear(); - await eName.sendKeys('iris'); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-primary')).click(); - await driver.wait(until.elementLocated(By.linkText('selenium/selenium/iris_advanced/1/iris')), 2000); - await driver.sleep(1000); - - // go to new exp - await driver.findElement(By.linkText('selenium/selenium/iris_advanced/1/iris')).click(); - await driver.wait(until.elementLocated(By.css('div.experimentEditor')), 2000); - - // assign dataset protocol - await driver.findElement(By.css('.datasets select')).click(); - await driver.findElement(By.css(`.datasets select option[value='{"testing_data":{"database":"iris/1","protocol":"Main","set":"training"},"training_data":{"database":"iris/1","protocol":"Main","set":"testing"}}']`)).click(); - - // pre_training block - await driver.findElement(By.css('rect#block_pre_training')).click(); - await driver.wait(until.elementLocated(By.css('div.block_pre_training')), 2000); - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="selenium/iris_preprocessor/1"]')).click(); - - // pre_testing block - await driver.findElement(By.css('rect#block_pre_testing')).click(); - await driver.wait(until.elementLocated(By.css('div.block_pre_testing')), 2000); - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="selenium/iris_preprocessor/1"]')).click(); - - // training_alg block - await driver.findElement(By.css('rect#block_training_alg')).click(); - await driver.wait(until.elementLocated(By.css('div.block_training_alg')), 2000); - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="test/iris_training/1"]')).click(); - - // testing_alg block - await driver.findElement(By.css('rect#block_testing_alg')).click(); - await driver.wait(until.elementLocated(By.css('div.block_testing_alg')), 2000); - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="test/iris_testing/1"]')).click(); - - // analyzer block - await driver.findElement(By.css('rect#block_analyzer')).click(); - await driver.wait(until.elementLocated(By.css('div.block_analyzer')), 2000); - await driver.findElement(By.css('select.custom-select')).click(); - await driver.findElement(By.css('select.custom-select option[value="test/iris_analyzer/1"]')).click(); - - // make sure the exp is still valid - await driver.wait(until.elementLocated(By.css('.badge-success')), 2000); - - // save exp - await driver.findElement(By.css('div.experimentEditor > div.d-flex > button.btn-outline-secondary')).click(); - await driver.sleep(1000); - - /************************************************************** - * CLEANUP - */ - - // go back and delete toolchain (which also deletes the associated experiment) - await driver.findElement(By.linkText('toolchains')).click(); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search toolchains..."]'), 2000)); - tLink = await driver.findElement(By.linkText('selenium/iris_advanced/1')); - await tLink.findElement(By.xpath('../..')).findElement(By.css('button.btn-outline-danger')).click(); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-danger')).click(); - await driver.sleep(1000); - - // go back and delete algorithm - await driver.findElement(By.linkText('algorithms')).click(); - await driver.wait(until.elementLocated(By.css('input[placeholder="Search algorithms..."]'), 2000)); - tLink = await driver.findElement(By.linkText('selenium/iris_preprocessor/1')); - await tLink.findElement(By.xpath('../..')).findElement(By.css('button.btn-outline-danger')).click(); - await driver.sleep(1000); - await driver.findElement(By.css('.modal button.btn-danger')).click(); - await driver.sleep(1000); - - console.log('selenium tests finished successfully!'); - } catch(e) { - console.log('selenium tests failed!'); - console.error(e); - } finally { - await driver.quit(); - } -})(); diff --git a/conda/js/test/test_algs.json b/conda/js/test/test_algs.json deleted file mode 100644 index 3a41206a..00000000 --- a/conda/js/test/test_algs.json +++ /dev/null @@ -1,1290 +0,0 @@ -[ - { - "name": "test/iris_preprocessor/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "measurements": { - "type": "system/array_1d_floats/1" - } - }, - "name": "group", - "outputs": { - "measurements": { - "type": "system/array_1d_floats/1" - } - } - } - ], - "description": "Rounds each measurement in an Iris dataset sample to the nearest integer", - "language": "python", - "splittable": false - } - }, - { - "name": "test/iris_testing/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "measurements": { - "type": "system/array_1d_floats/1" - } - }, - "name": "group", - "outputs": { - "scores": { - "type": "system/float/1" - } - } - }, - { - "inputs": { - "lda_machine": { - "type": "tutorial/linear_machine/1" - } - }, - "name": "group0" - } - ], - "description": "", - "language": "python", - "splittable": false - } - }, - { - "name": "test/iris_training/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "measurements": { - "type": "system/array_1d_floats/1" - }, - "species": { - "type": "system/text/1" - } - }, - "name": "group", - "outputs": { - "lda_machine": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "description": "", - "language": "python", - "splittable": false - } - }, - { - "name": "test/linear_machine_projection/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "id": { - "type": "system/uint64/1" - }, - "image": { - "type": "system/array_2d_uint8/1" - } - }, - "name": "main", - "outputs": { - "projections": { - "type": "system/array_2d_floats/1" - } - } - }, - { - "inputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "description": "This algorithm linearizes and accumulates images into a buffer", - "language": "python", - "splittable": true - } - }, - { - "name": "test/linear_machines_scoring/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "comparison_ids": { - "type": "system/array_1d_uint64/1" - }, - "probe_client_id": { - "type": "system/uint64/1" - }, - "probe_id": { - "type": "system/uint64/1" - }, - "probe_projections": { - "type": "system/array_2d_floats/1" - } - }, - "name": "probes", - "outputs": { - "scores": { - "type": "tutorial/probe_scores/1" - } - } - }, - { - "inputs": { - "template_client_id": { - "type": "system/uint64/1" - }, - "template_id": { - "type": "system/uint64/1" - }, - "template_projections": { - "type": "system/array_2d_floats/1" - } - }, - "name": "templates" - } - ], - "description": "This algorithm generates comparison scores", - "language": "python", - "splittable": true - } - }, - { - "name": "test/means_testing/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "measurements": { - "type": "system/array_1d_floats/1" - } - }, - "name": "group", - "outputs": { - "scores": { - "type": "system/float/1" - } - } - }, - { - "inputs": { - "means": { - "type": "system/array_1d_floats/1" - } - }, - "name": "group0" - } - ], - "description": "", - "language": "python", - "splittable": false - } - }, - { - "name": "test/means_training/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "measurements": { - "type": "system/array_1d_floats/1" - }, - "species": { - "type": "system/text/1" - } - }, - "name": "group", - "outputs": { - "means": { - "type": "system/array_1d_floats/1" - } - } - } - ], - "description": "", - "language": "python", - "splittable": false - } - }, - { - "name": "test/pca/1", - "contents": { - "parameters": { - "number-of-components": { - "default": 5, - "type": "uint32" - } - }, - "uses": {}, - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_uint8/1" - } - }, - "outputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "description": "Principal Component Analysis (PCA)", - "language": "python", - "splittable": false - } - }, - { - "name": "test/pcatest/1", - "contents": { - "parameters": { - "number-of-components": { - "default": 5, - "type": "uint32" - } - }, - "uses": {}, - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_uint8/1" - } - }, - "outputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - }, - { - "inputs": {}, - "name": "group" - } - ], - "description": "Principal Component Analysis (PCA)", - "language": "python", - "splittable": false - } - }, - { - "name": "test/testing/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": {}, - "name": "group", - "outputs": {} - } - ], - "description": "", - "language": "python", - "splittable": false - } - }, - { - "name": "tutorial/linear_machine_projection/4", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_uint8/1" - }, - "id": { - "type": "system/uint64/1" - } - }, - "name": "main", - "outputs": { - "projections": { - "type": "system/array_2d_floats/1" - } - } - }, - { - "inputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "description": "This algorithm linearizes and accumulates images into a buffer", - "language": "python", - "splittable": true - } - }, - { - "name": "tutorial/linear_machines_scoring/4", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "probe_projections": { - "type": "system/array_2d_floats/1" - }, - "comparison_ids": { - "type": "system/array_1d_uint64/1" - }, - "probe_id": { - "type": "system/uint64/1" - }, - "probe_client_id": { - "type": "system/uint64/1" - } - }, - "name": "probes", - "outputs": { - "scores": { - "type": "tutorial/probe_scores/1" - } - } - }, - { - "inputs": { - "template_client_id": { - "type": "system/uint64/1" - }, - "template_id": { - "type": "system/uint64/1" - }, - "template_projections": { - "type": "system/array_2d_floats/1" - } - }, - "name": "templates" - } - ], - "description": "This algorithm generates comparison scores", - "language": "python", - "splittable": true - } - }, - { - "name": "tutorial/pca/2", - "contents": { - "parameters": { - "number-of-components": { - "default": 5, - "type": "uint32" - } - }, - "uses": {}, - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_uint8/1" - } - }, - "outputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "description": "Principal Component Analysis (PCA)", - "language": "python", - "splittable": false - } - }, - { - "name": "test/iris_analyzer/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "scores": { - "type": "system/float/1" - }, - "species": { - "type": "system/text/1" - } - }, - "name": "group" - } - ], - "description": "", - "language": "python", - "results": { - "eer": { - "display": false, - "type": "float32" - }, - "roc": { - "display": false, - "type": "plot/isoroc/1" - }, - "scores_distribution": { - "display": false, - "type": "plot/bar/1" - } - } - } - }, - { - "name": "test/iris_analyzer_error/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "scores": { - "type": "system/float/1" - }, - "species": { - "type": "system/text/1" - } - }, - "name": "group" - } - ], - "description": "", - "language": "python", - "results": { - "eer": { - "display": false, - "type": "float32" - }, - "roc": { - "display": false, - "type": "plot/isoroc/1" - }, - "scores_distribution": { - "display": false, - "type": "plot/bar/1" - } - } - } - }, - { - "name": "test/iris_analyzertest/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "scores": { - "type": "system/float/1" - }, - "species": { - "type": "system/text/1" - } - }, - "name": "group" - } - ], - "description": "", - "language": "python", - "results": { - "eer": { - "display": false, - "type": "float32" - }, - "roc": { - "display": false, - "type": "plot/isoroc/1" - }, - "scores_distribution": { - "display": false, - "type": "plot/bar/1" - } - } - } - }, - { - "name": "test/postperf_iso/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "scores": { - "type": "tutorial/probe_scores/1" - } - }, - "name": "main" - } - ], - "description": "Standard metrics for biometric system evaluation", - "language": "python", - "results": { - "eer": { - "display": true, - "type": "float32" - }, - "number_of_negatives": { - "display": false, - "type": "int32" - }, - "number_of_positives": { - "display": false, - "type": "int32" - } - } - } - }, - { - "name": "tutorial/postperf_iso/1", - "contents": { - "parameters": {}, - "uses": {}, - "groups": [ - { - "inputs": { - "scores": { - "type": "tutorial/probe_scores/1" - } - }, - "name": "main" - } - ], - "description": "Standard metrics for biometric system evaluation", - "language": "python", - "results": { - "number_of_negatives": { - "type": "int32", - "display": false - }, - "far": { - "type": "float32", - "display": true - }, - "roc": { - "type": "plot/isoroc/1", - "display": false - }, - "scores_distribution": { - "type": "plot/bar/1", - "display": false - }, - "eer": { - "type": "float32", - "display": true - }, - "frr": { - "type": "float32", - "display": true - }, - "threshold": { - "type": "float32", - "display": false - }, - "number_of_positives": { - "type": "int32", - "display": false - } - } - } - }, - { - "name": "aythamimm/manhattan_scaled_scoring/63", - "contents": { - "splittable": false, - "parameters": { - "field": { - "default": "given_name", - "type": "string", - "description": "", - "choice": [ - "given_name", - "family_name", - "email", - "nationality", - "id_number", - "all_five" - ] - } - }, - "language": "python", - "uses": {}, - "groups": [ - { - "inputs": { - "comparison_ids": { - "type": "system/array_1d_text/1" - }, - "keystroke": { - "type": "tutorial/atvs_keystroke/1" - }, - "probe_client_id": { - "type": "system/text/1" - } - }, - "name": "probes", - "outputs": { - "scores": { - "type": "elie_khoury/string_probe_scores/1" - } - } - }, - { - "inputs": { - "template_client_id": { - "type": "system/text/1" - }, - "template_id": { - "type": "system/text/1" - }, - "model_template": { - "type": "aythamimm/keystroke_model/6" - } - }, - "name": "templates" - } - ], - "description": "This algorithm computes the score given a GMM and UBM using the Linear Scoring" - } - }, - { - "name": "tutorial/linear_machine_projection/4", - "contents": { - "splittable": true, - "parameters": {}, - "language": "python", - "uses": {}, - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_uint8/1" - }, - "id": { - "type": "system/uint64/1" - } - }, - "name": "main", - "outputs": { - "projections": { - "type": "system/array_2d_floats/1" - } - } - }, - { - "inputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "description": "This algorithm linearizes and accumulates images into a buffer" - } - }, - { - "name": "tutorial/linear_machines_scoring/4", - "contents": { - "splittable": true, - "parameters": {}, - "language": "python", - "uses": {}, - "groups": [ - { - "inputs": { - "probe_projections": { - "type": "system/array_2d_floats/1" - }, - "comparison_ids": { - "type": "system/array_1d_uint64/1" - }, - "probe_id": { - "type": "system/uint64/1" - }, - "probe_client_id": { - "type": "system/uint64/1" - } - }, - "name": "probes", - "outputs": { - "scores": { - "type": "tutorial/probe_scores/1" - } - } - }, - { - "inputs": { - "template_client_id": { - "type": "system/uint64/1" - }, - "template_id": { - "type": "system/uint64/1" - }, - "template_projections": { - "type": "system/array_2d_floats/1" - } - }, - "name": "templates" - } - ], - "description": "This algorithm generates comparison scores" - } - }, - { - "name": "tutorial/pca/2", - "contents": { - "language": "python", - "splittable": false, - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_uint8/1" - } - }, - "outputs": { - "subspace": { - "type": "tutorial/linear_machine/1" - } - } - } - ], - "parameters": { - "number-of-components": { - "default": 5, - "type": "uint32" - } - }, - "description": "Principal Component Analysis (PCA)" - } - }, - { - "name": "tutorial/postperf_iso/1", - "contents": { - "groups": [ - { - "inputs": { - "scores": { - "type": "tutorial/probe_scores/1" - } - }, - "name": "main" - } - ], - "parameters": {}, - "uses": {}, - "results": { - "number_of_negatives": { - "type": "int32", - "display": false - }, - "far": { - "type": "float32", - "display": true - }, - "roc": { - "type": "plot/isoroc/1", - "display": false - }, - "scores_distribution": { - "type": "plot/bar/1", - "display": false - }, - "eer": { - "type": "float32", - "display": true - }, - "frr": { - "type": "float32", - "display": true - }, - "threshold": { - "type": "float32", - "display": false - }, - "number_of_positives": { - "type": "int32", - "display": false - } - }, - "language": "python", - "description": "Standard metrics for biometric system evaluation" - } - }, - { - "name": "user/cropping_rgb/1", - "contents": { - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_3d_uint8/1" - }, - "eye_centers": { - "type": "system/eye_positions/1" - } - }, - "outputs": { - "cropped_image": { - "type": "system/array_2d_floats/1" - } - } - } - ], - "parameters": { - "left-eye-x": { - "default": "48", - "type": "uint32", - "description": "x-coordinate of the left eye on the cropped image" - }, - "left-eye-y": { - "default": "16", - "type": "uint32", - "description": "y-coordinate of the left eye on the cropped image" - }, - "crop-height": { - "default": "80", - "type": "uint32", - "description": "height of the resulting cropped image" - }, - "crop-width": { - "default": "64", - "type": "uint32", - "description": "width of the resulting cropped image" - }, - "right-eye-x": { - "default": "15", - "type": "uint32", - "description": "x-coordinate of the right eye on the cropped image" - }, - "right-eye-y": { - "default": "16", - "type": "uint32", - "description": "y-coordinate of the right eye on the cropped image" - } - }, - "splittable": true, - "description": "Crop and normalize a face from an RGB image", - "language": "python" - } - }, - { - "name": "user/eerhter_postperf/1", - "contents": { - "groups": [ - { - "inputs": { - "scores_test": { - "type": "user/probe_scores/1" - } - }, - "name": "test" - }, - { - "inputs": { - "scores_dev": { - "type": "user/probe_scores/1" - } - }, - "name": "dev" - } - ], - "language": "python", - "results": { - "number_of_negatives_dev": { - "type": "int32", - "display": false - }, - "far_test": { - "type": "float32", - "display": true - }, - "far_dev": { - "type": "float32", - "display": false - }, - "number_of_negatives_test": { - "type": "int32", - "display": false - }, - "roc_test": { - "type": "plot/scatter/1", - "display": false - }, - "roc_dev": { - "type": "plot/scatter/1", - "display": false - }, - "hter": { - "type": "float32", - "display": true - }, - "threshold": { - "type": "float32", - "display": false - }, - "frr_dev": { - "type": "float32", - "display": false - }, - "eer": { - "type": "float32", - "display": true - }, - "number_of_positives_test": { - "type": "int32", - "display": false - }, - "frr_test": { - "type": "float32", - "display": true - }, - "number_of_positives_dev": { - "type": "int32", - "display": false - } - } - } - }, - { - "name": "user/integers_add/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - }, - "name": "main", - "outputs": { - "out_data": { - "type": "system/integer/1" - } - } - } - ], - "parameters": { - "offset": { - "default": "1", - "type": "int32" - } - }, - "uses": { - "lib": "user/thelib/1" - }, - "splittable": true, - "language": "python" - } - }, - { - "name": "user/integers_echo/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - }, - "name": "main", - "outputs": { - "out_data": { - "type": "system/integer/1" - } - } - } - ], - "splittable": true, - "language": "python" - } - }, - { - "name": "user/integers_echo_analyzer/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - }, - "name": "main" - } - ], - "language": "python", - "results": { - "roc": { - "type": "plot/isoroc/1", - "display": false - }, - "plot": { - "type": "plot/scatter/1", - "display": false - }, - "out_data": { - "type": "int32", - "display": false - }, - "bar_plot": { - "type": "plot/bar/1", - "display": false - } - } - } - }, - { - "name": "user/integers_echo_error/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - }, - "name": "main", - "outputs": { - "out_data": { - "type": "system/integer/1" - } - } - } - ], - "splittable": true, - "language": "python" - } - }, - { - "name": "user/integers_echo_ignore/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - }, - "name": "main", - "outputs": { - "out_data": { - "type": "system/integer/1" - } - } - }, - { - "inputs": { - "in_data2": { - "type": "system/integer/1" - } - }, - "name": "sub" - } - ], - "splittable": true, - "language": "python" - } - }, - { - "name": "user/integers_echo_sleep/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - }, - "name": "main", - "outputs": { - "out_data": { - "type": "system/integer/1" - } - } - } - ], - "parameters": { - "delay": { - "default": "30", - "type": "uint32", - "description": "Time to sleep in seconds" - } - }, - "splittable": true, - "language": "python" - } - }, - { - "name": "user/integers_mean_analyzer/1", - "contents": { - "groups": [ - { - "inputs": { - "in_data": { - "type": "system/integer/1" - } - } - } - ], - "language": "python", - "results": { - "plot": { - "type": "plot/scatter/1", - "display": false - }, - "out_data": { - "type": "float32", - "display": false - } - } - } - }, - { - "name": "user/linear_machines_scoring/1", - "contents": { - "groups": [ - { - "inputs": { - "probe_projections": { - "type": "system/array_2d_floats/1" - }, - "comparison_ids": { - "type": "system/array_1d_uint64/1" - }, - "probe_id": { - "type": "system/uint64/1" - }, - "probe_client_id": { - "type": "system/uint64/1" - } - }, - "name": "probes", - "outputs": { - "scores": { - "type": "user/probe_scores/1" - } - } - }, - { - "inputs": { - "template_client_id": { - "type": "system/uint64/1" - }, - "template_id": { - "type": "system/uint64/1" - }, - "template_projections": { - "type": "system/array_2d_floats/1" - } - }, - "name": "templates" - } - ], - "splittable": true, - "description": "Minimum Euclidean distance comparison against a template matrix", - "language": "python" - } - }, - { - "name": "user/linear_machine_x2_projection/1", - "contents": { - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_floats/1" - }, - "id": { - "type": "system/uint64/1" - } - }, - "name": "main", - "outputs": { - "projections": { - "type": "system/array_2d_floats/1" - } - } - }, - { - "inputs": { - "subspace_lda": { - "type": "user/linear_machine/1" - }, - "subspace_pca": { - "type": "user/linear_machine/1" - } - } - } - ], - "splittable": true, - "description": "Accumulate images and apply two linear transformations", - "language": "python" - } - }, - { - "name": "user/pca_lda/1", - "contents": { - "groups": [ - { - "inputs": { - "image": { - "type": "system/array_2d_floats/1" - }, - "client_id": { - "type": "system/uint64/1" - } - }, - "outputs": { - "subspace_lda": { - "type": "user/linear_machine/1" - }, - "subspace_pca": { - "type": "user/linear_machine/1" - } - } - } - ], - "parameters": { - "number-of-pca-components": { - "default": "5", - "type": "uint32", - "description": "the number of dimensions to retain after applying PCA" - }, - "number-of-lda-components": { - "default": "2", - "type": "uint32", - "description": "the number of dimensions to retain after applying LDA" - } - }, - "splittable": false, - "description": "Principal Component Analysis (PCA) + Linear Discrimanant Analysis (LDA)", - "language": "python" - } - } -] diff --git a/conda/js/test/test_dbs.json b/conda/js/test/test_dbs.json deleted file mode 100644 index eb5d1a78..00000000 --- a/conda/js/test/test_dbs.json +++ /dev/null @@ -1,2511 +0,0 @@ -[ - { - "name": "iris/1", - "contents": { - "description": "", - "root_folder": "/not/needed", - "protocols": [ - { - "name": "Main", - "sets": [ - { - "parameters": {}, - "name": "training", - "outputs": { - "measurements": "system/array_1d_floats/1", - "species": "system/text/1" - }, - "template": "iris", - "view": "Training" - }, - { - "parameters": {}, - "name": "testing", - "outputs": { - "measurements": "system/array_1d_floats/1", - "species": "system/text/1" - }, - "template": "iris", - "view": "Testing" - } - ], - "template": "iris" - } - ] - } - }, - { - "name": "atnt/3", - "contents": { - "root_folder": "/remote/dataset/att_faces", - "description": "The AT&T Database of Faces", - "protocols": [ - { - "name": "idiap", - "template": "simple_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_2d_uint8/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "name": "train", - "template": "train", - "view": "Train" - }, - { - "outputs": { - "image": "system/array_2d_uint8/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "name": "templates", - "template": "templates", - "view": "Templates" - }, - { - "outputs": { - "probe_id": "system/uint64/1", - "image": "system/array_2d_uint8/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_ids": "system/array_1d_uint64/1" - }, - "name": "probes", - "template": "probes", - "view": "Probes" - } - ] - }, - { - "name": "idiap_test_eyepos", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "name": "train", - "template": "train", - "view": "TrainEyePositions" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "TemplatesEyePositions", - "name": "dev_templates", - "parameters": { - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "ProbesEyePositions", - "name": "dev_probes", - "parameters": { - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "TemplatesEyePositions", - "name": "test_templates", - "parameters": { - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "ProbesEyePositions", - "name": "test_probes", - "parameters": { - "group": "eval" - }, - "template": "probes" - } - ] - } - ] - } - }, - { - "name": "avspoof/2", - "contents": { - "description": "The AVspoof Database", - "root_folder": "/remote/dataset/AVSpoof", - "protocols": [ - { - "name": "smalltest_verify_train", - "template": "verify_trainset_speech", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "parameters": { - "group": "train", - "protocol": "smalltest", - "purpose": "enroll" - }, - "name": "train_templates", - "template": "templates", - "view": "RecognitionTemplates" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "probe_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "smalltest", - "purpose": "probe" - }, - "name": "train_probes", - "template": "probes", - "view": "Probes" - } - ] - }, - { - "name": "smalltest_verify_train_spoof", - "template": "verify_trainset_speech_spoof", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "attack_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "smalltest", - "purpose": "attack" - }, - "name": "train_attacks", - "template": "attacks", - "view": "Probes" - } - ] - }, - { - "name": "smalltest_verification", - "template": "advanced_speaker_recognition", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1" - }, - "parameters": { - "group": "train", - "protocol": "smalltest" - }, - "name": "train", - "template": "train", - "view": "RecognitionTraining" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "parameters": { - "group": "devel", - "protocol": "smalltest", - "purpose": "enroll" - }, - "name": "dev_templates", - "template": "templates", - "view": "RecognitionTemplates" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "probe_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "devel", - "protocol": "smalltest", - "purpose": "probe" - }, - "name": "dev_probes", - "template": "probes", - "view": "Probes" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "parameters": { - "group": "test", - "protocol": "smalltest", - "purpose": "enroll" - }, - "name": "test_templates", - "template": "templates", - "view": "RecognitionTemplates" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "probe_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "test", - "protocol": "smalltest", - "purpose": "probe" - }, - "name": "test_probes", - "template": "probes", - "view": "Probes" - } - ] - }, - { - "name": "smalltest_verification_spoof", - "template": "speaker_recognition_spoof", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "attack_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "devel", - "protocol": "smalltest", - "purpose": "attack" - }, - "name": "dev_attacks", - "template": "attacks", - "view": "Probes" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "attack_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "test", - "protocol": "smalltest", - "purpose": "attack" - }, - "name": "test_attacks", - "template": "attacks", - "view": "Probes" - } - ] - }, - { - "name": "grandtest_verify_train", - "template": "verify_trainset_speech", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "parameters": { - "group": "train", - "protocol": "grandtest", - "purpose": "enroll" - }, - "name": "train_templates", - "template": "templates", - "view": "RecognitionTemplates" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "probe_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "grandtest", - "purpose": "probe" - }, - "name": "train_probes", - "template": "probes", - "view": "Probes" - } - ] - }, - { - "name": "grandtest_verify_train_spoof", - "template": "verify_trainset_speech_spoof", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "attack_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "grandtest", - "purpose": "attack" - }, - "name": "train_attacks", - "template": "attacks", - "view": "Probes" - } - ] - }, - { - "name": "grandtest_verification", - "template": "advanced_speaker_recognition", - "sets": [ - { - "name": "train", - "template": "train", - "view": "RecognitionTraining", - "parameters": { - "protocol": "grandtest", - "group": "train" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "dev_templates", - "template": "templates", - "view": "RecognitionTemplates", - "parameters": { - "protocol": "grandtest", - "purpose": "enroll", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "dev_probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "grandtest", - "purpose": "probe", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "probe_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_templates", - "template": "templates", - "view": "RecognitionTemplates", - "parameters": { - "protocol": "grandtest", - "purpose": "enroll", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "grandtest", - "purpose": "probe", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "probe_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - } - ] - }, - { - "name": "grandtest_verification_spoof", - "template": "speaker_recognition_spoof", - "sets": [ - { - "name": "dev_attacks", - "template": "attacks", - "view": "Probes", - "parameters": { - "protocol": "grandtest", - "purpose": "attack", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "attack_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_attacks", - "template": "attacks", - "view": "Probes", - "parameters": { - "protocol": "grandtest", - "purpose": "attack", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "attack_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - } - ] - }, - { - "name": "physicalaccess_verify_train", - "template": "verify_trainset_speech", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "parameters": { - "group": "train", - "protocol": "physical_access", - "purpose": "enroll" - }, - "name": "train_templates", - "template": "templates", - "view": "RecognitionTemplates" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "probe_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "physical_access", - "purpose": "probe" - }, - "name": "train_probes", - "template": "probes", - "view": "Probes" - } - ] - }, - { - "name": "physicalaccess_verify_train_spoof", - "template": "verify_trainset_speech_spoof", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "attack_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "physical_access", - "purpose": "attack" - }, - "name": "train_attacks", - "template": "attacks", - "view": "Probes" - } - ] - }, - { - "name": "physicalaccess_verification", - "template": "advanced_speaker_recognition", - "sets": [ - { - "name": "train", - "template": "train", - "view": "RecognitionTraining", - "parameters": { - "protocol": "physical_access", - "group": "train" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "dev_templates", - "template": "templates", - "view": "RecognitionTemplates", - "parameters": { - "protocol": "physical_access", - "purpose": "enroll", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "dev_probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "physical_access", - "purpose": "probe", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "probe_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_templates", - "template": "templates", - "view": "RecognitionTemplates", - "parameters": { - "protocol": "physical_access", - "purpose": "enroll", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "physical_access", - "purpose": "probe", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "probe_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - } - ] - }, - { - "name": "physicalaccess_verification_spoof", - "template": "speaker_recognition_spoof", - "sets": [ - { - "name": "dev_attacks", - "template": "attacks", - "view": "Probes", - "parameters": { - "protocol": "physical_access", - "purpose": "attack", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "attack_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_attacks", - "template": "attacks", - "view": "Probes", - "parameters": { - "protocol": "physical_access", - "purpose": "attack", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "attack_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - } - ] - }, - { - "name": "logicalaccess_verify_train", - "template": "verify_trainset_speech", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "parameters": { - "group": "train", - "protocol": "logical_access", - "purpose": "enroll" - }, - "name": "train_templates", - "template": "templates", - "view": "RecognitionTemplates" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "probe_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "logical_access", - "purpose": "probe" - }, - "name": "train_probes", - "template": "probes", - "view": "Probes" - } - ] - }, - { - "name": "logicalaccess_verify_train_spoof", - "template": "verify_trainset_speech_spoof", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "client_id": "system/text/1", - "file_id": "system/text/1", - "attack_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "parameters": { - "group": "train", - "protocol": "logical_access", - "purpose": "attack" - }, - "name": "train_attacks", - "template": "attacks", - "view": "Probes" - } - ] - }, - { - "name": "logicalaccess_verification", - "template": "advanced_speaker_recognition", - "sets": [ - { - "name": "train", - "template": "train", - "view": "RecognitionTraining", - "parameters": { - "protocol": "logical_access", - "group": "train" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "dev_templates", - "template": "templates", - "view": "RecognitionTemplates", - "parameters": { - "protocol": "logical_access", - "purpose": "enroll", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "dev_probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "logical_access", - "purpose": "probe", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "probe_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_templates", - "template": "templates", - "view": "RecognitionTemplates", - "parameters": { - "protocol": "logical_access", - "purpose": "enroll", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "logical_access", - "purpose": "probe", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "probe_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - } - ] - }, - { - "name": "logicalaccess_verification_spoof", - "template": "speaker_recognition_spoof", - "sets": [ - { - "name": "dev_attacks", - "template": "attacks", - "view": "Probes", - "parameters": { - "protocol": "logical_access", - "purpose": "attack", - "group": "devel" - }, - "outputs": { - "file_id": "system/text/1", - "attack_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - }, - { - "name": "test_attacks", - "template": "attacks", - "view": "Probes", - "parameters": { - "protocol": "logical_access", - "purpose": "attack", - "group": "test" - }, - "outputs": { - "file_id": "system/text/1", - "attack_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "speech": "system/array_1d_floats/1" - } - } - ] - }, - { - "name": "smalltest_antispoofing", - "template": "simple_speech_antispoofing", - "sets": [ - { - "outputs": { - "attack_type": "system/text/1", - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "group": "train", - "protocol": "smalltest" - }, - "name": "train", - "template": "train", - "view": "SimpleAntispoofing" - }, - { - "outputs": { - "attack_type": "system/text/1", - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "group": "devel", - "protocol": "smalltest" - }, - "name": "dev_probes", - "template": "probes", - "view": "SimpleAntispoofing" - }, - { - "outputs": { - "attack_type": "system/text/1", - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "group": "test", - "protocol": "smalltest" - }, - "name": "eval_probes", - "template": "probes", - "view": "SimpleAntispoofing" - } - ] - }, - { - "name": "grandtest_antispoofing", - "template": "simple_speech_antispoofing", - "sets": [ - { - "name": "train", - "template": "train", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "grandtest", - "group": "train" - } - }, - { - "name": "dev_probes", - "template": "probes", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "grandtest", - "group": "devel" - } - }, - { - "name": "eval_probes", - "template": "probes", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "grandtest", - "group": "test" - } - } - ] - }, - { - "name": "physicalaccess_antispoofing", - "template": "simple_speech_antispoofing", - "sets": [ - { - "name": "train", - "template": "train", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "physical_access", - "group": "train" - } - }, - { - "name": "dev_probes", - "template": "probes", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "physical_access", - "group": "devel" - } - }, - { - "name": "eval_probes", - "template": "probes", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "physical_access", - "group": "test" - } - } - ] - }, - { - "name": "logicalaccess_antispoofing", - "template": "simple_speech_antispoofing", - "sets": [ - { - "name": "train", - "template": "train", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "logical_access", - "group": "train" - } - }, - { - "name": "dev_probes", - "template": "probes", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "logical_access", - "group": "devel" - } - }, - { - "name": "eval_probes", - "template": "probes", - "view": "SimpleAntispoofing", - "outputs": { - "file_id": "system/text/1", - "client_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "attack_type": "system/text/1", - "class": "system/text/1" - }, - "parameters": { - "protocol": "logical_access", - "group": "test" - } - } - ] - } - ] - } - }, - { - "name": "banca/2", - "contents": { - "root_folder": "/remote/dataset/banca/english/images/images", - "description": "The BANCA Database of Faces", - "protocols": [ - { - "name": "P", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "P" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "P", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "P", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "P", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "P", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "G", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "G" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "G", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "G", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "G", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "G", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "Mc", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "Mc" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "Mc", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "Mc", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "Mc", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "Mc", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "Md", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "Md" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "Md", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "Md", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "Md", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "Md", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "Ma", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "Ma" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "Ma", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "Ma", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "Ma", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "Ma", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "Ud", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "Ud" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "Ud", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "Ud", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "Ud", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "Ud", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "Ua", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "Ua" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "Ua", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "Ua", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "Ua", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "Ua", - "group": "eval" - }, - "template": "probes" - } - ] - } - ] - } - }, - { - "name": "kboc16/2", - "contents": { - "root_folder": "/remote/dataset/kboc16", - "description": "The KBOC16 database", - "protocols": [ - { - "name": "A", - "template": "simple_keystroke_recognition_kboc16", - "sets": [ - { - "name": "templates", - "template": "templates", - "view": "Templates", - "parameters": { - "protocol": "A" - }, - "outputs": { - "file_id": "system/uint64/1", - "client_id": "system/text/1", - "template_id": "system/text/1", - "keystroke": "system/kboc16_keystroke/1" - } - }, - { - "name": "probes", - "template": "probes", - "view": "Probes", - "parameters": { - "protocol": "A" - }, - "outputs": { - "file_id": "system/uint64/1", - "probe_id": "system/uint64/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1", - "keystroke": "system/kboc16_keystroke/1" - } - } - ] - }, - { - "name": "D", - "template": "simple_keystroke_recognition_kboc16", - "sets": [ - { - "outputs": { - "keystroke": "system/kboc16_keystroke/1", - "file_id": "system/uint64/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "template": "templates", - "name": "templates", - "parameters": { - "protocol": "D" - }, - "view": "Templates" - }, - { - "outputs": { - "client_id": "system/text/1", - "keystroke": "system/kboc16_keystroke/1", - "file_id": "system/uint64/1", - "probe_id": "system/uint64/1", - "template_ids": "system/array_1d_text/1" - }, - "template": "probes", - "name": "probes", - "parameters": { - "protocol": "D" - }, - "view": "Probes" - } - ] - } - ] - } - }, - { - "name": "mobio/2", - "contents": { - "root_folder": "/remote/dataset/mobio/IMAGES_PNG", - "description": "The MOBIO Database of Faces", - "protocols": [ - { - "name": "male", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "male", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "male", - "group": "dev", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "male", - "group": "dev", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "male", - "group": "eval", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "male", - "group": "eval", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "probes" - } - ] - }, - { - "name": "female", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "female", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "female", - "group": "dev", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "female", - "group": "dev", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "female", - "group": "eval", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "female", - "group": "eval", - "annotations": "../IMAGE_ANNOTATIONS" - }, - "template": "probes" - } - ] - } - ] - } - }, - { - "name": "simple/1", - "contents": { - "root_folder": "/this/database/does/not/require/a/path", - "description": "A test database that emits integers", - "protocols": [ - { - "name": "protocol", - "template": "test_integers", - "sets": [ - { - "outputs": { - "out": "system/integer/1" - }, - "name": "set", - "template": "set", - "view": "View" - }, - { - "outputs": { - "out": "system/integer/1" - }, - "name": "set2", - "template": "set", - "view": "View2" - } - ] - }, - { - "name": "protocol2", - "template": "test_integers", - "sets": [ - { - "outputs": { - "out": "system/integer/1" - }, - "name": "set", - "template": "set", - "view": "LargeView" - }, - { - "outputs": { - "out": "system/integer/1" - }, - "name": "set2", - "template": "set", - "view": "View2" - } - ] - } - ] - } - }, - { - "name": "voxforge/2", - "contents": { - "root_folder": "/remote/dataset/VoxForge/audio/denoised/SpeechCorpus/Trunk/Audio/Main/16kHz_16bit", - "description": "The VoxForge Database", - "protocols": [ - { - "name": "default", - "template": "advanced_speaker_recognition", - "sets": [ - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1" - }, - "name": "train", - "template": "train", - "view": "Train" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "probe_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_id": "system/text/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "probe_id": "system/text/1", - "speech": "system/array_1d_floats/1", - "file_id": "system/text/1", - "client_id": "system/text/1", - "template_ids": "system/array_1d_text/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "group": "eval" - }, - "template": "probes" - } - ] - } - ] - } - }, - { - "name": "xm2vts/2", - "contents": { - "root_folder": "/remote/dataset/xm2vtsdb/images", - "description": "The XM2VTS Database of Faces", - "protocols": [ - { - "name": "lp1", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "lp1" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "lp1", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "lp1", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "lp1", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "lp1", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "lp2", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "lp2" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "lp2", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "lp2", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "lp2", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "lp2", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "darkened-lp1", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "darkened-lp1" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "darkened-lp1", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "darkened-lp1", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "darkened-lp1", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "darkened-lp1", - "group": "eval" - }, - "template": "probes" - } - ] - }, - { - "name": "darkened-lp2", - "template": "advanced_face_recognition", - "sets": [ - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1" - }, - "view": "Train", - "name": "train", - "parameters": { - "protocol": "darkened-lp2" - }, - "template": "train" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "dev_templates", - "parameters": { - "protocol": "darkened-lp2", - "group": "dev" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "dev_probes", - "parameters": { - "protocol": "darkened-lp2", - "group": "dev" - }, - "template": "probes" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "eye_centers": "system/eye_positions/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "template_id": "system/uint64/1" - }, - "view": "Templates", - "name": "test_templates", - "parameters": { - "protocol": "darkened-lp2", - "group": "eval" - }, - "template": "templates" - }, - { - "outputs": { - "image": "system/array_3d_uint8/1", - "probe_id": "system/uint64/1", - "file_id": "system/uint64/1", - "client_id": "system/uint64/1", - "eye_centers": "system/eye_positions/1", - "template_ids": "system/array_1d_uint64/1" - }, - "view": "Probes", - "name": "test_probes", - "parameters": { - "protocol": "darkened-lp2", - "group": "eval" - }, - "template": "probes" - } - ] - } - ] - } - } -] diff --git a/conda/js/test/test_dfs.json b/conda/js/test/test_dfs.json deleted file mode 100644 index 7b3fe3bb..00000000 --- a/conda/js/test/test_dfs.json +++ /dev/null @@ -1,427 +0,0 @@ -[ - { - "name": "aythamimm/keystroke_model/6", - "contents": { - "nationality_average": [ - 0, - "float64" - ], - "#description": "Basic format containing a one-dimensional array of float values", - "email_average": [ - 0, - "float64" - ], - "family_name_std": [ - 0, - "float64" - ], - "family_name_average": [ - 0, - "float64" - ], - "id_number_std": [ - 0, - "float64" - ], - "given_name_std": [ - 0, - "float64" - ], - "email_std": [ - 0, - "float64" - ], - "id_number_average": [ - 0, - "float64" - ], - "nationality_std": [ - 0, - "float64" - ], - "given_name_average": [ - 0, - "float64" - ] - } - }, - { - "name": "elie_khoury/string_probe_scores/1", - "contents": { - "client_identity": "string", - "scores": [ - 0, - { - "template_identity": "string", - "score": "float64" - } - ], - "#description": "Score for verification" - } - }, - { - "name": "plot/bar/1", - "contents": { - "#description": "Array of bar plots", - "data": [ - 0, - { - "label": "string", - "x": [ - 0, - "float64" - ], - "y": [ - 0, - "float64" - ] - } - ] - } - }, - { - "name": "plot/isoroc/1", - "contents": { - "#description": "A set of ROC plots as described by ISO/IEC 19795-1:2006(E)", - "data": [ - 0, - { - "label": "string", - "number_of_positives": "uint64", - "number_of_negatives": "uint64", - "false_positives": [ - 0, - "float64" - ], - "false_negatives": [ - 0, - "float64" - ] - } - ] - } - }, - { - "name": "plot/scatter/1", - "contents": { - "#description": "A set of 2-D scatter plots with X/Y and a label", - "data": [ - 0, - { - "y": [ - 0, - "float64" - ], - "x": [ - 0, - "float64" - ], - "label": "string" - } - ] - } - }, - { - "name": "system/array_1d_floats/1", - "contents": { - "#description": "Basic format containing a one-dimensional array of float values", - "value": [ - 0, - "float64" - ] - } - }, - { - "name": "system/array_1d_text/1", - "contents": { - "text": [ - 0, - "string" - ] - } - }, - { - "name": "system/array_1d_uint64/1", - "contents": { - "#description": "Basic format containing a one-dimensional array of unsigned integer (64 bits) values", - "value": [ - 0, - "uint64" - ] - } - }, - { - "name": "system/array_2d_floats/1", - "contents": { - "#description": "Basic format containing a two-dimensional array of float values", - "value": [ - 0, - 0, - "float64" - ] - } - }, - { - "name": "system/array_2d_uint8/1", - "contents": { - "#description": "Two-dimensional array of 8 unsigned integer values", - "value": [ - 0, - 0, - "uint8" - ] - } - }, - { - "name": "system/array_3d_uint8/1", - "contents": { - "value": [ - 0, - 0, - 0, - "uint8" - ] - } - }, - { - "name": "system/coordinates/1", - "contents": { - "#description": "Contains the coordinates of a pixel", - "y": "int32", - "x": "int32" - } - }, - { - "name": "system/eye_positions/1", - "contents": { - "#description": "The position of the eyes of a person in an image", - "right": "system/coordinates/1", - "left": "system/coordinates/1" - } - }, - { - "name": "system/integer/1", - "contents": { - "#description": "Single (32 bits) integer value", - "value": "int32" - } - }, - { - "name": "system/kboc16_keystroke/1", - "contents": { - "#description": "Raw KBOC16 keystroke data", - "timestamps": [ - 0, - "int32" - ], - "key_events": [ - 0, - "string" - ] - } - }, - { - "name": "system/text/1", - "contents": { - "#description": "Basic format containing a text", - "text": "string" - } - }, - { - "name": "system/uint64/1", - "contents": { - "#description": "Basic format containing only a single unsigned integer (64 bits) value", - "value": "uint64" - } - }, - { - "name": "tutorial/atvs_keystroke/1", - "contents": { - "#description": "Raw ATVS keystroke data", - "holdtime": { - "given_name": [ - 0, - "int32" - ], - "family_name": [ - 0, - "int32" - ], - "email": [ - 0, - "int32" - ], - "nationality": [ - 0, - "int32" - ], - "id_number": [ - 0, - "int32" - ] - }, - "rplatency": { - "given_name": [ - 0, - "int32" - ], - "family_name": [ - 0, - "int32" - ], - "email": [ - 0, - "int32" - ], - "nationality": [ - 0, - "int32" - ], - "id_number": [ - 0, - "int32" - ] - }, - "pplatency": { - "given_name": [ - 0, - "int32" - ], - "family_name": [ - 0, - "int32" - ], - "email": [ - 0, - "int32" - ], - "nationality": [ - 0, - "int32" - ], - "id_number": [ - 0, - "int32" - ] - }, - "rrlatency": { - "given_name": [ - 0, - "int32" - ], - "family_name": [ - 0, - "int32" - ], - "email": [ - 0, - "int32" - ], - "nationality": [ - 0, - "int32" - ], - "id_number": [ - 0, - "int32" - ] - }, - "prlatency": { - "given_name": [ - 0, - "int32" - ], - "family_name": [ - 0, - "int32" - ], - "email": [ - 0, - "int32" - ], - "nationality": [ - 0, - "int32" - ], - "id_number": [ - 0, - "int32" - ] - } - } - }, - { - "name": "tutorial/linear_machine/1", - "contents": { - "input_divide": [ - 0, - "float64" - ], - "input_subtract": [ - 0, - "float64" - ], - "weights": [ - 0, - 0, - "float64" - ], - "biases": [ - 0, - "float64" - ], - "#description": "Linear Projection container" - } - }, - { - "name": "tutorial/probe_scores/1", - "contents": { - "client_identity": "uint64", - "scores": [ - 0, - { - "template_identity": "uint64", - "score": "float64" - } - ], - "#description": "Container that stores the scores of a probe" - } - }, - { - "name": "user/linear_machine/1", - "contents": { - "input_divide": [ - 0, - "float64" - ], - "input_subtract": [ - 0, - "float64" - ], - "#description": "Linear Projection Machine", - "weights": [ - 0, - 0, - "float64" - ], - "biases": [ - 0, - "float64" - ] - } - }, - { - "name": "user/probe_scores/1", - "contents": { - "client_identity": "uint64", - "#description": "Score for verification", - "scores": [ - 0, - { - "template_identity": "uint64", - "score": "float64" - } - ] - } - } -] diff --git a/conda/js/test/test_exps.json b/conda/js/test/test_exps.json deleted file mode 100644 index 3a9cf6fa..00000000 --- a/conda/js/test/test_exps.json +++ /dev/null @@ -1,787 +0,0 @@ -[ - { - "name": "test/test/iris_advanced/1/iris", - "contents": { - "description": "", - "analyzers": { - "analyzer": { - "algorithm": "test/iris_analyzer/1", - "inputs": { - "scores": "scores", - "species": "species" - }, - "parameters": {} - } - }, - "blocks": { - "pre_testing": { - "algorithm": "test/iris_preprocessor/1", - "inputs": { - "measurements": "measurements" - }, - "outputs": { - "measurements": "measurements" - }, - "parameters": {} - }, - "pre_training": { - "algorithm": "test/iris_preprocessor/1", - "inputs": { - "measurements": "measurements" - }, - "outputs": { - "measurements": "measurements" - }, - "parameters": {} - }, - "testing_alg": { - "algorithm": "test/iris_testing/1", - "inputs": { - "lda_machine": "lda_machine", - "measurements": "measurements" - }, - "outputs": { - "scores": "scores" - }, - "parameters": {} - }, - "training_alg": { - "algorithm": "test/iris_training/1", - "inputs": { - "measurements": "measurements", - "species": "species" - }, - "outputs": { - "lda_machine": "lda_machine" - }, - "parameters": {} - } - }, - "datasets": { - "testing_data": { - "database": "iris/1", - "protocol": "Main", - "set": "training" - }, - "training_data": { - "database": "iris/1", - "protocol": "Main", - "set": "testing" - } - }, - "globals": { - "queue": "Default", - "environment": { - "name": "Scientific Python 2.7", - "version": "0.0.4" - } - } - } - }, - { - "name": "tutorial/tutorial/eigenface/1/atnt-eigenfaces-7-comps", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "scores": "scores" - }, - "algorithm": "tutorial/postperf_iso/1" - } - }, - "datasets": { - "templates": { - "set": "templates", - "protocol": "idiap", - "database": "atnt/3" - }, - "train": { - "set": "train", - "protocol": "idiap", - "database": "atnt/3" - }, - "probes": { - "set": "probes", - "protocol": "idiap", - "database": "atnt/3" - } - }, - "blocks": { - "scoring": { - "inputs": { - "probe_projections": "probe_builder_projections", - "comparison_ids": "probes_template_ids", - "probe_id": "probes_probe_id", - "template_id": "templates_template_id", - "probe_client_id": "probes_client_id", - "template_client_id": "templates_client_id", - "template_projections": "template_builder_projections" - }, - "algorithm": "tutorial/linear_machines_scoring/4", - "outputs": { - "scores": "scores" - } - }, - "linear_machine_training": { - "inputs": { - "image": "image" - }, - "algorithm": "tutorial/pca/2", - "outputs": { - "subspace": "subspace" - } - }, - "template_builder": { - "inputs": { - "image": "image", - "subspace": "subspace", - "id": "template_id" - }, - "algorithm": "tutorial/linear_machine_projection/4", - "outputs": { - "projections": "projections" - } - }, - "probe_builder": { - "inputs": { - "image": "image", - "subspace": "subspace", - "id": "probe_id" - }, - "algorithm": "tutorial/linear_machine_projection/4", - "outputs": { - "projections": "projections" - } - } - }, - "globals": { - "queue": "Default", - "environment": { - "version": "0.0.4", - "name": "Scientific Python 2.7" - }, - "tutorial/pca/2": { - "number-of-components": 7 - } - } - } - }, - { - "name": "user/user/double/1/double_error", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo1": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo/1", - "outputs": { - "out_data": "out" - } - }, - "echo2": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_error/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - }, - { - "name": "user/user/double/1/double", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo1": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo/1", - "outputs": { - "out_data": "out" - } - }, - "echo2": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - }, - { - "name": "user/user/fisherface/1/atnt", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "scores_dev": "scoring_dev_scores", - "scores_test": "scoring_test_scores" - }, - "algorithm": "user/eerhter_postperf/1" - } - }, - "datasets": { - "dev_probes": { - "set": "dev_probes", - "protocol": "idiap_test_eyepos", - "database": "atnt/3" - }, - "test_templates": { - "set": "test_templates", - "protocol": "idiap_test_eyepos", - "database": "atnt/3" - }, - "train": { - "set": "train", - "protocol": "idiap_test_eyepos", - "database": "atnt/3" - }, - "dev_templates": { - "set": "dev_templates", - "protocol": "idiap_test_eyepos", - "database": "atnt/3" - }, - "test_probes": { - "set": "test_probes", - "protocol": "idiap_test_eyepos", - "database": "atnt/3" - } - }, - "blocks": { - "template_builder_test": { - "inputs": { - "image": "image_gray", - "subspace_lda": "subspace_lda", - "id": "template_id", - "subspace_pca": "subspace_pca" - }, - "algorithm": "user/linear_machine_x2_projection/1", - "outputs": { - "projections": "projections" - } - }, - "linear_machine_training": { - "inputs": { - "image": "image_gray", - "client_id": "client_id" - }, - "algorithm": "user/pca_lda/1", - "outputs": { - "subspace_lda": "subspace_lda", - "subspace_pca": "subspace_pca" - } - }, - "template_builder_dev": { - "inputs": { - "image": "image_gray", - "subspace_lda": "subspace_lda", - "id": "template_id", - "subspace_pca": "subspace_pca" - }, - "algorithm": "user/linear_machine_x2_projection/1", - "outputs": { - "projections": "projections" - } - }, - "cropping_rgb_probe_test": { - "inputs": { - "image": "image", - "eye_centers": "eye_centers" - }, - "algorithm": "user/cropping_rgb/1", - "outputs": { - "cropped_image": "image_gray" - } - }, - "cropping_rgb_ubm": { - "inputs": { - "image": "image", - "eye_centers": "eye_centers" - }, - "algorithm": "user/cropping_rgb/1", - "outputs": { - "cropped_image": "image_gray" - } - }, - "cropping_rgb_template_dev": { - "inputs": { - "image": "image", - "eye_centers": "eye_centers" - }, - "algorithm": "user/cropping_rgb/1", - "outputs": { - "cropped_image": "image_gray" - } - }, - "probe_builder_test": { - "inputs": { - "image": "image_gray", - "subspace_lda": "subspace_lda", - "id": "probe_id", - "subspace_pca": "subspace_pca" - }, - "algorithm": "user/linear_machine_x2_projection/1", - "outputs": { - "projections": "projections" - } - }, - "cropping_rgb_template_test": { - "inputs": { - "image": "image", - "eye_centers": "eye_centers" - }, - "algorithm": "user/cropping_rgb/1", - "outputs": { - "cropped_image": "image_gray" - } - }, - "cropping_rgb_probe_dev": { - "inputs": { - "image": "image", - "eye_centers": "eye_centers" - }, - "algorithm": "user/cropping_rgb/1", - "outputs": { - "cropped_image": "image_gray" - } - }, - "scoring_dev": { - "inputs": { - "probe_projections": "probe_builder_dev_projections", - "comparison_ids": "dev_probes_template_ids", - "probe_id": "dev_probes_probe_id", - "template_id": "dev_templates_template_id", - "probe_client_id": "dev_probes_client_id", - "template_client_id": "dev_templates_client_id", - "template_projections": "template_builder_dev_projections" - }, - "algorithm": "user/linear_machines_scoring/1", - "outputs": { - "scores": "scores" - } - }, - "scoring_test": { - "inputs": { - "probe_projections": "probe_builder_test_projections", - "comparison_ids": "test_probes_template_ids", - "probe_id": "test_probes_probe_id", - "template_id": "test_templates_template_id", - "probe_client_id": "test_probes_client_id", - "template_client_id": "test_templates_client_id", - "template_projections": "template_builder_test_projections" - }, - "algorithm": "user/linear_machines_scoring/1", - "outputs": { - "scores": "scores" - } - }, - "probe_builder_dev": { - "inputs": { - "image": "image_gray", - "subspace_lda": "subspace_lda", - "id": "probe_id", - "subspace_pca": "subspace_pca" - }, - "algorithm": "user/linear_machine_x2_projection/1", - "outputs": { - "projections": "projections" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - }, - "user/pca_lda/1": { - "number-of-pca-components": 5, - "number-of-lda-components": 2 - }, - "user/cropping_rgb/1": { - "left-eye-x": 48, - "left-eye-y": 16, - "crop-height": 80, - "crop-width": 64, - "right-eye-x": 15, - "right-eye-y": 16 - } - } - } - }, - { - "name": "user/user/single/1/single_add2", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_add/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - }, - "user/integers_add/1": { - "offset": 2 - } - } - } - }, - { - "name": "user/user/single/1/single_add", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_add/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - }, - "user/integers_add/1": { - "offset": 2 - } - } - } - }, - { - "name": "user/user/single/1/single", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - }, - { - "name": "user/user/single/1/single_large", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_mean_analyzer/1", - "parameters": {} - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol2", - "database": "simple/1" - } - }, - "blocks": { - "echo": { - "inputs": { - "in_data": "in" - }, - "nb_slots": 2, - "algorithm": "user/integers_echo/1", - "parameters": {}, - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - }, - { - "name": "user/user/single/1/single_sleep", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_sleep/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - }, - { - "name": "user/user/triangle/1/triangle", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - }, - "set2": { - "set": "set2", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo1": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo/1", - "outputs": { - "out_data": "out" - } - }, - "echo2": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo/1", - "outputs": { - "out_data": "out" - } - }, - "echo3": { - "inputs": { - "in_data2": "in2", - "in_data": "in" - }, - "algorithm": "user/integers_echo_ignore/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - }, - { - "name": "user/user/triangle/1/triangle_sleep", - "contents": { - "analyzers": { - "analysis": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_analyzer/1" - } - }, - "datasets": { - "set": { - "set": "set", - "protocol": "protocol", - "database": "simple/1" - }, - "set2": { - "set": "set2", - "protocol": "protocol", - "database": "simple/1" - } - }, - "blocks": { - "echo1": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_sleep/1", - "outputs": { - "out_data": "out" - } - }, - "echo2": { - "inputs": { - "in_data": "in" - }, - "algorithm": "user/integers_echo_sleep/1", - "outputs": { - "out_data": "out" - } - }, - "echo3": { - "inputs": { - "in_data2": "in2", - "in_data": "in" - }, - "algorithm": "user/integers_echo_ignore/1", - "outputs": { - "out_data": "out" - } - } - }, - "globals": { - "queue": "queue", - "environment": { - "version": "1.2.0", - "name": "Python 2.7" - } - } - } - } -] diff --git a/conda/js/test/test_libs.json b/conda/js/test/test_libs.json deleted file mode 100644 index 33d74de3..00000000 --- a/conda/js/test/test_libs.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "name": "user/anotherlib/1", - "contents": { - "uses": {}, - "language": "python" - } - }, - { - "name": "user/thelib/1", - "contents": { - "uses": { - "lib": "user/anotherlib/1" - }, - "language": "python" - } - } -] diff --git a/conda/js/test/test_plotterparameters.json b/conda/js/test/test_plotterparameters.json deleted file mode 100644 index 70b68418..00000000 --- a/conda/js/test/test_plotterparameters.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "name": "plot/bar/1", - "contents": { - "description": "Default parameters for bar plots", - "plotter": "plot/bar/1", - "data": { - "title-fontsize": 12, - "bar-norm": true, - "axis-fontsize": 10, - "height": 600, - "width": 800, - "grid": true, - "bar-alpha": 0.75, - "legend-fontsize": 8, - "legend-loc": "best", - "dpi": 120 - } - } - }, - { - "name": "plot/isoroc/1", - "contents": { - "description": "Default parameters for an ISO/ROC curve", - "plotter": "plot/isoroc/1", - "data": { - "ylim-bottom": 0, - "title-fontsize": 12, - "axis-fontsize": 10, - "height": 600, - "width": 800, - "grid": true, - "ylim-top": 100, - "xlim-right": 100, - "legend-fontsize": 8, - "legend-loc": "best", - "xlim-left": 0, - "dpi": 120 - } - } - } -] diff --git a/conda/js/test/test_plotters.json b/conda/js/test/test_plotters.json deleted file mode 100644 index e77da6e8..00000000 --- a/conda/js/test/test_plotters.json +++ /dev/null @@ -1,341 +0,0 @@ -[ - { - "name": "plot/bar/1", - "contents": { - "description": "Basic bar plotter for simple histograms", - "language": "python", - "parameters": { - "axis-fontsize": { - "default": 10, - "description": "Controls the axis font size (labels and values)", - "type": "uint16" - }, - "bar-alpha": { - "default": 0.75, - "description": "Value for the alpha effect in the bar plot", - "type": "float64" - }, - "bar-norm": { - "default": true, - "description": "If set to true will normalize the distribution between 0-1", - "type": "bool" - }, - "bar_attributes": { - "default": "", - "description": "Bar attributes passed directly to Matplotlib", - "type": "string" - }, - "content_type": { - "choice": [ - "image/png", - "image/jpeg", - "application/pdf" - ], - "default": "image/png", - "description": "The type of image returned", - "type": "string" - }, - "dpi": { - "default": 60, - "description": "Dots-per-inch in raster image formats", - "type": "uint16" - }, - "grid": { - "default": false, - "description": "If we should draw grid lines or not for the plot", - "type": "bool" - }, - "height": { - "default": 300, - "description": "Height of the resulting image in pixels", - "type": "uint16" - }, - "legend": { - "default": "", - "description": "Short description of the data, to be added to the plot", - "type": "string" - }, - "legend-bbox-to-anchor": { - "default": "1.0&1.0", - "description": "Specify any arbitrary location for the legend ", - "type": "string" - }, - "legend-fontsize": { - "default": 12, - "description": "Controls the font size of the legend", - "type": "uint16" - }, - "legend-loc": { - "default": "best", - "description": "The location of the legend", - "type": "string" - }, - "title": { - "default": "Bar plot", - "description": "The title for this plot", - "type": "string" - }, - "title-fontsize": { - "default": 10, - "description": "Controls the title font size", - "type": "uint16" - }, - "width": { - "default": 400, - "description": "Width of the resulting image in pixels", - "type": "uint16" - }, - "xaxis_multiplier": { - "default": 1, - "description": "The multiplication factor for the X-axis (horizontal)", - "type": "float64" - }, - "xlabel": { - "default": "", - "description": "The label of the X-axis (horizontal)", - "type": "string" - }, - "yaxis_log": { - "default": false, - "description": "If Y-axis (vertical) should be in log-scale", - "type": "bool" - }, - "yaxis_multiplier": { - "default": 1, - "description": "The multiplication factor for the Y-axis (vertical)", - "type": "float64" - }, - "ylabel": { - "default": "", - "description": "The label of the Y-axis (vertical)", - "type": "string" - } - }, - "dataformat": "plot/bar/1", - "uses": { - "baselib": "plot/baselib/1" - } - } - }, - { - "name": "plot/isoroc/1", - "contents": { - "description": "ROC/DET plotter following the ISO/IEC 19795-1:2006(E) standard", - "language": "python", - "parameters": { - "axis-fontsize": { - "default": 10, - "description": "Controls the axis font size (labels and values)", - "type": "uint16" - }, - "content_type": { - "choice": [ - "image/png", - "image/jpeg", - "application/pdf" - ], - "default": "image/png", - "description": "The type of image returned", - "type": "string" - }, - "det": { - "default": false, - "description": "If set, plot a DET curve instead of a ROC", - "type": "bool" - }, - "dpi": { - "default": 60, - "description": "Dots-per-inch in raster image formats", - "type": "uint16" - }, - "grid": { - "default": true, - "description": "If we should draw grid lines or not for the plot", - "type": "bool" - }, - "height": { - "default": 300, - "description": "Height of the resulting image in pixels", - "type": "uint16" - }, - "legend": { - "default": "", - "description": "Short description of the data, to be added to the plot", - "type": "string" - }, - "legend-fontsize": { - "default": 12, - "description": "Controls the font size of the legend", - "type": "uint16" - }, - "legend-loc": { - "default": "best", - "description": "The location of the legend", - "type": "string" - }, - "line_attributes": { - "default": "", - "description": "Scatter/Line attributes passed directly to Matplotlib", - "type": "string" - }, - "title": { - "default": "ISO/IEC 19795-1:2006(E) ROC", - "description": "The title for this plot", - "type": "string" - }, - "title-fontsize": { - "default": 10, - "description": "Controls the title font size", - "type": "uint16" - }, - "width": { - "default": 400, - "description": "Width of the resulting image in pixels", - "type": "uint16" - }, - "xaxis_log": { - "default": false, - "description": "If X-axis (horizontal) should be in log-scale", - "type": "bool" - }, - "xaxis_multiplier": { - "default": "100.0", - "description": "The multiplication factor for the X-axis (horizontal)", - "type": "float64" - }, - "xlabel": { - "default": "False Positives (False Match Rate), in %", - "description": "The label of the X-axis (horizontal)", - "type": "string" - }, - "xlim-left": { - "default": "0.0", - "description": "", - "type": "float64" - }, - "xlim-right": { - "default": "100.0", - "description": "", - "type": "float64" - }, - "yaxis_log": { - "default": false, - "description": "If Y-axis (vertical) should be in log-scale", - "type": "bool" - }, - "yaxis_multiplier": { - "default": "100.0", - "description": "The multiplication factor for the Y-axis (vertical)", - "type": "float64" - }, - "ylabel": { - "default": "True Positives (1 - False Non-Match Rate), in %", - "description": "The label of the Y-axis (vertical)", - "type": "string" - }, - "ylim-bottom": { - "default": "0.0", - "description": "", - "type": "float64" - }, - "ylim-top": { - "default": "100.0", - "description": "", - "type": "float64" - } - }, - "dataformat": "plot/isoroc/1", - "uses": { - "baselib": "plot/baselib/1" - } - } - }, - { - "name": "plot/scatter/1", - "contents": { - "description": "Basic scatter plotter for simple lines", - "language": "python", - "parameters": { - "content_type": { - "choice": [ - "image/png", - "image/jpeg", - "application/pdf" - ], - "default": "image/png", - "description": "The type of image returned", - "type": "string" - }, - "dpi": { - "default": 60, - "description": "Dots-per-inch in raster image formats", - "type": "uint16" - }, - "grid": { - "default": false, - "description": "If we should draw grid lines or not for the plot", - "type": "bool" - }, - "height": { - "default": 300, - "description": "Height of the resulting image in pixels", - "type": "uint16" - }, - "legend": { - "default": "", - "description": "Short description of the data, to be added to the plot", - "type": "string" - }, - "line_attributes": { - "default": "", - "description": "Scatter/Line attributes passed directly to Matplotlib", - "type": "string" - }, - "title": { - "default": "Scatter plot", - "description": "The title for this plot", - "type": "string" - }, - "width": { - "default": 400, - "description": "Width of the resulting image in pixels", - "type": "uint16" - }, - "xaxis_log": { - "default": false, - "description": "If X-axis (horizontal) should be in log-scale", - "type": "bool" - }, - "xaxis_multiplier": { - "default": "1.0", - "description": "The multiplication factor for the X-axis (horizontal)", - "type": "float64" - }, - "xlabel": { - "default": "X", - "description": "The label of the X-axis (horizontal)", - "type": "string" - }, - "yaxis_log": { - "default": false, - "description": "If Y-axis (vertical) should be in log-scale", - "type": "bool" - }, - "yaxis_multiplier": { - "default": "1.0", - "description": "The multiplication factor for the Y-axis (vertical)", - "type": "float64" - }, - "ylabel": { - "default": "Y", - "description": "The label of the Y-axis (vertical)", - "type": "string" - } - }, - "dataformat": "plot/scatter/1", - "uses": { - "baselib": "plot/baselib/1" - } - } - } -] diff --git a/conda/js/test/test_tcs.json b/conda/js/test/test_tcs.json deleted file mode 100644 index 4ccebb7c..00000000 --- a/conda/js/test/test_tcs.json +++ /dev/null @@ -1,2934 +0,0 @@ -[ - { - "name": "test/iris_advanced/1", - "contents": { - "analyzers": [ - { - "inputs": [ - "scores", - "species" - ], - "name": "analyzer", - "synchronized_channel": "testing_data" - } - ], - "blocks": [ - { - "inputs": [ - "measurements", - "species" - ], - "name": "training_alg", - "outputs": [ - "lda_machine" - ], - "synchronized_channel": "training_data" - }, - { - "inputs": [ - "lda_machine", - "measurements" - ], - "name": "testing_alg", - "outputs": [ - "scores" - ], - "synchronized_channel": "testing_data" - }, - { - "inputs": [ - "measurements" - ], - "name": "pre_training", - "outputs": [ - "measurements" - ], - "synchronized_channel": "training_data" - }, - { - "inputs": [ - "measurements" - ], - "name": "pre_testing", - "outputs": [ - "measurements" - ], - "synchronized_channel": "testing_data" - } - ], - "connections": [ - { - "channel": "testing_data", - "from": "testing_alg.scores", - "to": "analyzer.scores" - }, - { - "channel": "training_data", - "from": "training_alg.lda_machine", - "to": "testing_alg.lda_machine" - }, - { - "channel": "testing_data", - "from": "testing_data.species", - "to": "analyzer.species" - }, - { - "channel": "training_data", - "from": "training_data.species", - "to": "training_alg.species" - }, - { - "channel": "training_data", - "from": "training_data.measurements", - "to": "pre_training.measurements" - }, - { - "channel": "training_data", - "from": "pre_training.measurements", - "to": "training_alg.measurements" - }, - { - "channel": "testing_data", - "from": "testing_data.measurements", - "to": "pre_testing.measurements" - }, - { - "channel": "testing_data", - "from": "pre_testing.measurements", - "to": "testing_alg.measurements" - } - ], - "datasets": [ - { - "name": "training_data", - "outputs": [ - "measurements", - "species" - ] - }, - { - "name": "testing_data", - "outputs": [ - "measurements", - "species" - ] - } - ], - "description": "", - "representation": { - "blocks": { - "analyzer": { - "col": 59, - "height": 3, - "row": 6, - "width": 10 - }, - "pre_testing": { - "col": 19, - "height": 3, - "row": 5, - "width": 10 - }, - "pre_training": { - "col": 19, - "height": 3, - "row": 0, - "width": 10 - }, - "testing_alg": { - "col": 46, - "height": 3, - "row": 5, - "width": 10 - }, - "testing_data": { - "col": 6, - "height": 3, - "row": 6, - "width": 10 - }, - "training_alg": { - "col": 32, - "height": 3, - "row": 1, - "width": 10 - }, - "training_data": { - "col": 6, - "height": 3, - "row": 1, - "width": 10 - } - }, - "channel_colors": { - "testing_data": "#ff00ff", - "training_data": "#00ff00" - }, - "connections": { - "pre_testing.measurements/testing_alg.measurements": [], - "pre_training.measurements/training_alg.measurements": [], - "testing_alg.scores/analyzer.scores": [], - "testing_data.measurements/pre_testing.measurements": [], - "testing_data.species/analyzer.species": [], - "training_alg.lda_machine/testing_alg.lda_machine": [], - "training_data.measurements/pre_training.measurements": [], - "training_data.species/training_alg.species": [] - } - } - } - }, - { - "name": "tutorial/eigenface/1", - "contents": { - "datasets": [ - { - "outputs": [ - "image" - ], - "name": "train" - }, - { - "outputs": [ - "template_id", - "client_id", - "image" - ], - "name": "templates" - }, - { - "outputs": [ - "probe_id", - "client_id", - "template_ids", - "image" - ], - "name": "probes" - } - ], - "blocks": [ - { - "inputs": [ - "image" - ], - "synchronized_channel": "train", - "name": "linear_machine_training", - "outputs": [ - "subspace" - ] - }, - { - "inputs": [ - "image", - "template_id", - "subspace" - ], - "synchronized_channel": "templates", - "name": "template_builder", - "outputs": [ - "projections" - ] - }, - { - "inputs": [ - "image", - "probe_id", - "subspace" - ], - "synchronized_channel": "probes", - "name": "probe_builder", - "outputs": [ - "projections" - ] - }, - { - "inputs": [ - "templates_client_id", - "templates_template_id", - "template_builder_projections", - "probes_client_id", - "probes_probe_id", - "probe_builder_projections", - "probes_template_ids" - ], - "synchronized_channel": "probes", - "name": "scoring", - "outputs": [ - "scores" - ] - } - ], - "description": "Simple Face Recognition toolchain for EigenFaces", - "analyzers": [ - { - "inputs": [ - "scores" - ], - "synchronized_channel": "probes", - "name": "analysis" - } - ], - "connections": [ - { - "to": "linear_machine_training.image", - "from": "train.image", - "channel": "train" - }, - { - "to": "template_builder.image", - "from": "templates.image", - "channel": "templates" - }, - { - "to": "template_builder.template_id", - "from": "templates.template_id", - "channel": "templates" - }, - { - "to": "template_builder.subspace", - "from": "linear_machine_training.subspace", - "channel": "train" - }, - { - "to": "probe_builder.image", - "from": "probes.image", - "channel": "probes" - }, - { - "to": "probe_builder.probe_id", - "from": "probes.probe_id", - "channel": "probes" - }, - { - "to": "probe_builder.subspace", - "from": "linear_machine_training.subspace", - "channel": "train" - }, - { - "to": "scoring.templates_client_id", - "from": "templates.client_id", - "channel": "templates" - }, - { - "to": "scoring.templates_template_id", - "from": "templates.template_id", - "channel": "templates" - }, - { - "to": "scoring.template_builder_projections", - "from": "template_builder.projections", - "channel": "templates" - }, - { - "to": "scoring.probes_client_id", - "from": "probes.client_id", - "channel": "probes" - }, - { - "to": "scoring.probes_probe_id", - "from": "probes.probe_id", - "channel": "probes" - }, - { - "to": "scoring.probe_builder_projections", - "from": "probe_builder.projections", - "channel": "probes" - }, - { - "to": "scoring.probes_template_ids", - "from": "probes.template_ids", - "channel": "probes" - }, - { - "to": "analysis.scores", - "from": "scoring.scores", - "channel": "probes" - } - ], - "representation": { - "connections": { - "templates.template_id/template_builder.template_id": [ - { - "col": 5, - "row": 7 - }, - { - "col": 6, - "row": 7 - }, - { - "col": 17, - "row": 7 - }, - { - "col": 17, - "row": 10 - }, - { - "col": 21, - "row": 10 - }, - { - "col": 22, - "row": 10 - } - ], - "templates.template_id/scoring.templates_template_id": [ - { - "col": 5, - "row": 7 - }, - { - "col": 6, - "row": 7 - }, - { - "col": 17, - "row": 7 - }, - { - "col": 17, - "row": 14 - }, - { - "col": 33, - "row": 14 - }, - { - "col": 34, - "row": 14 - } - ], - "probes.client_id/scoring.probes_client_id": [ - { - "col": 5, - "row": 20 - }, - { - "col": 6, - "row": 20 - }, - { - "col": 20, - "row": 20 - }, - { - "col": 20, - "row": 16 - }, - { - "col": 33, - "row": 16 - }, - { - "col": 34, - "row": 16 - } - ], - "templates.client_id/scoring.templates_client_id": [ - { - "col": 5, - "row": 8 - }, - { - "col": 6, - "row": 8 - }, - { - "col": 15, - "row": 8 - }, - { - "col": 15, - "row": 13 - }, - { - "col": 33, - "row": 13 - }, - { - "col": 34, - "row": 13 - } - ], - "probes.image/probe_builder.image": [ - { - "col": 5, - "row": 22 - }, - { - "col": 6, - "row": 22 - }, - { - "col": 21, - "row": 22 - }, - { - "col": 22, - "row": 22 - } - ], - "probes.probe_id/scoring.probes_probe_id": [ - { - "col": 5, - "row": 19 - }, - { - "col": 6, - "row": 19 - }, - { - "col": 17, - "row": 19 - }, - { - "col": 17, - "row": 17 - }, - { - "col": 33, - "row": 17 - }, - { - "col": 34, - "row": 17 - } - ], - "train.image/linear_machine_training.image": [ - { - "col": 5, - "row": 3 - }, - { - "col": 6, - "row": 3 - }, - { - "col": 8, - "row": 3 - }, - { - "col": 9, - "row": 3 - } - ], - "templates.image/template_builder.image": [ - { - "col": 5, - "row": 9 - }, - { - "col": 6, - "row": 9 - }, - { - "col": 21, - "row": 9 - }, - { - "col": 22, - "row": 9 - } - ], - "probe_builder.projections/scoring.probe_builder_projections": [ - { - "col": 28, - "row": 22 - }, - { - "col": 29, - "row": 22 - }, - { - "col": 31, - "row": 22 - }, - { - "col": 31, - "row": 18 - }, - { - "col": 33, - "row": 18 - }, - { - "col": 34, - "row": 18 - } - ], - "scoring.scores/analysis.scores": [ - { - "col": 40, - "row": 13 - }, - { - "col": 41, - "row": 13 - }, - { - "col": 42, - "row": 13 - }, - { - "col": 43, - "row": 13 - } - ], - "probes.probe_id/probe_builder.probe_id": [ - { - "col": 5, - "row": 19 - }, - { - "col": 6, - "row": 19 - }, - { - "col": 15, - "row": 19 - }, - { - "col": 15, - "row": 23 - }, - { - "col": 21, - "row": 23 - }, - { - "col": 22, - "row": 23 - } - ], - "template_builder.projections/scoring.template_builder_projections": [ - { - "col": 28, - "row": 9 - }, - { - "col": 29, - "row": 9 - }, - { - "col": 32, - "row": 9 - }, - { - "col": 32, - "row": 15 - }, - { - "col": 33, - "row": 15 - }, - { - "col": 34, - "row": 15 - } - ], - "linear_machine_training.subspace/probe_builder.subspace": [ - { - "col": 15, - "row": 3 - }, - { - "col": 16, - "row": 3 - }, - { - "col": 19, - "row": 3 - }, - { - "col": 19, - "row": 24 - }, - { - "col": 21, - "row": 24 - }, - { - "col": 22, - "row": 24 - } - ], - "probes.template_ids/scoring.probes_template_ids": [ - { - "col": 5, - "row": 21 - }, - { - "col": 6, - "row": 21 - }, - { - "col": 21, - "row": 21 - }, - { - "col": 21, - "row": 19 - }, - { - "col": 33, - "row": 19 - }, - { - "col": 34, - "row": 19 - } - ], - "linear_machine_training.subspace/template_builder.subspace": [ - { - "col": 15, - "row": 3 - }, - { - "col": 16, - "row": 3 - }, - { - "col": 19, - "row": 3 - }, - { - "col": 19, - "row": 11 - }, - { - "col": 21, - "row": 11 - }, - { - "col": 22, - "row": 11 - } - ] - }, - "blocks": { - "templates": { - "width": 5, - "row": 5, - "col": 0, - "height": 5 - }, - "scoring": { - "width": 6, - "row": 11, - "col": 34, - "height": 9 - }, - "template_builder": { - "width": 6, - "row": 7, - "col": 22, - "height": 5 - }, - "linear_machine_training": { - "width": 6, - "row": 1, - "col": 9, - "height": 3 - }, - "analysis": { - "width": 6, - "row": 11, - "col": 43, - "height": 3 - }, - "probe_builder": { - "width": 6, - "row": 20, - "col": 22, - "height": 5 - }, - "train": { - "width": 5, - "row": 1, - "col": 0, - "height": 3 - }, - "probes": { - "width": 5, - "row": 17, - "col": 0, - "height": 6 - } - }, - "channel_colors": { - "templates": "#6AA84F", - "train": "#0000FF", - "probes": "#CC0000" - } - } - } - }, - { - "name": "user/double/1", - "contents": { - "datasets": [ - { - "outputs": [ - "out" - ], - "name": "set" - } - ], - "blocks": [ - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "echo1", - "outputs": [ - "out" - ] - }, - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "echo2", - "outputs": [ - "out" - ] - } - ], - "description": "Double integer echoing from a single database channel", - "analyzers": [ - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "analysis" - } - ], - "connections": [ - { - "to": "echo1.in", - "from": "set.out", - "channel": "set" - }, - { - "to": "echo2.in", - "from": "echo1.out", - "channel": "set" - }, - { - "to": "analysis.in", - "from": "echo2.out", - "channel": "set" - } - ], - "representation": { - "connections": { - "set.out/echo1.in": [ - { - "col": 4, - "row": 2 - }, - { - "col": 5, - "row": 2 - }, - { - "col": 6, - "row": 2 - }, - { - "col": 7, - "row": 2 - } - ], - "echo2.out/analysis.in": [ - { - "col": 22, - "row": 2 - }, - { - "col": 23, - "row": 2 - }, - { - "col": 24, - "row": 2 - }, - { - "col": 25, - "row": 2 - } - ], - "echo1.out/echo2.in": [ - { - "col": 13, - "row": 2 - }, - { - "col": 14, - "row": 2 - }, - { - "col": 15, - "row": 2 - }, - { - "col": 16, - "row": 2 - } - ] - }, - "blocks": { - "set": { - "width": 5, - "row": 0, - "col": -1, - "height": 3 - }, - "echo2": { - "width": 6, - "row": 0, - "col": 16, - "height": 3 - }, - "analysis": { - "width": 6, - "row": 0, - "col": 25, - "height": 3 - }, - "echo1": { - "width": 6, - "row": 0, - "col": 7, - "height": 3 - } - }, - "channel_colors": { - "set": "#0000FF" - } - } - } - }, - { - "name": "user/fisherface/1", - "contents": { - "datasets": [ - { - "outputs": [ - "image", - "client_id", - "eye_centers" - ], - "name": "train" - }, - { - "outputs": [ - "image", - "template_id", - "client_id", - "eye_centers" - ], - "name": "dev_templates" - }, - { - "outputs": [ - "image", - "probe_id", - "client_id", - "template_ids", - "eye_centers" - ], - "name": "dev_probes" - }, - { - "outputs": [ - "image", - "template_id", - "client_id", - "eye_centers" - ], - "name": "test_templates" - }, - { - "outputs": [ - "image", - "probe_id", - "client_id", - "template_ids", - "eye_centers" - ], - "name": "test_probes" - } - ], - "blocks": [ - { - "inputs": [ - "image", - "eye_centers" - ], - "synchronized_channel": "train", - "name": "cropping_rgb_ubm", - "outputs": [ - "image_gray" - ] - }, - { - "inputs": [ - "image", - "eye_centers" - ], - "synchronized_channel": "dev_templates", - "name": "cropping_rgb_template_dev", - "outputs": [ - "image_gray" - ] - }, - { - "inputs": [ - "image", - "eye_centers" - ], - "synchronized_channel": "dev_probes", - "name": "cropping_rgb_probe_dev", - "outputs": [ - "image_gray" - ] - }, - { - "inputs": [ - "image", - "eye_centers" - ], - "synchronized_channel": "test_templates", - "name": "cropping_rgb_template_test", - "outputs": [ - "image_gray" - ] - }, - { - "inputs": [ - "image", - "eye_centers" - ], - "synchronized_channel": "test_probes", - "name": "cropping_rgb_probe_test", - "outputs": [ - "image_gray" - ] - }, - { - "inputs": [ - "image_gray", - "client_id" - ], - "synchronized_channel": "train", - "name": "linear_machine_training", - "outputs": [ - "subspace_pca", - "subspace_lda" - ] - }, - { - "inputs": [ - "image_gray", - "template_id", - "subspace_pca", - "subspace_lda" - ], - "synchronized_channel": "dev_templates", - "name": "template_builder_dev", - "outputs": [ - "projections" - ] - }, - { - "inputs": [ - "image_gray", - "probe_id", - "subspace_pca", - "subspace_lda" - ], - "synchronized_channel": "dev_probes", - "name": "probe_builder_dev", - "outputs": [ - "projections" - ] - }, - { - "inputs": [ - "dev_templates_client_id", - "dev_templates_template_id", - "template_builder_dev_projections", - "dev_probes_client_id", - "dev_probes_probe_id", - "probe_builder_dev_projections", - "dev_probes_template_ids" - ], - "synchronized_channel": "dev_probes", - "name": "scoring_dev", - "outputs": [ - "scores" - ] - }, - { - "inputs": [ - "image_gray", - "template_id", - "subspace_pca", - "subspace_lda" - ], - "synchronized_channel": "test_templates", - "name": "template_builder_test", - "outputs": [ - "projections" - ] - }, - { - "inputs": [ - "image_gray", - "probe_id", - "subspace_pca", - "subspace_lda" - ], - "synchronized_channel": "test_probes", - "name": "probe_builder_test", - "outputs": [ - "projections" - ] - }, - { - "inputs": [ - "test_templates_client_id", - "test_templates_template_id", - "template_builder_test_projections", - "test_probes_client_id", - "test_probes_probe_id", - "probe_builder_test_projections", - "test_probes_template_ids" - ], - "synchronized_channel": "test_probes", - "name": "scoring_test", - "outputs": [ - "scores" - ] - } - ], - "description": "Fisher-faces for Face Recognition", - "analyzers": [ - { - "inputs": [ - "scoring_dev_scores", - "scoring_test_scores" - ], - "synchronized_channel": "test_probes", - "name": "analysis" - } - ], - "connections": [ - { - "to": "cropping_rgb_ubm.image", - "from": "train.image", - "channel": "train" - }, - { - "to": "cropping_rgb_ubm.eye_centers", - "from": "train.eye_centers", - "channel": "train" - }, - { - "to": "cropping_rgb_template_dev.image", - "from": "dev_templates.image", - "channel": "dev_templates" - }, - { - "to": "cropping_rgb_template_dev.eye_centers", - "from": "dev_templates.eye_centers", - "channel": "dev_templates" - }, - { - "to": "cropping_rgb_probe_dev.image", - "from": "dev_probes.image", - "channel": "dev_probes" - }, - { - "to": "cropping_rgb_probe_dev.eye_centers", - "from": "dev_probes.eye_centers", - "channel": "dev_probes" - }, - { - "to": "cropping_rgb_template_test.image", - "from": "test_templates.image", - "channel": "test_templates" - }, - { - "to": "cropping_rgb_template_test.eye_centers", - "from": "test_templates.eye_centers", - "channel": "test_templates" - }, - { - "to": "cropping_rgb_probe_test.image", - "from": "test_probes.image", - "channel": "test_probes" - }, - { - "to": "cropping_rgb_probe_test.eye_centers", - "from": "test_probes.eye_centers", - "channel": "test_probes" - }, - { - "to": "linear_machine_training.image_gray", - "from": "cropping_rgb_ubm.image_gray", - "channel": "train" - }, - { - "to": "linear_machine_training.client_id", - "from": "train.client_id", - "channel": "train" - }, - { - "to": "template_builder_dev.image_gray", - "from": "cropping_rgb_template_dev.image_gray", - "channel": "dev_templates" - }, - { - "to": "template_builder_dev.template_id", - "from": "dev_templates.template_id", - "channel": "dev_templates" - }, - { - "to": "template_builder_dev.subspace_pca", - "from": "linear_machine_training.subspace_pca", - "channel": "train" - }, - { - "to": "template_builder_dev.subspace_lda", - "from": "linear_machine_training.subspace_lda", - "channel": "train" - }, - { - "to": "probe_builder_dev.image_gray", - "from": "cropping_rgb_probe_dev.image_gray", - "channel": "dev_probes" - }, - { - "to": "probe_builder_dev.probe_id", - "from": "dev_probes.probe_id", - "channel": "dev_probes" - }, - { - "to": "probe_builder_dev.subspace_pca", - "from": "linear_machine_training.subspace_pca", - "channel": "train" - }, - { - "to": "probe_builder_dev.subspace_lda", - "from": "linear_machine_training.subspace_lda", - "channel": "train" - }, - { - "to": "scoring_dev.dev_templates_client_id", - "from": "dev_templates.client_id", - "channel": "dev_templates" - }, - { - "to": "scoring_dev.dev_templates_template_id", - "from": "dev_templates.template_id", - "channel": "dev_templates" - }, - { - "to": "scoring_dev.template_builder_dev_projections", - "from": "template_builder_dev.projections", - "channel": "dev_templates" - }, - { - "to": "scoring_dev.dev_probes_client_id", - "from": "dev_probes.client_id", - "channel": "dev_probes" - }, - { - "to": "scoring_dev.dev_probes_probe_id", - "from": "dev_probes.probe_id", - "channel": "dev_probes" - }, - { - "to": "scoring_dev.probe_builder_dev_projections", - "from": "probe_builder_dev.projections", - "channel": "dev_probes" - }, - { - "to": "scoring_dev.dev_probes_template_ids", - "from": "dev_probes.template_ids", - "channel": "dev_probes" - }, - { - "to": "template_builder_test.image_gray", - "from": "cropping_rgb_template_test.image_gray", - "channel": "test_templates" - }, - { - "to": "template_builder_test.template_id", - "from": "test_templates.template_id", - "channel": "test_templates" - }, - { - "to": "template_builder_test.subspace_pca", - "from": "linear_machine_training.subspace_pca", - "channel": "train" - }, - { - "to": "template_builder_test.subspace_lda", - "from": "linear_machine_training.subspace_lda", - "channel": "train" - }, - { - "to": "probe_builder_test.image_gray", - "from": "cropping_rgb_probe_test.image_gray", - "channel": "test_probes" - }, - { - "to": "probe_builder_test.probe_id", - "from": "test_probes.probe_id", - "channel": "test_probes" - }, - { - "to": "probe_builder_test.subspace_pca", - "from": "linear_machine_training.subspace_pca", - "channel": "train" - }, - { - "to": "probe_builder_test.subspace_lda", - "from": "linear_machine_training.subspace_lda", - "channel": "train" - }, - { - "to": "scoring_test.test_templates_client_id", - "from": "test_templates.client_id", - "channel": "test_templates" - }, - { - "to": "scoring_test.test_templates_template_id", - "from": "test_templates.template_id", - "channel": "test_templates" - }, - { - "to": "scoring_test.template_builder_test_projections", - "from": "template_builder_test.projections", - "channel": "test_templates" - }, - { - "to": "scoring_test.test_probes_client_id", - "from": "test_probes.client_id", - "channel": "test_probes" - }, - { - "to": "scoring_test.test_probes_probe_id", - "from": "test_probes.probe_id", - "channel": "test_probes" - }, - { - "to": "scoring_test.probe_builder_test_projections", - "from": "probe_builder_test.projections", - "channel": "test_probes" - }, - { - "to": "scoring_test.test_probes_template_ids", - "from": "test_probes.template_ids", - "channel": "test_probes" - }, - { - "to": "analysis.scoring_dev_scores", - "from": "scoring_dev.scores", - "channel": "dev_probes" - }, - { - "to": "analysis.scoring_test_scores", - "from": "scoring_test.scores", - "channel": "test_probes" - } - ], - "representation": { - "connections": { - "dev_probes.image/cropping_rgb_probe_dev.image": [ - { - "col": 6, - "row": 21 - }, - { - "col": 7, - "row": 21 - }, - { - "col": 13, - "row": 21 - }, - { - "col": 13, - "row": 19 - }, - { - "col": 43, - "row": 19 - }, - { - "col": 44, - "row": 19 - } - ], - "dev_templates.eye_centers/cropping_rgb_template_dev.eye_centers": [ - { - "col": 6, - "row": 16 - }, - { - "col": 7, - "row": 16 - }, - { - "col": 15, - "row": 16 - }, - { - "col": 15, - "row": 12 - }, - { - "col": 19, - "row": 12 - }, - { - "col": 20, - "row": 12 - } - ], - "train.eye_centers/cropping_rgb_ubm.eye_centers": [ - { - "col": 6, - "row": 8 - }, - { - "col": 7, - "row": 8 - }, - { - "col": 9, - "row": 8 - }, - { - "col": 9, - "row": 5 - }, - { - "col": 11, - "row": 5 - }, - { - "col": 12, - "row": 5 - } - ], - "train.image/cropping_rgb_ubm.image": [ - { - "col": 6, - "row": 6 - }, - { - "col": 7, - "row": 6 - }, - { - "col": 8, - "row": 6 - }, - { - "col": 8, - "row": 4 - }, - { - "col": 11, - "row": 4 - }, - { - "col": 12, - "row": 4 - } - ], - "test_probes.eye_centers/cropping_rgb_probe_test.eye_centers": [ - { - "col": 6, - "row": 42 - }, - { - "col": 7, - "row": 42 - }, - { - "col": 13, - "row": 42 - }, - { - "col": 13, - "row": 50 - }, - { - "col": 18, - "row": 50 - }, - { - "col": 19, - "row": 50 - } - ], - "test_templates.eye_centers/cropping_rgb_template_test.eye_centers": [ - { - "col": 6, - "row": 33 - }, - { - "col": 7, - "row": 33 - }, - { - "col": 13, - "row": 33 - }, - { - "col": 13, - "row": 36 - }, - { - "col": 17, - "row": 36 - }, - { - "col": 18, - "row": 36 - } - ], - "dev_probes.probe_id/probe_builder_dev.probe_id": [ - { - "col": 6, - "row": 22 - }, - { - "col": 7, - "row": 22 - }, - { - "col": 57, - "row": 22 - }, - { - "col": 58, - "row": 22 - } - ], - "scoring_test.scores/analysis.scoring_test_scores": [ - { - "col": 75, - "row": 40 - }, - { - "col": 76, - "row": 40 - }, - { - "col": 78, - "row": 40 - }, - { - "col": 78, - "row": 37 - }, - { - "col": 80, - "row": 37 - }, - { - "col": 81, - "row": 37 - } - ], - "cropping_rgb_ubm.image_gray/linear_machine_training.image_gray": [ - { - "col": 18, - "row": 4 - }, - { - "col": 19, - "row": 4 - }, - { - "col": 21, - "row": 4 - }, - { - "col": 22, - "row": 4 - } - ], - "dev_templates.client_id/scoring_dev.dev_templates_client_id": [ - { - "col": 6, - "row": 15 - }, - { - "col": 7, - "row": 15 - }, - { - "col": 12, - "row": 15 - }, - { - "col": 12, - "row": 26 - }, - { - "col": 68, - "row": 26 - }, - { - "col": 69, - "row": 26 - } - ], - "linear_machine_training.subspace_lda/template_builder_test.subspace_lda": [ - { - "col": 28, - "row": 5 - }, - { - "col": 29, - "row": 5 - }, - { - "col": 35, - "row": 5 - }, - { - "col": 35, - "row": 38 - }, - { - "col": 38, - "row": 38 - }, - { - "col": 39, - "row": 38 - } - ], - "test_templates.client_id/scoring_test.test_templates_client_id": [ - { - "col": 6, - "row": 32 - }, - { - "col": 7, - "row": 32 - }, - { - "col": 12, - "row": 32 - }, - { - "col": 12, - "row": 40 - }, - { - "col": 68, - "row": 40 - }, - { - "col": 69, - "row": 40 - } - ], - "test_probes.template_ids/scoring_test.test_probes_template_ids": [ - { - "col": 6, - "row": 41 - }, - { - "col": 7, - "row": 41 - }, - { - "col": 7, - "row": 46 - }, - { - "col": 68, - "row": 46 - }, - { - "col": 69, - "row": 46 - } - ], - "test_probes.probe_id/probe_builder_test.probe_id": [ - { - "col": 6, - "row": 39 - }, - { - "col": 7, - "row": 39 - }, - { - "col": 29, - "row": 39 - }, - { - "col": 29, - "row": 50 - }, - { - "col": 47, - "row": 50 - }, - { - "col": 48, - "row": 50 - } - ], - "test_templates.image/cropping_rgb_template_test.image": [ - { - "col": 6, - "row": 30 - }, - { - "col": 7, - "row": 30 - }, - { - "col": 16, - "row": 30 - }, - { - "col": 16, - "row": 35 - }, - { - "col": 17, - "row": 35 - }, - { - "col": 18, - "row": 35 - } - ], - "template_builder_test.projections/scoring_test.template_builder_test_projections": [ - { - "col": 45, - "row": 35 - }, - { - "col": 46, - "row": 35 - }, - { - "col": 47, - "row": 35 - }, - { - "col": 47, - "row": 42 - }, - { - "col": 68, - "row": 42 - }, - { - "col": 69, - "row": 42 - } - ], - "test_templates.template_id/scoring_test.test_templates_template_id": [ - { - "col": 6, - "row": 31 - }, - { - "col": 7, - "row": 31 - }, - { - "col": 11, - "row": 31 - }, - { - "col": 11, - "row": 41 - }, - { - "col": 68, - "row": 41 - }, - { - "col": 69, - "row": 41 - } - ], - "linear_machine_training.subspace_pca/template_builder_dev.subspace_pca": [ - { - "col": 28, - "row": 4 - }, - { - "col": 29, - "row": 4 - }, - { - "col": 39, - "row": 4 - }, - { - "col": 39, - "row": 13 - }, - { - "col": 43, - "row": 13 - }, - { - "col": 44, - "row": 13 - } - ], - "cropping_rgb_template_test.image_gray/template_builder_test.image_gray": [ - { - "col": 24, - "row": 35 - }, - { - "col": 25, - "row": 35 - }, - { - "col": 38, - "row": 35 - }, - { - "col": 39, - "row": 35 - } - ], - "probe_builder_dev.projections/scoring_dev.probe_builder_dev_projections": [ - { - "col": 64, - "row": 21 - }, - { - "col": 65, - "row": 21 - }, - { - "col": 66, - "row": 21 - }, - { - "col": 66, - "row": 31 - }, - { - "col": 68, - "row": 31 - }, - { - "col": 69, - "row": 31 - } - ], - "train.client_id/linear_machine_training.client_id": [ - { - "col": 6, - "row": 7 - }, - { - "col": 7, - "row": 7 - }, - { - "col": 20, - "row": 7 - }, - { - "col": 20, - "row": 5 - }, - { - "col": 21, - "row": 5 - }, - { - "col": 22, - "row": 5 - } - ], - "dev_probes.client_id/scoring_dev.dev_probes_client_id": [ - { - "col": 6, - "row": 23 - }, - { - "col": 7, - "row": 23 - }, - { - "col": 28, - "row": 23 - }, - { - "col": 28, - "row": 29 - }, - { - "col": 68, - "row": 29 - }, - { - "col": 69, - "row": 29 - } - ], - "probe_builder_test.projections/scoring_test.probe_builder_test_projections": [ - { - "col": 54, - "row": 49 - }, - { - "col": 55, - "row": 49 - }, - { - "col": 57, - "row": 49 - }, - { - "col": 57, - "row": 45 - }, - { - "col": 68, - "row": 45 - }, - { - "col": 69, - "row": 45 - } - ], - "test_probes.client_id/scoring_test.test_probes_client_id": [ - { - "col": 6, - "row": 40 - }, - { - "col": 7, - "row": 40 - }, - { - "col": 9, - "row": 40 - }, - { - "col": 9, - "row": 43 - }, - { - "col": 68, - "row": 43 - }, - { - "col": 69, - "row": 43 - } - ], - "linear_machine_training.subspace_pca/probe_builder_test.subspace_pca": [ - { - "col": 28, - "row": 4 - }, - { - "col": 29, - "row": 4 - }, - { - "col": 36, - "row": 4 - }, - { - "col": 36, - "row": 51 - }, - { - "col": 47, - "row": 51 - }, - { - "col": 48, - "row": 51 - } - ], - "dev_probes.eye_centers/cropping_rgb_probe_dev.eye_centers": [ - { - "col": 6, - "row": 25 - }, - { - "col": 7, - "row": 25 - }, - { - "col": 30, - "row": 25 - }, - { - "col": 30, - "row": 20 - }, - { - "col": 43, - "row": 20 - }, - { - "col": 44, - "row": 20 - } - ], - "linear_machine_training.subspace_pca/probe_builder_dev.subspace_pca": [ - { - "col": 28, - "row": 4 - }, - { - "col": 29, - "row": 4 - }, - { - "col": 38, - "row": 4 - }, - { - "col": 38, - "row": 23 - }, - { - "col": 57, - "row": 23 - }, - { - "col": 58, - "row": 23 - } - ], - "test_templates.template_id/template_builder_test.template_id": [ - { - "col": 6, - "row": 31 - }, - { - "col": 7, - "row": 31 - }, - { - "col": 15, - "row": 31 - }, - { - "col": 15, - "row": 38 - }, - { - "col": 27, - "row": 38 - }, - { - "col": 27, - "row": 36 - }, - { - "col": 38, - "row": 36 - }, - { - "col": 39, - "row": 36 - } - ], - "test_probes.image/cropping_rgb_probe_test.image": [ - { - "col": 6, - "row": 38 - }, - { - "col": 7, - "row": 38 - }, - { - "col": 10, - "row": 38 - }, - { - "col": 10, - "row": 49 - }, - { - "col": 18, - "row": 49 - }, - { - "col": 19, - "row": 49 - } - ], - "linear_machine_training.subspace_lda/probe_builder_dev.subspace_lda": [ - { - "col": 28, - "row": 5 - }, - { - "col": 29, - "row": 5 - }, - { - "col": 32, - "row": 5 - }, - { - "col": 32, - "row": 24 - }, - { - "col": 57, - "row": 24 - }, - { - "col": 58, - "row": 24 - } - ], - "test_probes.probe_id/scoring_test.test_probes_probe_id": [ - { - "col": 6, - "row": 39 - }, - { - "col": 7, - "row": 39 - }, - { - "col": 8, - "row": 39 - }, - { - "col": 8, - "row": 44 - }, - { - "col": 68, - "row": 44 - }, - { - "col": 69, - "row": 44 - } - ], - "dev_templates.image/cropping_rgb_template_dev.image": [ - { - "col": 6, - "row": 13 - }, - { - "col": 7, - "row": 13 - }, - { - "col": 11, - "row": 13 - }, - { - "col": 11, - "row": 11 - }, - { - "col": 19, - "row": 11 - }, - { - "col": 20, - "row": 11 - } - ], - "scoring_dev.scores/analysis.scoring_dev_scores": [ - { - "col": 75, - "row": 26 - }, - { - "col": 76, - "row": 26 - }, - { - "col": 78, - "row": 26 - }, - { - "col": 78, - "row": 36 - }, - { - "col": 80, - "row": 36 - }, - { - "col": 81, - "row": 36 - } - ], - "linear_machine_training.subspace_lda/template_builder_dev.subspace_lda": [ - { - "col": 28, - "row": 5 - }, - { - "col": 29, - "row": 5 - }, - { - "col": 34, - "row": 5 - }, - { - "col": 34, - "row": 14 - }, - { - "col": 43, - "row": 14 - }, - { - "col": 44, - "row": 14 - } - ], - "dev_templates.template_id/template_builder_dev.template_id": [ - { - "col": 6, - "row": 14 - }, - { - "col": 7, - "row": 14 - }, - { - "col": 28, - "row": 14 - }, - { - "col": 28, - "row": 12 - }, - { - "col": 43, - "row": 12 - }, - { - "col": 44, - "row": 12 - } - ], - "linear_machine_training.subspace_lda/probe_builder_test.subspace_lda": [ - { - "col": 28, - "row": 5 - }, - { - "col": 29, - "row": 5 - }, - { - "col": 33, - "row": 5 - }, - { - "col": 33, - "row": 52 - }, - { - "col": 47, - "row": 52 - }, - { - "col": 48, - "row": 52 - } - ], - "dev_probes.probe_id/scoring_dev.dev_probes_probe_id": [ - { - "col": 6, - "row": 22 - }, - { - "col": 7, - "row": 22 - }, - { - "col": 55, - "row": 22 - }, - { - "col": 55, - "row": 30 - }, - { - "col": 68, - "row": 30 - }, - { - "col": 69, - "row": 30 - } - ], - "template_builder_dev.projections/scoring_dev.template_builder_dev_projections": [ - { - "col": 50, - "row": 11 - }, - { - "col": 51, - "row": 11 - }, - { - "col": 53, - "row": 11 - }, - { - "col": 53, - "row": 28 - }, - { - "col": 68, - "row": 28 - }, - { - "col": 69, - "row": 28 - } - ], - "cropping_rgb_probe_test.image_gray/probe_builder_test.image_gray": [ - { - "col": 25, - "row": 49 - }, - { - "col": 26, - "row": 49 - }, - { - "col": 47, - "row": 49 - }, - { - "col": 48, - "row": 49 - } - ], - "dev_templates.template_id/scoring_dev.dev_templates_template_id": [ - { - "col": 6, - "row": 14 - }, - { - "col": 7, - "row": 14 - }, - { - "col": 17, - "row": 14 - }, - { - "col": 17, - "row": 27 - }, - { - "col": 68, - "row": 27 - }, - { - "col": 69, - "row": 27 - } - ], - "cropping_rgb_probe_dev.image_gray/probe_builder_dev.image_gray": [ - { - "col": 50, - "row": 19 - }, - { - "col": 51, - "row": 19 - }, - { - "col": 52, - "row": 19 - }, - { - "col": 52, - "row": 21 - }, - { - "col": 57, - "row": 21 - }, - { - "col": 58, - "row": 21 - } - ], - "linear_machine_training.subspace_pca/template_builder_test.subspace_pca": [ - { - "col": 28, - "row": 4 - }, - { - "col": 29, - "row": 4 - }, - { - "col": 37, - "row": 4 - }, - { - "col": 37, - "row": 37 - }, - { - "col": 38, - "row": 37 - }, - { - "col": 39, - "row": 37 - } - ], - "dev_probes.template_ids/scoring_dev.dev_probes_template_ids": [ - { - "col": 6, - "row": 24 - }, - { - "col": 7, - "row": 24 - }, - { - "col": 21, - "row": 24 - }, - { - "col": 21, - "row": 32 - }, - { - "col": 68, - "row": 32 - }, - { - "col": 69, - "row": 32 - } - ], - "cropping_rgb_template_dev.image_gray/template_builder_dev.image_gray": [ - { - "col": 26, - "row": 11 - }, - { - "col": 27, - "row": 11 - }, - { - "col": 43, - "row": 11 - }, - { - "col": 44, - "row": 11 - } - ] - }, - "blocks": { - "template_builder_test": { - "width": 6, - "row": 33, - "col": 39, - "height": 6 - }, - "scoring_test": { - "width": 6, - "row": 38, - "col": 69, - "height": 9 - }, - "dev_templates": { - "width": 5, - "row": 11, - "col": 1, - "height": 6 - }, - "linear_machine_training": { - "width": 6, - "row": 2, - "col": 22, - "height": 4 - }, - "template_builder_dev": { - "width": 6, - "row": 9, - "col": 44, - "height": 6 - }, - "dev_probes": { - "width": 5, - "row": 19, - "col": 1, - "height": 7 - }, - "analysis": { - "width": 6, - "row": 34, - "col": 81, - "height": 4 - }, - "test_probes": { - "width": 5, - "row": 36, - "col": 1, - "height": 7 - }, - "cropping_rgb_ubm": { - "width": 6, - "row": 2, - "col": 12, - "height": 4 - }, - "train": { - "width": 5, - "row": 4, - "col": 1, - "height": 5 - }, - "cropping_rgb_probe_test": { - "width": 6, - "row": 47, - "col": 19, - "height": 4 - }, - "probe_builder_test": { - "width": 6, - "row": 47, - "col": 48, - "height": 6 - }, - "cropping_rgb_template_test": { - "width": 6, - "row": 33, - "col": 18, - "height": 4 - }, - "cropping_rgb_probe_dev": { - "width": 6, - "row": 17, - "col": 44, - "height": 4 - }, - "scoring_dev": { - "width": 6, - "row": 24, - "col": 69, - "height": 9 - }, - "test_templates": { - "width": 5, - "row": 28, - "col": 1, - "height": 6 - }, - "cropping_rgb_template_dev": { - "width": 6, - "row": 9, - "col": 20, - "height": 4 - }, - "probe_builder_dev": { - "width": 6, - "row": 19, - "col": 58, - "height": 6 - } - }, - "channel_colors": { - "dev_probes": "#ff0000", - "test_templates": "#9900ff", - "train": "#0000FF", - "dev_templates": "#00ff00", - "test_probes": "#7F6000" - } - } - } - }, - { - "name": "user/single/1", - "contents": { - "datasets": [ - { - "outputs": [ - "out" - ], - "name": "set" - } - ], - "blocks": [ - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "echo", - "outputs": [ - "out" - ] - } - ], - "description": "Single integer echoing on a single channel", - "analyzers": [ - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "analysis" - } - ], - "connections": [ - { - "to": "echo.in", - "from": "set.out", - "channel": "set" - }, - { - "to": "analysis.in", - "from": "echo.out", - "channel": "set" - } - ], - "representation": { - "connections": { - "echo.out/analysis.in": [ - { - "col": 12, - "row": 2 - }, - { - "col": 13, - "row": 2 - }, - { - "col": 13, - "row": 2 - }, - { - "col": 14, - "row": 2 - } - ], - "set.out/echo.in": [ - { - "col": 4, - "row": 2 - }, - { - "col": 5, - "row": 2 - }, - { - "col": 5, - "row": 2 - }, - { - "col": 6, - "row": 2 - } - ] - }, - "blocks": { - "set": { - "width": 5, - "row": 0, - "col": -1, - "height": 3 - }, - "analysis": { - "width": 6, - "row": 0, - "col": 14, - "height": 3 - }, - "echo": { - "width": 6, - "row": 0, - "col": 6, - "height": 3 - } - }, - "channel_colors": { - "set": "#0000FF" - } - } - } - }, - { - "name": "user/triangle/1", - "contents": { - "datasets": [ - { - "outputs": [ - "out" - ], - "name": "set" - }, - { - "outputs": [ - "out" - ], - "name": "set2" - } - ], - "blocks": [ - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "echo1", - "outputs": [ - "out" - ] - }, - { - "inputs": [ - "in" - ], - "synchronized_channel": "set2", - "name": "echo2", - "outputs": [ - "out" - ] - }, - { - "inputs": [ - "in", - "in2" - ], - "synchronized_channel": "set", - "name": "echo3", - "outputs": [ - "out" - ] - } - ], - "description": "A single intersection of two de-synchronized channels", - "analyzers": [ - { - "inputs": [ - "in" - ], - "synchronized_channel": "set", - "name": "analysis" - } - ], - "connections": [ - { - "to": "echo1.in", - "from": "set.out", - "channel": "set" - }, - { - "to": "echo2.in", - "from": "set2.out", - "channel": "set2" - }, - { - "to": "echo3.in", - "from": "echo1.out", - "channel": "set" - }, - { - "to": "echo3.in2", - "from": "echo2.out", - "channel": "set2" - }, - { - "to": "analysis.in", - "from": "echo3.out", - "channel": "set" - } - ], - "representation": { - "connections": { - "set.out/echo1.in": [ - { - "col": 4, - "row": 2 - }, - { - "col": 5, - "row": 2 - }, - { - "col": 5, - "row": 2 - }, - { - "col": 6, - "row": 2 - } - ], - "set2.out/echo2.in": [ - { - "col": 4, - "row": 7 - }, - { - "col": 5, - "row": 7 - }, - { - "col": 5, - "row": 7 - }, - { - "col": 6, - "row": 7 - } - ], - "echo1.out/echo3.in": [ - { - "col": 12, - "row": 2 - }, - { - "col": 13, - "row": 2 - }, - { - "col": 14, - "row": 2 - }, - { - "col": 14, - "row": 4 - }, - { - "col": 15, - "row": 4 - }, - { - "col": 16, - "row": 4 - } - ], - "echo2.out/echo3.in2": [ - { - "col": 12, - "row": 7 - }, - { - "col": 13, - "row": 7 - }, - { - "col": 14, - "row": 7 - }, - { - "col": 14, - "row": 5 - }, - { - "col": 15, - "row": 5 - }, - { - "col": 16, - "row": 5 - } - ], - "echo3.out/analysis.in": [ - { - "col": 22, - "row": 4 - }, - { - "col": 23, - "row": 4 - }, - { - "col": 24, - "row": 4 - }, - { - "col": 25, - "row": 4 - } - ] - }, - "blocks": { - "set": { - "width": 5, - "row": 0, - "col": -1, - "height": 3 - }, - "set2": { - "width": 5, - "row": 5, - "col": -1, - "height": 3 - }, - "analysis": { - "width": 6, - "row": 2, - "col": 25, - "height": 3 - }, - "echo1": { - "width": 6, - "row": 0, - "col": 6, - "height": 3 - }, - "echo2": { - "width": 6, - "row": 5, - "col": 6, - "height": 3 - }, - "echo3": { - "width": 6, - "row": 2, - "col": 16, - "height": 4 - } - }, - "channel_colors": { - "set": "#0000FF", - "set2": "#6AA84F" - } - } - } - } -] diff --git a/conda/js/webpack.config.js b/conda/js/webpack.config.js deleted file mode 100644 index 391ad8e8..00000000 --- a/conda/js/webpack.config.js +++ /dev/null @@ -1,159 +0,0 @@ -/* eslint-disable */ -const { resolve } = require('path'); -var webpack = require('webpack') -const VisualizerPlugin = require('webpack-visualizer-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const TerserPlugin = require('terser-webpack-plugin') - -const dist = resolve(__dirname, '../../beat/editor/js'); - -const isExternal = (module) => module.context && module.context.indexOf('node_modules') === -1; - -module.exports = { - entry: { - main: [ - 'react-hot-loader/patch', - // all our code starts here - './main.jsx', - ] - }, - mode: 'development', - devtool: 'inline-source-map', - output: { - // use [name] for sanity checks & debugging - filename: '[name].js', - // output in './dist/' - path: dist, - publicPath: '/', - globalObject: 'this', - }, - module: { - rules: [ - // load our js files with babel-loader - { - test: /\.js(x)?$/, - loader: 'babel-loader', - // js deps shouldnt need any loaders - exclude: /node_modules/ - }, - // web/shared worker files - { - test: /\.worker\.js$/, - use: [ - 'worker-loader', - 'babel-loader', - ] - }, - // load css with: - { - test: /\.css$/, - use: [ - // style-loader -> pulls in the file initially - 'style-loader', - // css-loader -> handles css - 'css-loader', - // postcss-loader -> postprocess css (like babel for css) - 'postcss-loader' - ], - exclude: /node_modules/, - }, - { - test: /\.css$/, - use: [ - // style-loader -> pulls in the file initially - 'style-loader', - // css-loader -> handles css - 'css-loader', - ], - include: /node_modules/, - }, - // files should be handled by file-loader - { - test: /\.(png|jpeg(2)?|gif)(\?[a-z0-9]+)?$/, - loader: 'file-loader' - }, - // fonts should be handled by file-loader but with special output format - { - test: /\.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/, - loader: 'file-loader?name=fonts/[name].[ext]?[hash]' - }, - // special loader for svg - { - test: /\.(svg)(\?[a-z0-9]+)?$/, - loader: 'svg-inline-loader' - } - ] - }, - resolve: { - extensions: [ - '.js', '.jsx' - ], - alias: { - // icons - /* - 'icon': resolve(__dirname, './node_modules/feather-icons/dist/icons'), - */ - '@store': resolve(__dirname, './src/store'), - '@helpers': resolve(__dirname, './src/helpers'), - '@test': resolve(__dirname, './test'), - } - }, - devServer: { - }, - plugins: [ - //uses the index.ejs template to generate dynamic html pages based on hashes - new HtmlWebpackPlugin({ - alwaysWriteToDisk: true, - template: 'index.html' - }), - - - /******************* - * POST-PROCESSING * - *******************/ - - //generate a little viz for insight into bundle contents/sizes - new VisualizerPlugin() - ] -} - -if(process.env.NODE_ENV === 'debug'){ - // setup the devserver - module.exports.devServer = { - // use the history api if necessary - historyApiFallback: true, - - // serve the content in the output path - contentBase: dist, - - port: 9101 - } -} - -if(process.env.NODE_ENV === 'test'){ - // when testing with karma, almost all plugins are useless - module.exports.plugins = [ - new webpack.NamedModulesPlugin() - ]; - // make sure to use fancy sourcemaps - module.devtool = 'inline-source-map' -} - -// PROD -// TODO: pull out into different webpack config -if (process.env.NODE_ENV === 'production') { - module.mode = 'production'; - module.exports.output.publicPath = './'; - module.exports.plugins = [ - // make sure the env is the string 'production' - new webpack.DefinePlugin({ - 'process.env': { - // need the nested quotes! - NODE_ENV: '"production"' - } - }), - ].concat(module.exports.plugins); - module.exports.optimization = { - minimizer: [new TerserPlugin()] - }; -} -- GitLab