From e78fe22d68a524f01dbb09f9359797cd10a426ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Wed, 12 Feb 2020 16:58:19 +0100 Subject: [PATCH] [Ivette] import from old repository --- Ivette/.babelrc | 21 + Ivette/.dome-pkg-app.lock | 1 + Ivette/.dome-pkg-dev.lock | 1 + Ivette/.gitignore | 15 + Ivette/Makefile | 25 + Ivette/README.md | 25 + Ivette/backup/Configure.js | 155 + Ivette/backup/Display.js | 34 + Ivette/backup/FileMenu.js | 37 + Ivette/backup/Home.js | 134 + Ivette/backup/Project.js | 101 + Ivette/backup/ivette/index.js | 455 + Ivette/backup/ivette/plugins.js | 247 + Ivette/backup/ivette/stores.js | 152 + Ivette/backup/ivette/views.js | 42 + Ivette/backup/sandbox/Events.js | 7 + Ivette/backup/sandbox/Project.js | 206 + Ivette/backup/sandbox/Properties.js | 137 + Ivette/backup/sandbox/SourceCode.js | 129 + Ivette/backup/sandbox/SourceFiles.js | 44 + Ivette/backup/sandbox/index.js | 195 + Ivette/backup/sandbox/server.js | 226 + Ivette/backup/style.css | 50 + Ivette/electron-webpack.json | 22 + Ivette/package.json | 36 + Ivette/push-dome.sh | 31 + Ivette/src/dome/.gitignore | 47 + Ivette/src/dome/CHANGELOG.md | 1 + Ivette/src/dome/CONTRIBUTING.md | 56 + Ivette/src/dome/CONTRIBUTORS.md | 8 + Ivette/src/dome/LICENSE.md | 5 + Ivette/src/dome/Makefile | 45 + Ivette/src/dome/README.md | 57 + Ivette/src/dome/doc/README.md | 26 + Ivette/src/dome/doc/app.json | 14 + Ivette/src/dome/doc/config.json | 18 + Ivette/src/dome/doc/gallery.css | 68 + Ivette/src/dome/doc/icons.js | 82 + .../src/dome/doc/template/gallery-head.html | 15 + .../src/dome/doc/template/gallery-tail.html | 11 + Ivette/src/dome/doc/template/publish.js | 665 ++ .../static/fonts/OpenSans-Bold-webfont.eot | Bin 0 -> 19544 bytes .../static/fonts/OpenSans-Bold-webfont.svg | Bin 0 -> 118258 bytes .../static/fonts/OpenSans-Bold-webfont.woff | Bin 0 -> 22432 bytes .../fonts/OpenSans-BoldItalic-webfont.eot | Bin 0 -> 20133 bytes .../fonts/OpenSans-BoldItalic-webfont.svg | Bin 0 -> 121111 bytes .../fonts/OpenSans-BoldItalic-webfont.woff | Bin 0 -> 23048 bytes .../static/fonts/OpenSans-Italic-webfont.eot | Bin 0 -> 20265 bytes .../static/fonts/OpenSans-Italic-webfont.svg | Bin 0 -> 122494 bytes .../static/fonts/OpenSans-Italic-webfont.woff | Bin 0 -> 23188 bytes .../static/fonts/OpenSans-Light-webfont.eot | Bin 0 -> 19514 bytes .../static/fonts/OpenSans-Light-webfont.svg | Bin 0 -> 117269 bytes .../static/fonts/OpenSans-Light-webfont.woff | Bin 0 -> 22248 bytes .../fonts/OpenSans-LightItalic-webfont.eot | Bin 0 -> 20535 bytes .../fonts/OpenSans-LightItalic-webfont.svg | Bin 0 -> 122967 bytes .../fonts/OpenSans-LightItalic-webfont.woff | Bin 0 -> 23400 bytes .../static/fonts/OpenSans-Regular-webfont.eot | Bin 0 -> 19836 bytes .../static/fonts/OpenSans-Regular-webfont.svg | Bin 0 -> 119398 bytes .../fonts/OpenSans-Regular-webfont.woff | Bin 0 -> 22660 bytes .../doc/template/static/scripts/linenumber.js | 25 + .../scripts/prettify/Apache-License-2.0.txt | 202 + .../static/scripts/prettify/lang-css.js | 2 + .../static/scripts/prettify/prettify.js | 28 + .../template/static/styles/jsdoc-default.css | 496 + .../template/static/styles/prettify-jsdoc.css | 111 + .../static/styles/prettify-tomorrow.css | 132 + .../src/dome/doc/template/tmpl/augments.tmpl | 25 + .../src/dome/doc/template/tmpl/container.tmpl | 261 + .../src/dome/doc/template/tmpl/details.tmpl | 143 + .../src/dome/doc/template/tmpl/example.tmpl | 2 + .../src/dome/doc/template/tmpl/examples.tmpl | 13 + .../dome/doc/template/tmpl/exceptions.tmpl | 32 + Ivette/src/dome/doc/template/tmpl/layout.tmpl | 48 + .../src/dome/doc/template/tmpl/mainpage.tmpl | 14 + .../src/dome/doc/template/tmpl/members.tmpl | 40 + Ivette/src/dome/doc/template/tmpl/method.tmpl | 103 + Ivette/src/dome/doc/template/tmpl/params.tmpl | 76 + .../dome/doc/template/tmpl/properties.tmpl | 75 + .../src/dome/doc/template/tmpl/returns.tmpl | 25 + Ivette/src/dome/doc/template/tmpl/source.tmpl | 8 + .../src/dome/doc/template/tmpl/tutorial.tmpl | 19 + Ivette/src/dome/doc/template/tmpl/type.tmpl | 7 + Ivette/src/dome/doc/tutorials/application.md | 119 + Ivette/src/dome/doc/tutorials/dataflow.png | Bin 0 -> 48365 bytes Ivette/src/dome/doc/tutorials/development.md | 204 + Ivette/src/dome/doc/tutorials/glossary.md | 30 + Ivette/src/dome/doc/tutorials/hooks.md | 18 + Ivette/src/dome/doc/tutorials/hotreload.md | 45 + Ivette/src/dome/doc/tutorials/index.json | 9 + Ivette/src/dome/doc/tutorials/quickstart.md | 26 + Ivette/src/dome/doc/tutorials/styling.md | 63 + Ivette/src/dome/src/main/dome.js | 506 + Ivette/src/dome/src/main/menubar.js | 415 + Ivette/src/dome/src/misc/devtools.js | 12 + Ivette/src/dome/src/misc/events.js | 81 + Ivette/src/dome/src/misc/plugins.js | 97 + Ivette/src/dome/src/misc/register.js | 100 + Ivette/src/dome/src/misc/system.js | 653 ++ .../dome/src/renderer/controls/buttons.css | 257 + .../src/dome/src/renderer/controls/buttons.js | 522 ++ .../src/dome/src/renderer/controls/icons.css | 42 + .../src/dome/src/renderer/controls/icons.js | 156 + .../src/dome/src/renderer/controls/icons.json | 319 + .../src/dome/src/renderer/controls/labels.css | 18 + .../src/dome/src/renderer/controls/labels.js | 97 + Ivette/src/dome/src/renderer/dialogs.js | 318 + Ivette/src/dome/src/renderer/dnd.js | 860 ++ Ivette/src/dome/src/renderer/dome.css | 131 + Ivette/src/dome/src/renderer/dome.js | 987 ++ Ivette/src/dome/src/renderer/errors.js | 75 + Ivette/src/dome/src/renderer/layout/boxes.css | 86 + Ivette/src/dome/src/renderer/layout/boxes.js | 201 + .../src/dome/src/renderer/layout/dispatch.js | 118 + Ivette/src/dome/src/renderer/layout/forms.css | 254 + Ivette/src/dome/src/renderer/layout/forms.js | 1147 +++ Ivette/src/dome/src/renderer/layout/frames.js | 211 + Ivette/src/dome/src/renderer/layout/grids.css | 51 + Ivette/src/dome/src/renderer/layout/grids.js | 1347 +++ Ivette/src/dome/src/renderer/layout/pages.css | 81 + Ivette/src/dome/src/renderer/layout/pages.js | 81 + .../src/dome/src/renderer/layout/sidebars.css | 107 + .../src/dome/src/renderer/layout/sidebars.js | 216 + .../dome/src/renderer/layout/splitters.css | 51 + .../src/dome/src/renderer/layout/splitters.js | 389 + Ivette/src/dome/src/renderer/layout/tabs.css | 98 + Ivette/src/dome/src/renderer/layout/tabs.js | 123 + .../src/dome/src/renderer/layout/toolbars.css | 228 + .../src/dome/src/renderer/layout/toolbars.js | 198 + Ivette/src/dome/src/renderer/table/arrays.js | 489 + Ivette/src/dome/src/renderer/table/models.js | 255 + Ivette/src/dome/src/renderer/table/tables.css | 121 + Ivette/src/dome/src/renderer/table/views.js | 552 ++ Ivette/src/dome/src/renderer/text/buffers.js | 446 + Ivette/src/dome/src/renderer/text/editors.css | 28 + Ivette/src/dome/src/renderer/text/editors.js | 375 + Ivette/src/dome/template/Application.js | 22 + Ivette/src/dome/template/Preferences.js | 20 + Ivette/src/dome/template/babelrc.json | 21 + .../src/dome/template/electron-webpack.json | 22 + Ivette/src/dome/template/export.sh | 27 + Ivette/src/dome/template/git-ignore | 14 + Ivette/src/dome/template/main.js | 17 + Ivette/src/dome/template/makefile | 369 + .../src/dome/template/makefile.app.packages | 15 + Ivette/src/dome/template/makefile.packages | 30 + Ivette/src/dome/template/package.sh | 60 + Ivette/src/dome/template/packplugin.js | 31 + Ivette/src/dome/template/renderer.js | 41 + Ivette/src/dome/template/update.sh | 75 + Ivette/src/dome/template/webpack.main.js | 38 + Ivette/src/dome/template/webpack.plugin.js | 41 + Ivette/src/dome/template/webpack.renderer.js | 35 + Ivette/src/frama-c/labviews.css | 53 + Ivette/src/frama-c/labviews.js | 597 ++ Ivette/src/frama-c/server.js | 623 ++ Ivette/src/frama-c/states.js | 114 + Ivette/src/main/index.js | 19 + Ivette/src/renderer/Application.js | 63 + Ivette/src/renderer/Console.js | 31 + Ivette/src/renderer/Preferences.js | 20 + Ivette/src/renderer/index.js | 41 + Ivette/src/renderer/style.css | 7 + Ivette/webpack.main.js | 38 + Ivette/webpack.plugin.js | 41 + Ivette/webpack.renderer.js | 38 + Ivette/yarn.lock | 8215 +++++++++++++++++ 166 files changed, 29724 insertions(+) create mode 100644 Ivette/.babelrc create mode 100644 Ivette/.dome-pkg-app.lock create mode 100644 Ivette/.dome-pkg-dev.lock create mode 100644 Ivette/.gitignore create mode 100644 Ivette/Makefile create mode 100644 Ivette/README.md create mode 100644 Ivette/backup/Configure.js create mode 100644 Ivette/backup/Display.js create mode 100644 Ivette/backup/FileMenu.js create mode 100644 Ivette/backup/Home.js create mode 100644 Ivette/backup/Project.js create mode 100644 Ivette/backup/ivette/index.js create mode 100644 Ivette/backup/ivette/plugins.js create mode 100644 Ivette/backup/ivette/stores.js create mode 100644 Ivette/backup/ivette/views.js create mode 100644 Ivette/backup/sandbox/Events.js create mode 100644 Ivette/backup/sandbox/Project.js create mode 100644 Ivette/backup/sandbox/Properties.js create mode 100644 Ivette/backup/sandbox/SourceCode.js create mode 100644 Ivette/backup/sandbox/SourceFiles.js create mode 100644 Ivette/backup/sandbox/index.js create mode 100644 Ivette/backup/sandbox/server.js create mode 100644 Ivette/backup/style.css create mode 100644 Ivette/electron-webpack.json create mode 100644 Ivette/package.json create mode 100755 Ivette/push-dome.sh create mode 100644 Ivette/src/dome/.gitignore create mode 100644 Ivette/src/dome/CHANGELOG.md create mode 100644 Ivette/src/dome/CONTRIBUTING.md create mode 100644 Ivette/src/dome/CONTRIBUTORS.md create mode 100644 Ivette/src/dome/LICENSE.md create mode 100644 Ivette/src/dome/Makefile create mode 100644 Ivette/src/dome/README.md create mode 100644 Ivette/src/dome/doc/README.md create mode 100644 Ivette/src/dome/doc/app.json create mode 100644 Ivette/src/dome/doc/config.json create mode 100644 Ivette/src/dome/doc/gallery.css create mode 100755 Ivette/src/dome/doc/icons.js create mode 100644 Ivette/src/dome/doc/template/gallery-head.html create mode 100644 Ivette/src/dome/doc/template/gallery-tail.html create mode 100644 Ivette/src/dome/doc/template/publish.js create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.eot create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.svg create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.woff create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.eot create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.svg create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.woff create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.eot create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.svg create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.woff create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.eot create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.svg create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.woff create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.eot create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.svg create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.woff create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.eot create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.svg create mode 100644 Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.woff create mode 100644 Ivette/src/dome/doc/template/static/scripts/linenumber.js create mode 100644 Ivette/src/dome/doc/template/static/scripts/prettify/Apache-License-2.0.txt create mode 100644 Ivette/src/dome/doc/template/static/scripts/prettify/lang-css.js create mode 100644 Ivette/src/dome/doc/template/static/scripts/prettify/prettify.js create mode 100644 Ivette/src/dome/doc/template/static/styles/jsdoc-default.css create mode 100644 Ivette/src/dome/doc/template/static/styles/prettify-jsdoc.css create mode 100644 Ivette/src/dome/doc/template/static/styles/prettify-tomorrow.css create mode 100644 Ivette/src/dome/doc/template/tmpl/augments.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/container.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/details.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/example.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/examples.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/exceptions.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/layout.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/mainpage.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/members.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/method.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/params.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/properties.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/returns.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/source.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/tutorial.tmpl create mode 100644 Ivette/src/dome/doc/template/tmpl/type.tmpl create mode 100644 Ivette/src/dome/doc/tutorials/application.md create mode 100644 Ivette/src/dome/doc/tutorials/dataflow.png create mode 100644 Ivette/src/dome/doc/tutorials/development.md create mode 100644 Ivette/src/dome/doc/tutorials/glossary.md create mode 100644 Ivette/src/dome/doc/tutorials/hooks.md create mode 100644 Ivette/src/dome/doc/tutorials/hotreload.md create mode 100644 Ivette/src/dome/doc/tutorials/index.json create mode 100644 Ivette/src/dome/doc/tutorials/quickstart.md create mode 100644 Ivette/src/dome/doc/tutorials/styling.md create mode 100644 Ivette/src/dome/src/main/dome.js create mode 100644 Ivette/src/dome/src/main/menubar.js create mode 100644 Ivette/src/dome/src/misc/devtools.js create mode 100644 Ivette/src/dome/src/misc/events.js create mode 100644 Ivette/src/dome/src/misc/plugins.js create mode 100644 Ivette/src/dome/src/misc/register.js create mode 100644 Ivette/src/dome/src/misc/system.js create mode 100644 Ivette/src/dome/src/renderer/controls/buttons.css create mode 100644 Ivette/src/dome/src/renderer/controls/buttons.js create mode 100644 Ivette/src/dome/src/renderer/controls/icons.css create mode 100644 Ivette/src/dome/src/renderer/controls/icons.js create mode 100644 Ivette/src/dome/src/renderer/controls/icons.json create mode 100644 Ivette/src/dome/src/renderer/controls/labels.css create mode 100644 Ivette/src/dome/src/renderer/controls/labels.js create mode 100644 Ivette/src/dome/src/renderer/dialogs.js create mode 100644 Ivette/src/dome/src/renderer/dnd.js create mode 100644 Ivette/src/dome/src/renderer/dome.css create mode 100644 Ivette/src/dome/src/renderer/dome.js create mode 100644 Ivette/src/dome/src/renderer/errors.js create mode 100644 Ivette/src/dome/src/renderer/layout/boxes.css create mode 100644 Ivette/src/dome/src/renderer/layout/boxes.js create mode 100644 Ivette/src/dome/src/renderer/layout/dispatch.js create mode 100644 Ivette/src/dome/src/renderer/layout/forms.css create mode 100644 Ivette/src/dome/src/renderer/layout/forms.js create mode 100644 Ivette/src/dome/src/renderer/layout/frames.js create mode 100644 Ivette/src/dome/src/renderer/layout/grids.css create mode 100644 Ivette/src/dome/src/renderer/layout/grids.js create mode 100644 Ivette/src/dome/src/renderer/layout/pages.css create mode 100644 Ivette/src/dome/src/renderer/layout/pages.js create mode 100644 Ivette/src/dome/src/renderer/layout/sidebars.css create mode 100644 Ivette/src/dome/src/renderer/layout/sidebars.js create mode 100644 Ivette/src/dome/src/renderer/layout/splitters.css create mode 100644 Ivette/src/dome/src/renderer/layout/splitters.js create mode 100644 Ivette/src/dome/src/renderer/layout/tabs.css create mode 100644 Ivette/src/dome/src/renderer/layout/tabs.js create mode 100644 Ivette/src/dome/src/renderer/layout/toolbars.css create mode 100644 Ivette/src/dome/src/renderer/layout/toolbars.js create mode 100644 Ivette/src/dome/src/renderer/table/arrays.js create mode 100644 Ivette/src/dome/src/renderer/table/models.js create mode 100644 Ivette/src/dome/src/renderer/table/tables.css create mode 100644 Ivette/src/dome/src/renderer/table/views.js create mode 100644 Ivette/src/dome/src/renderer/text/buffers.js create mode 100644 Ivette/src/dome/src/renderer/text/editors.css create mode 100644 Ivette/src/dome/src/renderer/text/editors.js create mode 100644 Ivette/src/dome/template/Application.js create mode 100644 Ivette/src/dome/template/Preferences.js create mode 100644 Ivette/src/dome/template/babelrc.json create mode 100644 Ivette/src/dome/template/electron-webpack.json create mode 100755 Ivette/src/dome/template/export.sh create mode 100644 Ivette/src/dome/template/git-ignore create mode 100644 Ivette/src/dome/template/main.js create mode 100644 Ivette/src/dome/template/makefile create mode 100644 Ivette/src/dome/template/makefile.app.packages create mode 100644 Ivette/src/dome/template/makefile.packages create mode 100755 Ivette/src/dome/template/package.sh create mode 100644 Ivette/src/dome/template/packplugin.js create mode 100644 Ivette/src/dome/template/renderer.js create mode 100755 Ivette/src/dome/template/update.sh create mode 100644 Ivette/src/dome/template/webpack.main.js create mode 100644 Ivette/src/dome/template/webpack.plugin.js create mode 100644 Ivette/src/dome/template/webpack.renderer.js create mode 100644 Ivette/src/frama-c/labviews.css create mode 100644 Ivette/src/frama-c/labviews.js create mode 100644 Ivette/src/frama-c/server.js create mode 100644 Ivette/src/frama-c/states.js create mode 100644 Ivette/src/main/index.js create mode 100644 Ivette/src/renderer/Application.js create mode 100644 Ivette/src/renderer/Console.js create mode 100644 Ivette/src/renderer/Preferences.js create mode 100644 Ivette/src/renderer/index.js create mode 100644 Ivette/src/renderer/style.css create mode 100644 Ivette/webpack.main.js create mode 100644 Ivette/webpack.plugin.js create mode 100644 Ivette/webpack.renderer.js create mode 100644 Ivette/yarn.lock diff --git a/Ivette/.babelrc b/Ivette/.babelrc new file mode 100644 index 00000000000..3e895f0c581 --- /dev/null +++ b/Ivette/.babelrc @@ -0,0 +1,21 @@ +// -------------------------------------------------------------------------- +// --- Template .babelrc configuration file for Dome +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/babelrc.json + + This configuration is a necessary extension to electron-webpack + for enabling react-hot-reloading. +*/ + +{ + "presets": [ + [ "@babel/env", { "modules": false } ], + [ "@babel/react" ] + ], + "plugins": [ + "@babel/plugin-proposal-object-rest-spread", + "react-hot-loader/babel" + ] +} diff --git a/Ivette/.dome-pkg-app.lock b/Ivette/.dome-pkg-app.lock new file mode 100644 index 00000000000..7282f0cc447 --- /dev/null +++ b/Ivette/.dome-pkg-app.lock @@ -0,0 +1 @@ +react@^16.8 react-dom source-map-support lodash react-virtualized react-draggable codemirror diff --git a/Ivette/.dome-pkg-dev.lock b/Ivette/.dome-pkg-dev.lock new file mode 100644 index 00000000000..e1751fd6636 --- /dev/null +++ b/Ivette/.dome-pkg-dev.lock @@ -0,0 +1 @@ +@babel/core@^7 @babel/preset-env @babel/preset-react @babel/plugin-proposal-object-rest-spread electron@^7 electron-builder electron-webpack electron-devtools-installer webpack babel-loader css-loader react-hot-loader @hot-loader/react-dom @types/react diff --git a/Ivette/.gitignore b/Ivette/.gitignore new file mode 100644 index 00000000000..1efbc2521d6 --- /dev/null +++ b/Ivette/.gitignore @@ -0,0 +1,15 @@ +# -------------------------------------------------------------------------- +# --- Template .gitignore file for Dome +# -------------------------------------------------------------------------- + +.dome-*.stamp +.dome-*.back +node_modules +yarn.lock +yarn-error.log +/bin +/dist +/html +/src/dome + +# -------------------------------------------------------------------------- diff --git a/Ivette/Makefile b/Ivette/Makefile new file mode 100644 index 00000000000..f4aa3784376 --- /dev/null +++ b/Ivette/Makefile @@ -0,0 +1,25 @@ +# -------------------------------------------------------------------------- +APP=Ivette +DOME=src/dome +DOME_APP_CLI=bin/frama-c-gui +DOME_APP_SRC=src/frama-c +COPYRIGHT="CEA LIST / LSL" +# -------------------------------------------------------------------------- + +.PHONY: app dev doc dist + +app: dome-app +dev: dome-dev +doc: dome-api dome-doc +dist: dome-dist + +# -------------------------------------------------------------------------- +# --- Ivette Plugins +# -------------------------------------------------------------------------- + +DOME_PLUGINS= +DOME_EXPORTS= + +# -------------------------------------------------------------------------- +include $(DOME)/template/makefile +# -------------------------------------------------------------------------- diff --git a/Ivette/README.md b/Ivette/README.md new file mode 100644 index 00000000000..da470aaa236 --- /dev/null +++ b/Ivette/README.md @@ -0,0 +1,25 @@ +## Setup + +From the `./gui` sub-directory of Frama-C main directory: + +``` +$ make app +``` + +## Mirroring to Dome/Electron + +The content of ./src/dome is git-subtree to be kept in sync +with Dome/Electron. The related commands must be issued from +the Frama-C root directory: + +1. Importing a branch from dome/electron: + +``` +$ git subtree pull -P gui/src/dome git@git.frama-c.com:dome/electron.git <branch> +``` + +2. Exporting to a branch into dome/electron: + +``` +$ git subtree push -P gui/src/dome git@git.frama-c.com:dome/electron.git <branch> +``` diff --git a/Ivette/backup/Configure.js b/Ivette/backup/Configure.js new file mode 100644 index 00000000000..b91206cb19d --- /dev/null +++ b/Ivette/backup/Configure.js @@ -0,0 +1,155 @@ +// -------------------------------------------------------------------------- +// --- Module Configuration View +// -------------------------------------------------------------------------- + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import Dialogs from 'dome/dialogs' ; +import { Catch } from 'dome/errors' ; +import { Label } from 'dome/controls/labels' ; +import Box from 'dome/layout/boxes' ; +import Toolbar from 'dome/layout/toolbars' ; +import Dispatch from 'dome/layout/dispatch' ; +import Form from 'dome/layout/forms' ; +import Ivette from '@ivette' ; +import Project from './Project' ; + +// -------------------------------------------------------------------------- +// --- Configuration View +// -------------------------------------------------------------------------- + +export default function Configure() +{ + + const [ state, setState ] = Project.useState(); + const configure = state.configure ; + if (!configure) return null; + + const { module, value, error, modified=false, copied } = configure ; + const valueId = value && value.id ; + const savedId = module && module.id ; + const isFresh = Ivette.isFresh(valueId); + const borrowed_label = copied && module.label ; + const borrowed_title = copied && module.title ; + + const validIdent = (id) => + id === savedId || + (!Ivette.isValid(id) ? 'Invalid identifier (not a filename)' : + !Ivette.isFresh(id) ? 'Already used identifier' : + true) ; + + const validLabel = borrowed_label && ((label) => label !== borrowed_label) ; + const validTitle = borrowed_title && ((title) => title !== borrowed_title) ; + + const onChange = (value,error) => { + Object.assign( configure, { modified: true, value, error } ); + setState({ configure }); + }; + + const onReload = () => { + setState({ configure: { + module, + copied: configure.copied, + value: Project.initConfigValue(configure.module) + }}); + }; + + const closeWith = (current) => { + setState({ + current, + configure: undefined, + frame: configure.onClose || 'home' + }); + }; + + const onClose = () => closeWith( state.current ); + + const onApply = () => { + if ( value && !error && !module.locked()) { + let commit = Ivette.commitModule( module, value ); + module.synchronize(commit) + .catch(onError) + .finally(() => closeWith( configure.copied ? module : undefined )); + } else { + closeWith( undefined ); + } + }; + + const onError = (err) => Dialogs.showMessageBox({ + kind: 'warning', + title: 'Module Management Error', + message: 'An error occurs during a module operation:\n' + err, + buttons: [{ label:'Ok' }] + }); + + const onRemove = () => Dialogs.showMessageBox({ + kind: 'warning', + title: 'Remove Module', + message: 'Definitively remove this Module from your Project ?', + defaultValue: false, + cancelValue: false, + buttons: [ + { value:false, label:'No' }, + { value:true, label:'Remove' } + ] + }).then( (ok) => { + if (ok) { + let removal = Ivette.removeModule( configure.module ); + module.synchronize(removal) + .catch(onError) + .finally(() => closeWith( undefined )); + } + }); + + return ( + <Box.Vfill> + <Dispatch.Item id='ivette.toolbar.configure'> + <Toolbar.Separator/> + <Toolbar.Button + kind='positive' icon='CHECK' + label='Apply' title='Apply modifications' + enabled={modified || isFresh} + disabled={error || module.locked()} + onClick={onApply} /> + <Toolbar.Inset/> + <Label>{ isFresh && 'New' } Module Configuration </Label> + <Toolbar.Filler/> + <Toolbar.Button + kind='negative' icon='TRASH' + label='Remove' title='Remove module' + disabled={isFresh} + enabled={valueId === savedId} + onClick={onRemove} /> + <Toolbar.Button + icon='RELOAD' title='Reset configuration' + enabled={modified} + onClick={onReload} /> + <Toolbar.Button + kind='cancel' + icon='CIRC.CLOSE' title='Cancel modifications' + onClick={onClose} /> + </Dispatch.Item> + <Form.Form + value={value} + error={error} + onChange={onChange} > + <Form.FieldCode + path='id' label='Module' + validate={validIdent} + placeholder={valueId} /> + <Form.FieldText + path='label' label='Display Name' + validate={validLabel} /> + <Form.FieldTextArea + path='title' label='Description' + validate={validTitle} rows={3} /> + <Form.Select path='config'> + <Catch label='Plugin Config'>{ module.renderConfig() }</Catch> + </Form.Select> + </Form.Form> + </Box.Vfill> + ); +} + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/Display.js b/Ivette/backup/Display.js new file mode 100644 index 00000000000..140f47ea5a9 --- /dev/null +++ b/Ivette/backup/Display.js @@ -0,0 +1,34 @@ +// -------------------------------------------------------------------------- +// --- Module Control View +// -------------------------------------------------------------------------- + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import { Catch } from 'dome/errors' ; +import { Label } from 'dome/controls/labels' ; +import Toolbar from 'dome/layout/toolbars' ; +import Dispatch from 'dome/layout/dispatch' ; +import Project from './Project' ; +import { ProvideModule } from '@ivette' ; + +// -------------------------------------------------------------------------- +// --- Current Module Display +// -------------------------------------------------------------------------- + +export default function Display() +{ + const [ { current } ] = Project.useState(); + if (!current) + return <Label>No module selected.</Label> ; + else + return ( + <ProvideModule module={current}> + <Catch label='Plugin Main View'> + <Dome.Render>{current.renderMain}</Dome.Render> + </Catch> + </ProvideModule> + ); +} + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/FileMenu.js b/Ivette/backup/FileMenu.js new file mode 100644 index 00000000000..c2bf7131c3f --- /dev/null +++ b/Ivette/backup/FileMenu.js @@ -0,0 +1,37 @@ +// -------------------------------------------------------------------------- +// --- File Menu +// -------------------------------------------------------------------------- + +import fs from 'fs' ; +import path from 'path' ; +import Dome from 'dome' ; +import Dialogs from 'dome/dialogs' ; +import Project from './Project' ; +import Ivette from '@ivette' ; + +// -------------------------------------------------------------------------- +// --- Actions +// -------------------------------------------------------------------------- + +function openProject() +{ + console.log('OPEN PROJECT…'); +} + +// -------------------------------------------------------------------------- +// --- Menu Items +// -------------------------------------------------------------------------- + +Dome.addMenuItem({ + menu: 'File', + id: 'ivette.menu.file.open', + label: 'Open Project…', + onClick: openProject +}); + +Dome.onUpdate(() => { + let enabled = Ivette.isProjectLocked(); + Dome.setMenuItem({ id: 'ivette.menu.file.open', enabled }); +}); + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/Home.js b/Ivette/backup/Home.js new file mode 100644 index 00000000000..93c98808a6c --- /dev/null +++ b/Ivette/backup/Home.js @@ -0,0 +1,134 @@ +// -------------------------------------------------------------------------- +// --- Project Home View +// -------------------------------------------------------------------------- + +import React from 'react' ; +import Dome from 'dome' ; +import Toolbar from 'dome/layout/toolbars' ; +import { Scroll, Hpack, Vbox, Vfill, Hfill } from 'dome/layout/boxes' ; +import { Splitter } from 'dome/layout/splitters' ; +import { Title, Label, Code, Descr } from 'dome/controls/labels' ; +import { Button, IconButton } from 'dome/controls/buttons' ; +import Ivette from '@ivette' ; +import Project from './Project' ; + +// -------------------------------------------------------------------------- +// --- Generic Dongle +// -------------------------------------------------------------------------- + +function Dongle({ id, label, title, selected, onSelect, children }) +{ + const wident = id && <Code className='ivette-dongle-id' label={id}/> ; + const wlabel = label && <Label label={label} /> ; + const wdescr = title && <Descr label={title} /> ; + const classes = 'ivette-dongle' + + (onSelect ? ' ivette-dongle-selectable' : '') + + (selected ? ' ivette-dongle-selected' : '') ; + return ( + <Hfill className={classes} + onClick={onSelect} > + {wident} + <Vfill> + {wlabel} + {wdescr} + </Vfill> + { children } + </Hfill> + ); +} + +// -------------------------------------------------------------------------- +// --- Module Dongle +// -------------------------------------------------------------------------- + +function ModuleDongle({ module, current, configure }) +{ + let selected = module === current ; + let configuring = configure && configure.modified ; + let configured = configuring && configure.value && configure.value.id === module.id ; + let SELECT = () => Project.setState({ current: module }); + let DISPLAY = () => Project.setState({ current: module, frame:'display' }); + let CONFIGURE = () => { + if (configured) Project.setConfigure(); + else if (!configuring) Project.setConfiguring(module); + }; + return ( + <Dongle id={module.id} + label={module.label} + title={module.title} + selected={selected} + onSelect={SELECT} > + <Toolbar.ButtonGroup> + <Toolbar.Button + icon='DISPLAY' title={'Display ' + module.id} + onClick={DISPLAY} /> + <Toolbar.Button + icon='SETTINGS' title={'Configure ' + module.id} + disabled={configuring && !configured} + onClick={CONFIGURE} /> + </Toolbar.ButtonGroup> + </Dongle> + ); +} + +// -------------------------------------------------------------------------- +// --- Plugin Dongle +// -------------------------------------------------------------------------- + +function PluginDongle({ plugin, configure }) +{ + const CREATE = () => Project.setConfiguring( Ivette.newModule(plugin) ); + return ( + <Dongle label={plugin.label} title={plugin.title} > + <Button icon='CIRC.PLUS' label='New' + title='Create a new Module from this plugin' + kind='positive' + style={{ width:80, height: 32 }} + disabled={configure && configure.modified} + onClick={CREATE} /> + </Dongle> + ); +} + +// -------------------------------------------------------------------------- +// --- Main View +// -------------------------------------------------------------------------- + +export default function Home() +{ + const [ { current,configure } , setState ] = Project.useState(); + const PROJECT = Ivette.getProjectDirectory(); + + const MODULES= Ivette.getModules().map((module) => ( + <ModuleDongle + key={'M' + module.id} + module={module} + current={current} + configure={configure} + /> + )); + + const PLUGINS= Ivette.getPlugins().map((plugin) => ( + <PluginDongle + key={'P' + plugin.id} + plugin={plugin} + configure={configure} + /> + )); + + return ( + <Scroll> + <Vbox> + {PROJECT ? <Title label='Project'/> : null} + {PROJECT ? <div className='ivette-project'><Code>{PROJECT}</Code></div> : null} + {MODULES.length ? <Title label='Modules'/> : null} + {MODULES} + {MODULES.length ? <div style={{height: 32}}/> : null} + {PLUGINS.length ? <Title label='Plugins'/> : null} + {PLUGINS} + </Vbox> + </Scroll> + ); +} + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/Project.js b/Ivette/backup/Project.js new file mode 100644 index 00000000000..67e6fa68443 --- /dev/null +++ b/Ivette/backup/Project.js @@ -0,0 +1,101 @@ +// -------------------------------------------------------------------------- +// --- Current State of Project +// -------------------------------------------------------------------------- + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import Dialogs from 'dome/dialogs' ; +import System from 'dome/system' ; +import Ivette from '@ivette' ; +import { Module } from '@ivette/plugins' ; + +// -------------------------------------------------------------------------- +// --- Global State +// -------------------------------------------------------------------------- + +/* + - 'frame': currently displayed frame in main window + - 'current': currently selected module object + - 'configure.module': original configured module + - 'configure.value': edited module properties + - 'configure.error': edited module errors + - 'configure.copied': true if the the target is a fresh copy from another module + - 'configure.modified': true if the value has been edited + */ + +const project = new Dome.State({ frame: 'home' }); + +export const setState = project.setState ; +export const useState = project.useState ; + +const mkSetFrame = (frame) => () => project.setState({frame}); +export const setHome = mkSetFrame('home'); +export const setDisplay = mkSetFrame('display'); +export const setConfigure = mkSetFrame('configure'); + +// -------------------------------------------------------------------------- +// --- Module Helpers +// -------------------------------------------------------------------------- + +export function initConfigValue( module ) +{ + let { id, label, descr } = module ; + let config = _.cloneDeep( module.config ); + return { id, label, descr, config }; +} + +export function setConfiguring( module, onClose ) +{ + if (module instanceof Module) { + let value = initConfigValue( module ); + setState({ + frame: 'configure', + configure: Object.assign( { onClose }, { value, module } ) + }); + } else + console.err( 'Not a plugin instance' , module ); +} + +// -------------------------------------------------------------------------- +// --- Module Helpers +// -------------------------------------------------------------------------- + +export function lookupProject() { + + let argv = System.argv(); + let commandProject = Ivette.lookupProject( argv[0] ); + if (commandProject) return commandProject ; + + let previousProject = Ivette.lookupProject( Dome.getGlobalSetting('ivette.working.project') ); + if (previousProject) return previousProject ; + + let workingProject = Ivette.lookupProject( System.getWorking() ); + if (workingProject) return workingProject ; + + return undefined ; +} + +export function loadProject( dir ) +{ + if (!dir) return ; + Dome.setGlobalSetting('ivette.working.project',dir); + let setup = Ivette.loadProject( dir ); + setup.then( (errors) => errors && errors.length && Dialogs.showMessageBox({ + kind: 'error', + message: 'Error(s) when loading project:\n' + errors.join('\n'), + buttons: [{ label: 'Ok' }] + })).finally(Dome.update); +} + +// -------------------------------------------------------------------------- +// --- Exports Default +// -------------------------------------------------------------------------- + +export default { + useState, setState, setHome, setConfigure, setDisplay, + setConfiguring, initConfigValue, + lookupProject, loadProject +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/ivette/index.js b/Ivette/backup/ivette/index.js new file mode 100644 index 00000000000..c9520ab74cf --- /dev/null +++ b/Ivette/backup/ivette/index.js @@ -0,0 +1,455 @@ +/** @module @ivette */ + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import System from 'dome/system' ; +import { Module, Factory, CONFIG, UPDATE } from './plugins' ; +import { Registry } from './stores' ; + +// -------------------------------------------------------------------------- +// --- Plugin & Module Registries +// -------------------------------------------------------------------------- + +const pluginsRegistry = new Registry('plugin'); +const modulesRegistry = new Registry('module'); + +/** + @method + @summary Registered Plugins. + @return {Class[]} an array of `Plugin` classes + */ +export const getPlugins = () => pluginsRegistry.elements() ; + +/** + @method + @summary Registered Modules. + @return {Plugin[]} an array of `Plugin` instances + */ +export const getModules = () => modulesRegistry.elements() ; + +/** + @method + @summary Returns a module by id. + */ +export const getModule = (id) => modulesRegistry.get(id); + +// -------------------------------------------------------------------------- +// --- Register Plugin +// -------------------------------------------------------------------------- + +const checkModule = ( m ) => { + if (!(m instanceof Module)) + throw `Invalid Plugin '${m}'` ; +}; + +const checkPlugin = ( P ) => checkModule( P.prototype ); +const getPluginId = ( m ) => m.constructor.id ; + +/** + @summary Register a (new) plugin. + @param {PLUGIN|Class<Module>} Plugin - + [plugin specification](module-@ivette_plugins.html#~PLUGIN) or + [module class](module-@ivette_plugins.html#Module) + @description + + Register a new plugin in the Ivette system. + + It is recommand to use a [PLUGIN](module-@ivette_plugins.html#~PLUGIN) + object for plugin specification. + If a class is provided, it shall extends the [Module](module-@ivette_plugins.html#Module) + base class and shall have static properties `id`, `label` + and `title` defined. + + Unless your are in development mode (which implies hot module reloading), + it is not permitted to register two plugins with the same identifier, + and an error would be emitted on the console in turn. + */ +function registerPlugin( spec ) +{ + const ThePlugin = typeof(spec)==='object' ? Factory(spec) : spec ; + checkPlugin( ThePlugin ); + const id = ThePlugin.id ; + if (!id) + throw `Invalid plugin: missing identifier` ; + if (!System.DEVEL && pluginsRegistry.get(id)) + throw `Duplicate plugin '${id}'` ; + pluginsRegistry.add( ThePlugin ); + if (System.DEVEL) modulesRegistry.forEach( (module) => { + // Propagates changes from HMR + if (module.constructor.id === ThePlugin.id) Object.setPrototypeOf( module , ThePlugin.prototype ); + }); +} + +// -------------------------------------------------------------------------- +// --- Project Directory +// -------------------------------------------------------------------------- + +let projectDirectory ; + +const getProjectDir = () => { + if (!projectDirectory) return projectDirectory; + let cwd = System.getWorkingDir(); + return cwd ? System.join( cwd , '.ivette' ) : undefined ; +}; +const getProjectIndex = () => System.join( getProjectDir(), 'index.json' ); +const getModuleSession = (mid) => System.join( getProjectDir(), 'modules', mid ); +const getModuleConfig = (mid) => System.join( getProjectDir() , 'config.json' ); + +/** @method + @summary Check is fome module is locked. + @return {boolean} */ +export const isProjectLocked = () => ( + modulesRegistry.find((m) => m.locked()) !== undefined +); + +/** + @method + @summary Returns current project directory. + @return {string} absolute path or undefined */ +export const getProjectDirectory = () => projectDirectory; + +/** + @summary Find enclosing project. + @param {string} path - a file path to starts with + @return {string} project directory holding that path + @description + Looks for the closest directory with name `"*.ivette"` + containing the given path, or the closest directory with a `.ivette` + file at root. + Returns `undefined` if not found. +*/ +export function lookupProject( path ) { + try { + path = System.resolve(path); + let prev ; + while( prev !== path ) + { + if (System.extname(path) === '.ivette' && System.isDirectory(path)) + return path; + let here = System.join( path, '.ivette' ); + if (System.isDirectory(here)) + return here; + prev = path ; + path = System.dirname(path); + } + } catch(_err) { } + return undefined ; +} + +// -------------------------------------------------------------------------- +// --- Project Index +// -------------------------------------------------------------------------- + +const saveIndex = async () => { + let modules = modulesRegistry.elements().map((m) => m.id); + let indexFile = getProjectIndex(); + let indexJSON = JSON.stringify({ modules }); + await System.mkDir( projectDirectory , { recursive: true }); + await System.writeFile( indexFile , indexJSON ); +}; + +const loadIndex = () => { + let indexFile = getProjectIndex(); + if (System.isFile(indexFile)) { + return System.readFile( indexFile ).then((content) => { + try { + return JSON.parse(content); + } catch(err) { + console.warn('[Ivette] invalid index.json:',err); + return {}; + } + }); + } else { + return Promise.resolve({}); + } +}; + +// -------------------------------------------------------------------------- +// --- Module Helpers +// -------------------------------------------------------------------------- + +export const isFresh = (id) => modulesRegistry.isFresh(id); +export const isValid = (id) => modulesRegistry.isValid(id); + +/** + @summary Creates a fresh Plugin instance. + @param {Class} Plugin - a class extending Plugin + @return {Plugin} a fresh module instance + @description + The returned module has a fresh identifier but is not yet registered. + */ +export function newModule( Plugin ) +{ + checkPlugin( Plugin ); + let module = new Plugin(); + module.id = modulesRegistry.fresh( Plugin.id ); + return module; +} + +/** + @summary Creates a fresh duplicate of a Plugin instance. + @param {Module} module - the instance to duplicate + @return {Module} a fresh module instance + @description + The returned module has a fresh identifier but is not yet registered. + It inherits from the original `module` configuration, with tagged label and title. + */ +export function duplicateModule( module ) +{ + let { label, title, constructor: Plugin } = module ; + checkPlugin( Plugin ); + let duplicate = new Plugin(); + duplicate.id = modulesRegistry.fresh( module.id ); + duplicate.label = label && label + " (copy)" ; + duplicate.title = title && title + " (duplicated)" ; + duplicate.config = _.cloneDeep(module.config); + return duplicate ; +} + +/** + @summary Unregister a module (if registered). + @param {Module} module - the module to remove + @return {Promise} resolved when the module has been removed (from disk) + @description + + Remove a module from the current project. + If the module is locked, an exception if raised. + The function does nothing if the module is not registered. + The promise is resolved when the module session directory has been fully removed. + */ +function removeModule( module ) +{ + checkModule( module ); + if (module.locked()) throw `Try to remove locked module '${module}'` ; + modulesRegistry.remove( module.id ); + if (module.session) + return System.rmDir( module.session, { recursive: true } ).then(saveIndex); + else + return saveIndex(); +} + +// -------------------------------------------------------------------------- +// --- Commit Module +// -------------------------------------------------------------------------- + +/** + @summary Commit module updates. + @param {Module} module - the module to update + @param {object} update - the module fields to update with + @param {string} [update.id] - new identifier + @param {string} [update.label] - new display name + @param {string} [update.title] - new short description + @param {object} [update.config] - new configuration + @return {Promise} resolved when the module has been commited (on disk) + @description + + The module is registered in the current project, or updated if already present. + Its session directory is created or renamed if necessary. + Finally, the module is emitted a `Plugin.CONFIG` event. + + */ +export function commitModule( module, { id, label, title, config } ) +{ + checkModule( module ); + if (module.locked()) throw `Try to commit locked module '${id}'` ; + + const oldId = module.id ; + const newId = id || oldId ; + + // Update registry + let index ; // Promise + if ( newId !== oldId ) { + module.id = newId ; + modulesRegistry.remove( oldId ); + modulesRegistry.add( module ); + index = saveIndex(); + } else { + if (!modulesRegistry.get( newId )) { + modulesRegistry.add( module ); + index = saveIndex(); + } + } + + // Update module + if (label !== undefined) module.label = label; + if (title !== undefined) module.title = title; + if (config !== undefined) module.config = config ; + + // Setup session directory + let setup ; // Promise + let oldSession = module.session ; + let newSession = System.join( projectDirectory, 'modules', newId ); + if ( newSession !== oldSession ) { + module.session = newSession ; + if (System.exists( oldSession )) + setup = System.rename( oldSession, newSession ); + else + setup = System.mkDir( newSession, { recursive:true } ); + } else { + if (!System.exists( newSession )) + setup = System.mkDir( newSession , { recursive:true } ); + else + setup = Promise.resolve(); + } + + // Backup config + let configFile = System.join( module.session , 'config.json' ); + if (!id || !label || !title || !config || !System.exists(configFile)) + { + let plugin = getPluginId( module ); + let configJSON = JSON.stringify({ id, label, title, plugin, config }); + setup.then(() => System.writeFile( configFile , configJSON )); + } + + // Batch updates and finally emit config event + return Promise.all([index,setup]).finally(() => module.emit( CONFIG )); +} + +// -------------------------------------------------------------------------- +// --- Project Management +// -------------------------------------------------------------------------- + +function loadProjectModule(id) +{ + if (modulesRegistry.get(id)) + return Promise.reject('Duplicate module'); + let session = System.join( projectDirectory, 'modules', id ); + let configFile = System.join( session , 'config.json' ); + return System.readFile( configFile ) + .then( (configJSON) => { + let moduleConfig = JSON.parse(configJSON); + let { label, title, plugin, config } = moduleConfig ; + let P = pluginsRegistry.get( plugin ); + if (!P) throw `Invalid plugin identifier ('${plugin}')` ; + let module = new P(); + module.id = id ; + module.label = label ; + module.title = title ; + module.config = config ; + modulesRegistry.add( module ); + module.emit( CONFIG ); + }); +} + +function reportLoadModule(id) { + return loadProjectModule(id) + .then(() => undefined) + .catch((err) => `Error with module ${id}: ${err}`); +} + +/** Change project directory. + @param {string} path - the directory of the project + @return {Promise} returning an array of errors +*/ +export function loadProject( path ) { + if (isProjectLocked()) throw 'Try to close locked project' ; + if (!path) throw 'Try to open empty project' ; + projectDirectory = path ; + modulesRegistry.clear(); + return loadIndex() + .then(({ modules=[] }) => Promise.all(modules.map(reportLoadModule))) + .then((errors) => errors.filter((e) => e !== undefined)); +} + +// -------------------------------------------------------------------------- +// --- Plugin Hooks +// -------------------------------------------------------------------------- + +const ModuleContext = React.createContext(); + +/** + @class + @summary Set the current module for children components. + @property {Module} module - the current module (can be `'undefined'`) + @property {React.Children} children - content to be rendered with the current module + */ +export const ProvideModule = ({ module, children }) => ( + <ModuleContext.Provider value={module}> + {children} + </ModuleContext.Provider> +); + +/** + @method + @summary Use the current module (Custom React Hook). + @return {Module} the current module + @description + Convenient method to obtain the current module. Does _not_ update on events. +*/ +export const useModule = () => React.useContext(ModuleContext); + +/** + @method + @summary Listen to (current) module event (Custom React Hook). + @parameter {string} event - the plugin event to listen on + @parameter {function} callback - the callback on event + @return {Plugin} the plugin instance of the current module + @description + Same as `Dome.useEmitter(module,event,callback)` with the current module. + The hook itself does not force update, unless the callback does. +*/ +export const useEvent = (event,callback) => { + let module = React.useContext(ModuleContext); + Dome.useEmitter( module, event, callback ); +}; + +/** + @method + @summary Use the current module with optional update on events (Custom React Hook). + @parameter {string} [events...] - the event(s) to listen on, in addition to `UPDATE` + @return {Module} the current module + @description + Convenient method to obtain the current module and connect to updating events. +*/ +export const useUpdate = (...events) => { + let module = React.useContext(ModuleContext); + let callback = Dome.useForceUpdate(); + React.useEffect(() => { + if (module) { + events.push(UPDATE); + events.forEach((evt) => module.on(evt,callback)); + return () => events.forEach((evt) => module.off(evt,callback)); + } else + return undefined; + }); + return module ; +}; + +/** + @method + @summary Returns the current module configuration (Custom React Hook). + @return {Module} the plugin configuration (up-to-date) + @description + Equivalent to `useUpdate(CONFIG).config` unless there is no current module. +*/ +export const useConfig = () => { + let m = useUpdate(CONFIG); + return m && m.config; +}; + +// -------------------------------------------------------------------------- +// --- Export Default +// -------------------------------------------------------------------------- + +export default { + registerPlugin, + getPlugins, + getModules, + isProjectLocked, + getProjectDirectory, + loadProject, + lookupProject, + isFresh, isValid, + newModule, + duplicateModule, + commitModule, + removeModule, + ProvideModule, + useModule, + useEvent, + useUpdate, + useConfig +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/ivette/plugins.js b/Ivette/backup/ivette/plugins.js new file mode 100644 index 00000000000..90cd687daf8 --- /dev/null +++ b/Ivette/backup/ivette/plugins.js @@ -0,0 +1,247 @@ +// -------------------------------------------------------------------------- +// --- Plugin Base Class +// -------------------------------------------------------------------------- + +/** @module @ivette/plugins */ + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import EventEmitter from 'events' ; + +/** + @event + @description + Triggered when a module is asked for killing its pending jobs. +*/ +export const KILL = 'ivette.kill' ; + +/** + @event + @description + Triggered when a module enters in locked state +*/ +export const LOCK = 'ivette.lock' ; + +/** + @event + @description + Triggered when a module is back to unlocked state +*/ +export const UNLOCK = 'ivette.unlock' ; + +/** + @event + @description + Triggered when a plugin has been configured +*/ +export const CONFIG = 'ivette.config' ; + +/** + @event + @description + Triggered when a plugin has been updated +*/ +export const UPDATE = 'ivette.update' ; + +/** + @summary Base class for Module instances. + @property {string} id - Module identifier + @property {string} [label] - Module display name + @property {string} [title] - Module short description + @property {object} config - Module configuration object + @property {string} session - Module session directory + @description + Each Ivette module is associated to a global object maintaining its internal state. + A `Plugin` is a class responsible for creating and managing the internal state of a module. + It is also responsible for rendering the module main view, its toolbar and sidebar items, + and configuration fields. +*/ +export class Module extends EventEmitter { + + constructor() { + super(); + this.config = {} ; + let _lock = { sem: 0 } ; + let _LOCKED = () => _lock.sem > 0 ; + let _LOCK = () => { + if (_lock.sem == 0) this.emit(LOCK); + _lock.sem++; + } ; + let _UNLOCK = () => { + _lock.sem--; + if (_lock.sem == 0) this.emit(UNLOCK); + if (_lock.sem < 0) { + console.warn(`[Ivette:${this.id}] unbalanced lock/unlock`,this.id); + _lock.sem = 0 ; + } + } ; + let _SYNCHRO = (p,k) => { + _LOCK() ; + if (k) this.once(KILL,k); + p.finally(() => { + if (k) this.off(KILL,k); + _UNLOCK(); + }); + return p; + } ; + this.lock = _LOCK ; + this.unlock = _UNLOCK ; + this.locked = _LOCKED ; + this.synchronize = _SYNCHRO ; + this.renderMain = this.renderMain.bind(this); + this.renderConfig = this.renderConfig.bind(this); + } + + // -------------------------------------------------------------------------- + // --- Locking + // -------------------------------------------------------------------------- + + /** + @summary Lock the plugin. + @description + Prevents the module from being re-configured. + Nested calls to `lock/unlock` shall be well balanced. + It is preferrable to use `this.synchronize()` instead. + Emits the signal `'ivette.lock'` unless already locked. + */ + lock() {} // privately defined by constructor + + /** + @summary Unlock the plugin. + @description + Cancel the last `lock()` call effect. + Nested calls to `lock/unlock` shall be well balanced. + It is preferrable to use `this.synchronize()` instead. + Emits the signal `'ivette.unlock'` when actually unlocked. + */ + unlock() {} // privately defined by constructor + + /** Whether the module is currenly locked or not. + @return {boolean} the locked status of the module. */ + locked() {} // privately defined by constructor + + /** + @summary Lock the module until a promise is pending. + @param {Promise} job - the promise to lock on + @param {function} kill - a callback to kill the job + @return {Promise} the job, for chaining + @description + Locks the module and wait for the promise to terminate + (normally or with an error) before unlocking. The callback is triggered + if the module is asked to be killed while the job is still running. + */ + synchronize() {} // privately defined by constructor + + /** + @summary Promise awaiting until unlocked. + @return {Promise} awaiting promise + @description + The returned promise is resolved once the + plugin is unlocked. It is immediately resolved + if not locked. + */ + wait() { + if ( !this.locked() ) { + return Promise.resolved(); + } else { + return new Promise((resolve,reject) => this.once(UNLOCK,resolve)); + } + } + + /** + @summary Interrupts pending tasks. + @description + Emits the `'ivette.kill'` signal. + Any currently running job shall be interrupted, + and the module shall eventually be unlocked. + @return {Promise} a promise resolved once unlocked + */ + kill() { + this.emit(KILL); + return this.wait(); + } + + // -------------------------------------------------------------------------- + // --- Render + // -------------------------------------------------------------------------- + + /** + @summary Emits the `@ivette.plugins.UPDATE` event. + */ + update() { + this.emit(UPDATE); + } + + /** + @summary Main view for the plugin. + @return {React.Children} the main view for the module + @description + See also the '@ivette/views' for defining sidebars and toolbars. + */ + renderMain() { + return null; + } + + /** + @summary Configuration view for the plugin. + @return {React.Children} form fields for configuring the plugin + */ + renderConfig() { + return null; + } + +} + +// -------------------------------------------------------------------------- +// --- Plugin Factory +// -------------------------------------------------------------------------- + +/** + @typedef PLUGIN + @summary Plugin Specification + @property {string} id - plugin identifier + @property {string} [label] - display name + @property {string} [title] - short description + @property {function} [initializer] - module initializer + @property {React.Element} [mainView] - main view + @property {React.Element} [configView] - configuration view + @description + + Properties for [registerPlugin](module-@ivette.html#registerPlugin) + specification. + + The `initializer` function, when specified, + is invoked once on each plugin instance. + The initializer function can be written as follows: + - `initializer() { ... this.XXX ... }` + - `initializer: function() { ... this.XXX ... }` + - `initializer: (module) => { ... module.XXX ... }` + + Typical usage of `initializer` is to initialize specific module properties + and register static callbacks on module events like `CONFIG` and `KILL`. +*/ + +export function Factory(spec) { + const { id, label, title, mainView, configView, initializer } = spec; + + class Plugin extends Module { + constructor() { + super(); + initializer && initializer.apply(this, [this]); + } + renderMain() { return mainView; } + renderConfig() { return configView; } + }; + Plugin.id = id; + Plugin.label = label; + Plugin.title = title; + + return Plugin; +} + +// -------------------------------------------------------------------------- + +export default { Module, Factory, KILL, LOCK, UNLOCK, CONFIG, UPDATE } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/ivette/stores.js b/Ivette/backup/ivette/stores.js new file mode 100644 index 00000000000..201516c5d51 --- /dev/null +++ b/Ivette/backup/ivette/stores.js @@ -0,0 +1,152 @@ +// -------------------------------------------------------------------------- +// --- Items Registry +// -------------------------------------------------------------------------- + +/** @module @ivette/stores */ + +import _ from 'lodash' ; + +const ALL = () => true ; +const IDENT = /^[a-zA-Z0-9_-]+$/ ; +const SUFFIX = /-[0-9]+$/ ; +const PADDING = (n) => n<10 ? "0"+n : n ; + +/** + @summary Base class for registries. + */ +export class Registry +{ + + /** @param {string} prefix - fresh identifier prefix */ + constructor( prefix ) { + this.items = {} ; + this.prefix = prefix ; + } + + /** + @summary Valid identifiers (letters, digits, dashes and underscores). + @return {boolean} `true` if the identifier is valid + */ + isValid(id) { + return typeof(id)=='string' && id.match( IDENT ); + } + + /** + @summary Test for freshness identifier. + @return {boolean} `true` if the identifier is not yet attributed + */ + isFresh(id) { + return !this.items[id] ; + } + + /** + @summary Creates an identifier. + @param {string} [id] - the base identifier to starts with + @return {string} a fresh identifier + @description + Returns a fresh identifier with format `<base>-<n>` where + the base is extracted from `id` (without its `-<n>` suffix, if any). + The default base is the registry prefix, if any. + */ + fresh(id) { + let base = this.prefix ; + if (id) { + let m = SUFFIX.exec(id); + base = m ? id.substring(0,m.index) : id ; + } + base += '-' ; + let kid = 1 ; + for( ;; ) { + var a = base + PADDING(kid++) ; + if (!this.items[a]) break ; + } + return a ; + } + + /** + @summary Iterates ovee the registry. + @param {function} job - called with `job(item,id)` in unspecified order + @description + If the iteratee returns `false`, the iteration is interrupted. + */ + forEach(job) { _.forEach( this.items , (item,id) => job(item,id) ); + } + + /** + @summary Iterates ovee the registry. + @param {function} test - called with `test(item,id)` in unspecified order + @description + Returns the first item such that `test(item,id)` returns a truthy value. + Returns `undefined` otherwise. + */ + find(test) { _.find( this.items , (item,id) => test(item,id) ); } + + /** + Select items from the registry + @param {object} [options] - filter and ordering options + @return {item[]} the selected array of items + @description +Available options are: +- `filter:(item) => boolean` to select some itmes (default: all) +- `sortBy:function | function[] | field | field[]` to sort items by (default: by identifier) + +Sorting is done by loadsh [sortBy](https://lodash.com/docs/4.17.11#sortBy) method. + */ + elements( options ) + { + const filter = (options && options.filter) || ALL ; + const sortBy = (options && options.sortBy) || 'id' ; + const pool = []; + _.forEach( this.items, (item) => { + if (filter(item)) pool.push(item); + }); + return _.sortBy(pool,sortBy); + } + + /** Register a new item + @param {object} - the item to register in + @param {once} - register only fresh items + @description +Each object shall define the following properties: +- `id:string` item identifier (default to `fresh()`) +- `label:string` _optional_ item display name +- `title:string` _optional_ item short description + */ + add( item, once=false ) { + if (!item.id) item.id = this.fresh(); + if (!this.isValid(item.id)) { + console.warn( `[Ivette:${this.prefix}] invalid identifier (${item.id})` ); + return ; + } + if (once && !this.isFresh(item.id)) { + console.warn( `[Ivette:${this.prefix}] duplicate identifier (${item.id})` ); + return ; + } + this.items[item.id] = item ; + } + + /** Retrieve an item by id + @param {string} id - item identifier + @return {object} the associated item + */ + get(id) { return id ? this.items[id] : undefined; } + + /** Remove an item by id + @param {string} id - item identifier + */ + remove( id ) { + if (id && this.items[id]) { + delete this.items[id]; + } + } + + /** Remove all items */ + clear() { + this.items = {}; + } + +} + +export default { Registry }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/ivette/views.js b/Ivette/backup/ivette/views.js new file mode 100644 index 00000000000..4b80dfc0ee5 --- /dev/null +++ b/Ivette/backup/ivette/views.js @@ -0,0 +1,42 @@ +// -------------------------------------------------------------------------- +// --- Lab View Component +// -------------------------------------------------------------------------- + +/** @module @ivette/views */ + +import _ from 'lodash' ; +import React from 'react' ; +import { Catch } from 'dome/errors' ; +import { Item } from 'dome/layout/dispatch' ; + +import Ivette from '@ivette' ; + +/** + @class + @summary Defines the plugin toolbar + @description + Shall be defined once inside main plugin rendering. +*/ +export const PluginToolbar = ({children}) => ( + <Item id='ivette.toolbar.display'> + <Catch label='Plugin Toolbar'>{ children }</Catch> + </Item> +); + +/** + @class + @summary Defines the plugin toolbar + @description + Shall be defined once inside main plugin rendering. +*/ +export const PluginSidebar = ({children}) => ( + <Item id='ivette.sidebar.display'> + <Catch label='Plugin Sidevar'>{ children }</Catch> + </Item> +); + +// -------------------------------------------------------------------------- + +export default { PluginSidebar, PluginToolbar }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/sandbox/Events.js b/Ivette/backup/sandbox/Events.js new file mode 100644 index 00000000000..ab8069cbcd7 --- /dev/null +++ b/Ivette/backup/sandbox/Events.js @@ -0,0 +1,7 @@ +// -------------------------------------------------------------------------- +// --- Frama-C Events +// -------------------------------------------------------------------------- + +export const reload = 'frama-c.reload' ; + +export default { reload } ; diff --git a/Ivette/backup/sandbox/Project.js b/Ivette/backup/sandbox/Project.js new file mode 100644 index 00000000000..37d33df468a --- /dev/null +++ b/Ivette/backup/sandbox/Project.js @@ -0,0 +1,206 @@ +import React, { useState, useEffect } from 'react'; +import { showOpenFiles } from 'dome/dialogs'; +import { Button } from 'dome/controls/buttons'; +import { Label } from 'dome/controls/labels'; +import { Badge } from 'dome/controls/icons'; +import { Hbox, Vbox } from 'dome/layout/boxes'; +import Server from './server'; +import { Set } from 'immutable'; + +class SelectList extends React.Component { + render() { + return ( + <select value={this.props.value} onChange={this.props.onChange}> + {this.props.values.map(v => <option key={v.id}>{v.name}</option>)} + </select> + ) + } +} + +function FileSelect(props) { + const [files, setFiles] = useState(Set([])); + const [addedFiles, setAddedFiles] = useState(Set([])); + const [removedFiles, setRemovedFiles] = useState(Set([])); + + function updateFiles() { + Server + .sendGET("kernel.ast.getFiles", [], false) + .then( + (data) => { + console.log("success: " + data + '\n'); + setFiles(Set(data)); + setAddedFiles(Set([])); + setRemovedFiles(Set([])); + }, + (_rid, data) => { + console.log("err:" + data + '\n') + }); + }; + + //Done only once + useEffect(updateFiles, []); + + function addFiles() { + showOpenFiles({ message: "Add files" }) + .then(files => { + setAddedFiles(() => { + const sfiles = Set(files); + const res = addedFiles.union(sfiles); + return res + }) + }); + }; + + function generateItem(v) { + const removed = removedFiles.has(v); + const added = addedFiles.has(v); + return ( + <Hbox key={v}> + <Label + style={(removed ? { color: 'red' } : (added ? { color: 'green' } : {}))}> + {v} + </Label> + <Badge + value={removed ? 'CIRC.PLUS' : 'CIRC.MINUS'} + onClick={() => + setRemovedFiles(() => + removed ? removedFiles.remove(v) : removedFiles.add(v)) + } /> + </Hbox> + ) + }; + + function sendFiles() { + const filesToSend = files.union(addedFiles).subtract(removedFiles); + Server + .sendSET("kernel.ast.setFiles", filesToSend.toArray(), false) + .then( + () => { + console.log("setFiles: success"); + Server + .sendEXEC("kernel.ast.execCompute", [], false) + .then( + () => { + console.log("execComput: success"); + updateFiles(); + }, + (_rid, data) => { + console.log("execCompute err:" + data + '\n') + } + ); + }, + (_rid, data) => { + console.log("setFiles err:" + data + '\n') + } + ); + }; + + return ( + <Vbox> + {files.map(generateItem)} + {addedFiles.map(generateItem)} + <Hbox> + <Button label='Add files' onClick={addFiles} /> + <Button label='Update' onClick={sendFiles} /> + </Hbox> + </Vbox> + ) +} + +function Projects(props) { + const [projects, setProjects] = useState([]); + const [current, setCurrent] = useState(undefined); + const [newName, setNewName] = useState("project_name"); + + + function updateProjects() { + Server + .sendGET("kernel.project.getList", [], false) + .then( + (data) => { + console.log("success: " + data.datadir + '\n'); + setProjects(data) + }, + (_rid, data) => { + console.log("err:" + data + '\n') + }); + }; + + //Done only once + useEffect(updateProjects, []); + + function new_project() { + Server + .sendSET("kernel.project.setCreate", newName, false) + .then( + (data) => { + console.log("success: " + data.datadir + '\n'); + updateProjects(); + }, + (_rid, data) => { + console.log("err:" + data + '\n') + }); + }; + + + console.log("projects:", projects); + return ( + <Hbox> + <form onSubmit={new_project}> + <label> + Name of new project : + <input + type="text" + value={newName} + onChange={event => setNewName(event.target.value)} + /> + </label> + <input type="submit" value="Create" /> + </form> + <label> + Current project: + <SelectList + values={projects} + value={current} + onChange={event => setCurrent(event.target.value)} + /> + </label> + </Hbox> + ) +} + +function Kernel(props) { + const [state, setState] = useState("undefined"); + + function getCfg() { + console.log("send request\n"); + Server + .sendGET("kernel.getConfig", [], false) + .then( + (data) => { + console.log("success: " + data.datadir + '\n'); + setState(data.datadir); + }, + (_rid, data) => { + console.log("err:" + data + '\n') + }); + }; + + return ( + <Hbox> + <Button label='GetConfig' onClick={getCfg} /> + <Label label={state} /> + </Hbox> + ) +} + +export default function Project(props) { + + return ( + <> + <Kernel /> + <Projects /> + <FileSelect /> + </> + ) +} \ No newline at end of file diff --git a/Ivette/backup/sandbox/Properties.js b/Ivette/backup/sandbox/Properties.js new file mode 100644 index 00000000000..ac8e770bef9 --- /dev/null +++ b/Ivette/backup/sandbox/Properties.js @@ -0,0 +1,137 @@ +// -------------------------------------------------------------------------- +// --- Frama-C Properties Table +// -------------------------------------------------------------------------- + +import React from 'react' ; +import Dome from 'dome' ; +import { useState, useEffect } from 'react' ; + +import { Button } from 'dome/controls/buttons'; +import { Vfill, Vbox, Scroll } from 'dome/layout/boxes' ; +import { Splitter } from 'dome/layout/splitters' ; +import { Column, Table } from 'dome/table/views' ; +import { ArrayModel } from 'dome/table/arrays' ; +import { Form, Section, FieldList, FieldCheckbox, FieldRadio } from 'dome/layout/forms' ; + +import Server from './server.js' ; +import Events from './Events.js' ; + +export default function Properties (props) { + const model = props.properties; + + /* --- Columns of the table ----------------------------------------------- */ + + const columnFile = <Column id='file' + label='File' />; + const columnFct = <Column id='fct' + label='Function' />; + const columnProp = <Column id='property' + label='Property' + fill />; + const columnStatus = <Column id='status' + label='Status' />; + + /* The default columns displayed. The property column is always shown. */ + const defaultColumns = + { path:false, + fct:true, + status:true, + }; + /* The columns displayed. Set by the user through a form. */ + const [columnsValue, _] = useState(defaultColumns); + + /* Builds the array of columns according to [columnsValue]. */ + function makeColumns () { + const columns = new Array(); + if (columnsValue.path) + columns.push(columnFile); + if (columnsValue.fct) + columns.push(columnFct); + columns.push(columnProp); // Always shown. + if (columnsValue.status) + columns.push(columnStatus); + return columns; + } + + /* The columns array used by the table. */ + const [ columns, setColumns ] = useState(makeColumns()); + + function onChangeColumns () { + setColumns(makeColumns()); + } + + /* Form to choose the columns displayed. */ + const columns_list = + <Form value={columnsValue} onChange={onChangeColumns} > + <Section label="Columns" unfold='false' > + <FieldCheckbox label="File" path='path' /> + <FieldCheckbox label="Function" path='fct' /> + <FieldCheckbox label="Status" path='status' /> + </Section> + </Form>; + + /* --- Filters of logical properties ------------------------------------- */ + + /* All properties are shown by default. */ + const default_status = + { valid:true, + valid_hyp:true, + unknown:true, + invalid:true, + invalid_hyp:true, + considered_valid:true, + untried:true, + dead:true, + inconsistent:true + }; + const [status, setStatus] = useState(default_status); + + /* Function filtering the properties by status. */ + function filter (item) { + switch (item.status) { + case 'Valid': + case 'Valid_but_dead': return status.valid; + case 'Valid_under_hyp': return status.valid_hyp; + case 'Invalid': + case 'Invalid_but_dead': return status.invalid; + case 'Invalid_under_hyp': return status.invalid_hyp; + case 'Unknown': + case 'Unknown_but_dead': return status.unknown; + case 'Considered_valid': return status.considered_valid; + case 'Never_tried': return status.untried; + case 'Dead': return status.dead; + case 'Inconsistent': return status.inconsistent; + default: return true; + } + } + + function onChangeFilter (value, error) { + model.setFiltering(filter); + } + + /* Filters selection. */ + const filter_list = + <Form value={status} onChange={onChangeFilter} > + <Section label="Status" unfold='true' > + <FieldCheckbox label="Valid" path='valid' /> + <FieldCheckbox label="Valid under hyp." path='valid_hyp' /> + <FieldCheckbox label="Unknown" path='unknown' /> + <FieldCheckbox label="Invalid" path='invalid' /> + <FieldCheckbox label="Invalid under hyp." path='invalid_hyp' /> + <FieldCheckbox label="Considered valid" path='considered_valid' /> + <FieldCheckbox label="Untried" path='untried' /> + <FieldCheckbox label="Dead" path='dead' /> + <FieldCheckbox label="Inconsistent" path='inconsistent' /> + </Section> + </Form>; + + /* Table of logical properties. */ + const table = <Table model={model} children={columns} />; + + return ( + <Splitter dir='LEFT' > + <Vfill> <Scroll> {filter_list} {columns_list} </Scroll> </Vfill> + <Vfill> {table} </Vfill> + </Splitter> + ) +} diff --git a/Ivette/backup/sandbox/SourceCode.js b/Ivette/backup/sandbox/SourceCode.js new file mode 100644 index 00000000000..023eeafbfb3 --- /dev/null +++ b/Ivette/backup/sandbox/SourceCode.js @@ -0,0 +1,129 @@ +// -------------------------------------------------------------------------- +// --- Frama-C Source Panel +// ------------------------------------------------------------------------- + +import React from 'react' ; +import Dome from 'dome' ; + +import { Button } from 'dome/controls/buttons'; +import Toolbar from 'dome/layout/toolbars' ; +import { Hbox, Hfill, Vbox, Vfill, Space } from 'dome/layout/boxes' ; +import { Splitter } from 'dome/layout/splitters' ; +import { Column, Table } from 'dome/table/views' ; +import { Text } from 'dome/text/editors' ; +import Server from './server.js' ; +import Events from './Events.js' ; + +import { useState, useEffect } from 'react' ; + +import 'codemirror/mode/clike/clike.js'; +import 'codemirror/theme/ambiance.css' ; +import 'codemirror/theme/solarized.css'; + +/* Pretty prints the source code from [text] in [buffer]. */ +function printSource (buffer, text) { + if (text === null) return; + if (Array.isArray(text)) { + const tag = text.shift(); + if (tag !== '') { + buffer.openTextMarker( { id:tag } ); + text.forEach(txt => printSource(buffer, txt)); + buffer.closeTextMarker(); + } else + text.forEach(txt => printSource(buffer, txt)); + } else + buffer.append(text); +} + +/* Display the list of functions and the source code for the selected function + in the list. */ +export default function Source (props) { + /* Buffer for the source code. */ + const buffer = props.sourceCode; + /* Model for the function list. */ + const model = props.functions; + + /* Print the source code of the function [data.fct]. */ + function printFunction (data) { + console.log("Select function: " + data.fct); + Server.sendGET("kernel.ast.printFunction", data.fct, false).then + ( data => { + buffer.clear(); + printSource(buffer, data); + }); + } + + const [ theme, setTheme ] = useState('default'); + function selectTheme (name) { + return function () { setTheme(name); } + } + + function contextMenu (data) { + const item1 = { label:"Default", onClick:selectTheme("default") }; + const item2 = { label:"Ambiance", onClick:selectTheme("ambiance") }; + const item3 = { label:"Solarized light", onClick:selectTheme("solarized light") }; + const item4 = { label:"Solarized dark", onClick:selectTheme("solarized dark") }; + Dome.popupMenu([item1, item2, item3, item4]).catch(() => {}); + } + + /* Table for the function list. */ + const table = + <Table model={model} + onSelection={printFunction} > + <Column id='fct' + label='Functions' + title='List of functions in the current Frama-C project' /> + </Table>; + + const [ lineWrapping, setLineWrapping ] = useState(false); + function changeLineWrapping () { setLineWrapping(!lineWrapping); } + + const code = <Text buffer={buffer} + mode='text/x-csrc' + theme={theme} + lineWrapping={lineWrapping} + readOnly />; + + const [ fontSize, setFontSize ] = useState(12); + function increaseFontSize () { setFontSize(fontSize + 2); } + function decreaseFontSize () { setFontSize(fontSize - 2); } + + const toolbar = + <Toolbar.ToolBar> + <Toolbar.Space/> + <Toolbar.Select + value={theme} + onChange={(name) => {selectTheme(name)();}} > + <option value='default' label='Default'/> + <option value='ambiance' label='Ambiance'/> + <option value='solarized light' label='Solarized light'/> + <option value='solarized dark' label='Solarized dark'/> + </Toolbar.Select> + <Toolbar.ButtonGroup> + <Toolbar.Button + icon='MINUS' + title='Decrease the font size' + onClick={decreaseFontSize} + /> + <Toolbar.Button + icon='PLUS' + title='Increase the font size' + onClick={increaseFontSize} + /> + </Toolbar.ButtonGroup> + <Toolbar.Button icon={lineWrapping ? "CHECK" : "CROSS"} + label="Line wrapping" + title="Change line wrapping mode" + onClick={changeLineWrapping} /> + </Toolbar.ToolBar>; + + return ( + <Splitter dir='LEFT' > + <Vfill style={{ minWidth: 100 }}> {table} </Vfill> + <Vfill onContextMenu={contextMenu} style={{ fontSize: fontSize }} > + {toolbar} + {code} + </Vfill> + </Splitter> + ); +} diff --git a/Ivette/backup/sandbox/SourceFiles.js b/Ivette/backup/sandbox/SourceFiles.js new file mode 100644 index 00000000000..8a7386b5706 --- /dev/null +++ b/Ivette/backup/sandbox/SourceFiles.js @@ -0,0 +1,44 @@ +import React, { useState, useEffect } from 'react'; +import { Buffer } from 'dome/text/buffers' +import { Text } from 'dome/text/editors'; +import Server from './server'; +import System from 'dome/system'; +import 'codemirror/mode/clike/clike.js'; + +export default function SourceFiles() { + + const [filenames, setFilenames] = useState([]); + const buffer = new Buffer({ mode: 'text/x-csrc' }); + + function getSourceFilenames() { + console.log('SourceFiles::getFiles'); + + Server + .sendGET("kernel.ast.getFiles", [], false) + .then( + (fnames) => { + console.log('Got source filenames:' + fnames); + setFilenames(fnames); + }); + } + + useEffect(getSourceFilenames, []); + + useEffect(() => { + if (filenames.length > 0) { + console.log('Displaying ' + filenames[0] + '!'); + System + .readFile(filenames[0]) + .then( + (fcontent) => { + console.log('Got file content: ' + fcontent); + buffer.clear(); + buffer.append(fcontent); + }); + } + }, [filenames]) + + return ( + <Text buffer={buffer} readOnly='true' lineNumbers='true' /> + ) +} diff --git a/Ivette/backup/sandbox/index.js b/Ivette/backup/sandbox/index.js new file mode 100644 index 00000000000..a47d41f75e7 --- /dev/null +++ b/Ivette/backup/sandbox/index.js @@ -0,0 +1,195 @@ +// -------------------------------------------------------------------------- +// --- Frama-C Ivette Plug-in +// -------------------------------------------------------------------------- + +import React from 'react' ; +import Dome from 'dome' ; +import Toolbar from 'dome/layout/toolbars' ; +import { GridItem, GridHbox, GridVbox } from 'dome/layout/grids' ; +import { Code } from 'dome/controls/labels' ; +import Ivette from '@ivette' ; +import { Module } from '@ivette/plugins' ; +import { PluginToolbar } from '@ivette/views' ; +import { LabView, View, Group, Component } from '@ivette/labviews' ; +import { Buffer } from 'dome/text/buffers' ; +import { ArrayModel } from 'dome/table/arrays' ; +import Dialogs from 'dome/dialogs'; +import Server from './server'; +import SourceFiles from './SourceFiles'; +import Events from './Events'; +import SourceCode from './SourceCode'; +import Properties from './Properties'; +import Project from "./Project"; + +// -------------------------------------------------------------------------- +// --- Frama-C Plugin +// -------------------------------------------------------------------------- + +/* Load a Frama-C session. */ +function LoadSession () { + Dialogs.showOpenFile({message: 'Select a Frama-C save file'}).then + ( path => { + if (path) { + console.log("Load session, path selected: " + path); + Server.sendSET("kernel.load",path,false).then + ( err => { + if (err) { + let message = + { kind: 'error', + title: 'Error while loading the Frama-C session', + message: err, + buttons: [{ label: 'Ok' }] + }; + Dialogs.showMessageBox(message); + } else { + Dome.emit(Events.reload); + console.log("Project successfully loaded."); + } + }); + } else + console.log("Load session: no path selected."); + }); +} + +function emitReload () { + Dome.emit(Events.reload); +} + +export class FramaC extends Module { + + constructor() + { + super(); + this.sourceCode = new Buffer ({ mode:'text/x-csrc' }); + this.functions = new ArrayModel (); + this.getFunctions = this.getFunctions.bind(this); + this.properties = new ArrayModel (); + this.getProperties = this.getProperties.bind(this); + Server.startServer(); + Dome.addMenuItem({ + menu: 'File', + id: 'ivette.menu.file.load', + label: 'Load session', + key: 'Cmd+L', + onClick: LoadSession + }); + } + + /* Get the list of functions from the server, and fill [this.functions]. */ + getFunctions () { + Server.sendGET("kernel.ast.getFunctions", [], false).then + ( data => { + console.log("Collecting " + data.length + " functions."); + this.functions.clear(); + const array = new Array(data.length); + data.forEach( (fct, index) => { array[index] = {fct: fct}; } ); + this.functions.setData(array); + }); + } + + /* Get the list of properties from the server, and fill [this.properties]. */ + getProperties () { + Server.sendGET("kernel.ast.getProperties", [], false).then + ( data => { + this.properties.clear(); + const array = new Array(data.length); + data.forEach( (item, index) => { + array[index] = { property: item.property, + fct: item.function, + status: item.status, + file: item.file }; + }); + this.properties.setData(array); + }); + } + + renderMain() { + let [ custom, setCustom ] = Dome.useState('sandbox.custom',false); + Dome.useEvent(Events.reload, this.getFunctions); + Dome.useEvent(Events.reload, this.getProperties); + return ( + <React.Fragment> + <PluginToolbar> + <Toolbar.Button + icon='FILE' + label='Load' + title='Load a Frama-C session' + onClick={LoadSession} + /> + <Toolbar.Filler/> + <Toolbar.Button + icon='RELOAD' + title='Reload the tables' + onClick={emitReload} + /> + <Toolbar.Button + icon='ITEMS.GRID' + title='Customize Main View' + selected={custom} + onClick={() => setCustom(!custom)}/> + </PluginToolbar> + <LabView + customize={custom} + settings='sandbox.labview' + > + <View id='lab.main' label='Lab View' defaultView > + <GridItem id='kernel.props' /> + </View> + <View id='lab.eva' label='EVA Lab'> + <GridHbox> + <GridItem id='kernel.globals' /> + <GridItem id='plugins.eva' /> + </GridHbox> + </View> + <View id='lab.wp' label='WP Lab'> + <GridHbox> + <GridItem id='kernel.globals' /> + <GridItem id='plugins.wp' /> + </GridHbox> + </View> + <Component id='dashboard' label='Dashboard'/> + <Group id='kernel' label='Kernel'> + <Component id='kernel.project' label='Projects' > + <Project /> + </Component> + <Component id='kernel.source' label='Source Code' > + <SourceCode functions={this.functions} + sourceCode={this.sourceCode} /> + </Component> + <Component id='kernel.files' label='Source Files'> + <SourceFiles /> + <Dome.Render> + {() => { + let m = Ivette.useModule(); + return (<Code> Module: {m.id} </Code>); + }} + </Dome.Render> + </Component> + <Component id='kernel.globals' label='Globals Index' /> + <Component id='kernel.ast' label='AST Inspector' /> + <Component id='kernel.props' label='Properties Status' > + <Properties properties={this.properties} /> + </Component> + </Group> + <Group id='plugins' label='Plugins'> + <Component id='plugins.eva' label='Frama-C / EVA' /> + <Component id='plugins.wp' label='Frama-C / WP' /> + </Group> + </LabView> + </React.Fragment> + ); + } + +} + +FramaC.id = 'frama-c-sandbox'; +FramaC.label = "Frama-C Sandbox" ; +FramaC.title = "A playground for Frama-C" ; + +// -------------------------------------------------------------------------- +// --- Registration +// -------------------------------------------------------------------------- + +Ivette.registerPlugin( FramaC ); + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/sandbox/server.js b/Ivette/backup/sandbox/server.js new file mode 100644 index 00000000000..cb14624f32a --- /dev/null +++ b/Ivette/backup/sandbox/server.js @@ -0,0 +1,226 @@ +// -------------------------------------------------------------------------- +// --- Global State +// -------------------------------------------------------------------------- + +import _ from 'lodash' ; +import Dome from 'dome' ; +import System from 'dome/system' ; +import { Request } from 'zeromq' ; + +// -------------------------------------------------------------------------- +// --- Frama-C Server +// -------------------------------------------------------------------------- + +const url = 'ipc:///tmp/fc.io' ; + +var stable = true ; +var server = null ; + +export function isStopped() { return stable && server === null; } +export function isRunning() { return stable && server !== null; } + +export function stopServer() { + if (server) { + stable = false; + server.kill(); + Dome.update(); + } +} + +export function startServer() { + if (stable && !server) { + stable = false ; + System.spawn + ( 'frama-c', + [ + '-server-zmq', url, + '-server-debug', 1 + ] + ).then((process) => { + stable = true ; + server = process ; + startSocket(); + process.stdout.on('data',(msg) => {console.log(msg); Dome.emit('console',msg)}); + process.stderr.on('data',(msg) => {console.log(msg); Dome.emit('console',msg)}); + process.on('close',(status) => { + console.log(`Frama-C exit with status ${status}\n`); + Dome.emit('console',`Frama-C exit with status ${status}\n`); + stable = true ; + server = null ; + stopSocket(); + Dome.update(); + }); + Dome.update(); + }).catch((err) => { + stable = true ; + server = null ; + console.log('Error: ' + err + '\n'); + Dome.emit('console','Error: ' + err + '\n'); + Dome.update(); + }); + Dome.update(); + } +} + +// // -------------------------------------------------------------------------- +// // --- Frama-C Socket +// // -------------------------------------------------------------------------- + +var socket = null; +var queue_cmd = []; +var queue_ids = []; +var waiting = false; +var promises = {}; +var pending = 0; +var kid = 0; + +export function getPending() { return pending; } + +export function killPending() { + _.forEach(promises,( _data , rid ) => { + queue_cmd.push( 'KILL' ); + queue_cmd.push( rid ); + }); + flushQueue(); +} + +function startSocket() { + if (socket) stopSocket(); + socket = new Request(); + socket.connect(url); + console.log("socket connected\n"); + // Dome.emit('server',true); +} + +function stopSocket() { + if (socket) { + _.forEach(promises,( { reject } ) => reject('socket closed') ); + socket.close(); + waiting = false; + socket = null; + // Dome.emit('server',false); + } +} + +function sendRequest( kind , request , params = null , more ) { + console.log("send request\n"); + return new Promise((resolve,reject) => { + if (!socket) reject('socket closed'); + try { + const rid = 'RQ' + kid++ ; + const data = JSON.stringify(params); + pending++; + promises[rid] = { resolve , reject } ; + queue_ids.push(rid); + queue_cmd.push(kind); + queue_cmd.push(rid); + queue_cmd.push(request); + queue_cmd.push(data); + if (!more) flushQueue(); + } catch(err) { + reject(err); + } + }); +} + +export function sendGET( request, params, more ) { return sendRequest('GET',request,params,more); } +export function sendSET( request, params, more ) { return sendRequest('SET',request,params,more); } +export function sendEXEC( request, params, more ) { return sendRequest('EXEC',request,params,more); } + +function flushQueue() { + if (!waiting && (queue_cmd.length > 0 || pending > 0)) { + console.log("flushQeue\n"); + const cmd = queue_cmd.length > 0 ? queue_cmd : 'POLL' ; + const ids = queue_ids ; + queue_ids = []; + queue_cmd = []; + waiting = true ; + socket.send( cmd ) + .then(() => {console.log("query sent\n"); socket.receive().then(receiveResponse)}) + .catch((err) => { + console.log("error: " + err + "\n") + waiting = false; + ids.forEach( (id) => rejectRequest(id,err) ); + }); + } +} + +function receiveResponse( commands ) { + console.log("response received\n"); + waiting = false; + while( commands.length ) { + var rid,data,err; + const cmd = commands.shift(); + switch( cmd.toString() ) { + case 'NONE': + break; + case 'DATA': + rid = commands.shift(); + data = commands.shift(); + resolveRequest(rid,data); + break; + case 'ERROR': + rid = commands.shift(); + err = commands.shift(); + rejectRequest(rid,err); + break; + case 'KILLED': + rid = commands.shift(); + rejectRequest(rid,'killed'); + break; + case 'REJECTED': + rid = commands.shift(); + rejectRequest(rid,'rejected'); + break; + case 'WRONG': + err = commands.shift(); + console.log('SERVER-ERROR:' + err); + // Dome.warn('SERVER-ERROR:',err); + break; + default: + // Dome.warn('SERVER-UNKNOWN-RESPONSE:',cmd,commands); + console.log(`SERVER-UNKNOWN-RESPONSE: (${cmd})\n`,commands); + commands.length = 0; + break; + } + } + flushQueue(); +} + +function rejectRequest(rid,err) { + const entry = promises[rid]; + if (entry) { + delete promises[rid]; + pending--; + entry.reject(err); + } +} + +function resolveRequest(rid,data) { + const entry = promises[rid]; + if (entry) { + delete promises[rid]; + pending--; + try { + entry.resolve(JSON.parse(data)); + } catch(err) { + entry.reject(err); + } + } +} + +// -------------------------------------------------------------------------- + +System.atExit(() => { + stopServer(); + stopSocket(); +}); + +export default { + isStopped, isRunning, + startServer, stopServer, + sendSET, sendGET, sendEXEC, + getPending, killPending +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/backup/style.css b/Ivette/backup/style.css new file mode 100644 index 00000000000..96b0490f3cd --- /dev/null +++ b/Ivette/backup/style.css @@ -0,0 +1,50 @@ +/* -------------------------------------------------------------------------- */ +/* --- Ivette Styling --- */ +/* -------------------------------------------------------------------------- */ + +.ivette-dongle { + flex-wrap: nowrap ; + margin: 8px ; + padding: 6px ; + max-width: 480px ; + background: #ddd ; + border: thin solid darkgrey ; + border-radius: 8px ; +} + +.ivette-dongle-id { + min-width: 80px ; +} + +.ivette-project { + margin: 6px 6px 18px 6px ; + padding: 3px ; +} + +.ivette-dongle-selectable:hover { + background: orange ; +} + +.dome-window-inactive .ivette-dongle { + background: #eee ; +} + +.dome-window-active .ivette-dongle-selected { + background: #ffcd00 ; +} + +.ivette-plugin-item { + margin: 2px ; + padding: 0px 6px ; + background: lightgrey ; + border: thin solid darkgrey ; + border-radius: 10px ; + align-items: baseline ; +} + +.ivette-dongle-cancel { + position: relative ; + visibility: hidden ; + top: 15px ; + height: 18px ; +} diff --git a/Ivette/electron-webpack.json b/Ivette/electron-webpack.json new file mode 100644 index 00000000000..048484644ed --- /dev/null +++ b/Ivette/electron-webpack.json @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------- +// --- Electron-webpack configuration file for Dome +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/electron-webpack.json + + This configuration file makes electron-webpack loading + webpack extensions to resolve Dome packages differently + for electron main-process and renderer-process. + + You may configure further electron-webpack to your convenience. +*/ + +{ + "main": { + "webpackConfig": "webpack.main.js" + }, + "renderer": { + "webpackConfig": "webpack.renderer.js" + } +} diff --git a/Ivette/package.json b/Ivette/package.json new file mode 100644 index 00000000000..f64e23e2cd3 --- /dev/null +++ b/Ivette/package.json @@ -0,0 +1,36 @@ +{ + "name": "Ivette", + "version": "1.0.0", + "main": "index.js", + "repository": "git@git.frama-c.com:frama-c/Ivette.git", + "author": "Loïc Correnson <loic.correnson@cea.fr>", + "license": "MIT", + "devDependencies": { + "@babel/core": "^7", + "@babel/plugin-proposal-object-rest-spread": "^7.7.7", + "@babel/preset-env": "^7.7.7", + "@babel/preset-react": "^7.7.4", + "@hot-loader/react-dom": "^16.11.0", + "@types/react": "^16.9.17", + "babel-loader": "^8.0.6", + "css-loader": "^3.4.0", + "electron": "^7", + "electron-builder": "^21.2.0", + "electron-devtools-installer": "^2.2.4", + "electron-webpack": "^2.7.4", + "jsdoc": "^3.6.3", + "react-hot-loader": "^4.12.18", + "webpack": "^4.41.4" + }, + "dependencies": { + "codemirror": "^5.49.2", + "immutable": "^4.0.0-rc.12", + "lodash": "^4.17.15", + "react": "^16.8", + "react-dom": "^16.12.0", + "react-draggable": "^4.2.0", + "react-virtualized": "^9.21.2", + "source-map-support": "^0.5.16", + "zeromq": "^6.0.0-beta.5" + } +} diff --git a/Ivette/push-dome.sh b/Ivette/push-dome.sh new file mode 100755 index 00000000000..4e7e6914e31 --- /dev/null +++ b/Ivette/push-dome.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +DOME=$1 +BRANCH=$2 + +if [ "$DOME" == "" ] || [ "$BRANCH" == "" ] +then + echo "Usage: push-electron.sh <dome-clone-dir> <new-branch>" + exit 1 +fi + +git -C $DOME remote -v | grep -q dome/electron.git + +if [ "$?" != "0" ] +then + echo "Clone of dome/electron not found in '$DOME'" + exit 1 +fi + +echo "Push updates to $DOME#$BRANCH" + +git -C $DOME checkout -B $BRANCH + +FILES=$(cd src/dome ; git ls-files) + +for f in $FILES +do + cp -f src/dome/$f $DOME/$f +done + +git -C $DOME commit -a diff --git a/Ivette/src/dome/.gitignore b/Ivette/src/dome/.gitignore new file mode 100644 index 00000000000..48a7072b2d7 --- /dev/null +++ b/Ivette/src/dome/.gitignore @@ -0,0 +1,47 @@ +######################################### +# Makefile +######################################### + +.dome-*.stamp +.dome-*.back +.dome-*.orig +.dome-*.lock + +######################################### +# JavaScript +######################################### + +node_modules +yarn.lock +/package.json + +######################################### +# Example Application +######################################### + +/.babelrc +/webpack.main.js +/webpack.renderer.js +/webpack.plugin.js +/electron-webpack.json +/dist +/bin +/src/main/index.js +/src/misc/exports.js +/src/renderer/index.js +/src/renderer/Application.js +/src/renderer/Preferences.js +/src/renderer/styles.css +/src/renderer/demo +/src/plugins + +######################################### +# Documentation +######################################### + +/html +/doc/template/gallery-icons.html +/doc/template/gallery-styles.js +/doc/template/gallery-styles.html + +######################################### diff --git a/Ivette/src/dome/CHANGELOG.md b/Ivette/src/dome/CHANGELOG.md new file mode 100644 index 00000000000..4e51470c1da --- /dev/null +++ b/Ivette/src/dome/CHANGELOG.md @@ -0,0 +1 @@ +# Version 0.0.1 diff --git a/Ivette/src/dome/CONTRIBUTING.md b/Ivette/src/dome/CONTRIBUTING.md new file mode 100644 index 00000000000..718b8d2fcd6 --- /dev/null +++ b/Ivette/src/dome/CONTRIBUTING.md @@ -0,0 +1,56 @@ +## Authorship + +All contributions are proprietary of CEA Tech. +An exhaustive list of authors is maintained in [CONTRIBUTORS.md] file. + +## Git Conventions + +The branches are organized as follows: + +- `master` is the prototype for building the next release. +- `stable` is the current working candidate for the next release. +It shall be an ancestor of `master` and is considered ready to be distributed. +- `release/DOME-vN.N.N` are tags pointing to public releases of the framework. +- `feature/*` are branches where new development are experimented before being merged +into `master`. + +The release branches `master`, `stable` and `release/*` are protected and only +release managers are authorized to merge into. + +It is highly recommended to not rebase `feature` branches already pushed on the repository, +unless there is only one contributor to the feature, on order to avoid losing data. + +## Javascript Coding Rules + +Your favorite editor shall be configured such that: +- indentation in two-spaces per level, with no tabulation +- module names are lowercase identifiers +- react compomnents are capitalized + +## Framework Organization + +- [CHANGELOG.md] tracks modifications with releases +- [CONTRIBUTING.md] recommandations for Dome developpers +- [CONTRIBUTORS.md] maintains the list of authors +- [LICENSE.md] framework terms and conditions +- [README.md] public description +- `./Makefile` framework quick-testing +- `./doc` framework documentation resources +- `./dist` local build for tests (generated) +- `./html` local documentation (generated) +- `./src/dome` framework sources +- `./template` framework configuration templates + +For developping an application with **Dome**, follow the indications +provided by the [README.md] file. + +The root Makefile is _not_ designed for +developping an application with the **Dome** framework. +See `make` or `make help` for details. + +This Makefile has been designed for live-editing and quick-testing the +framework itself (see « Live Editing » chapter of Html documentation). +You can type `make dev` to generate an application in `.` and live-edit the +generated `./src/main/*.js` and `./src/renderer/*.js` files. +Then, `make app` and `make dist` can be used to test the framework in production mode. +Use `make doc` to build the documentation in `./html` directory. diff --git a/Ivette/src/dome/CONTRIBUTORS.md b/Ivette/src/dome/CONTRIBUTORS.md new file mode 100644 index 00000000000..f7753c13aed --- /dev/null +++ b/Ivette/src/dome/CONTRIBUTORS.md @@ -0,0 +1,8 @@ +## Dome Contributors + +(by order of appearance) + +- [Loïc Correnson](loic.correnson@cea.fr), CEA-LIST, main architect +- [Franck Pujol](franck.pujol@atos.net), ATOS, early designer +- [Valentin Perrelle](valentin.perrelle@cea.fr), CEA-LIST, beta tester +- [Andre Maroneze](andre.oliveiramaroneze@cea.fr), CEA-LIST, beta tester diff --git a/Ivette/src/dome/LICENSE.md b/Ivette/src/dome/LICENSE.md new file mode 100644 index 00000000000..90f4610c925 --- /dev/null +++ b/Ivette/src/dome/LICENSE.md @@ -0,0 +1,5 @@ +Copyright (C) 2016 +CEA (Commissariat à l'énergie atomique et aux énergies alternatives) + +All rights reserved. +Contact CEA LIST for licensing. diff --git a/Ivette/src/dome/Makefile b/Ivette/src/dome/Makefile new file mode 100644 index 00000000000..91d1bf27385 --- /dev/null +++ b/Ivette/src/dome/Makefile @@ -0,0 +1,45 @@ +# -------------------------------------------------------------------------- +help: + @echo "*****************************************" + @echo "*** Dome Framework Makefile ***" + @echo "*****************************************" + @echo + @echo " make doc: alias for dome-doc" + @echo " make dev: alias for dome-dev" + @echo " make app: alias for dome-app" + @echo " make dist: alias for dome-dist" + @echo " make dome-help: detailed help for dome" + @echo " make DEMO=<xxx> demo: switch to 'src/renderer/demo/xxx.js' " + @echo + @echo "*****************************************" + +# -------------------------------------------------------------------------- + +APP=Dome +DOME=. +DEMO=Hello + +include $(DOME)/template/makefile + +.PHONY: doc demo dev app dist + +doc: dome-doc +dev: dome-dev +app: dome-app +dist: dome-dist + +demo: src/renderer/demo/$(DEMO).js + @echo "Switch to src/renderer/demo/$(DEMO).js" + @rm -f src/renderer/Application.js + @echo "// Dome Demonstrator" >> src/renderer/Application.js + @echo "import React from 'react' ;" >> src/renderer/Application.js + @echo "import Main from './demo/$(DEMO).js' ;" >> src/renderer/Application.js + @echo "export default (() => <Main/>);" >> src/renderer/Application.js + +src/renderer/demo/%.js: + @echo "Generate $@" + @echo "// Dome Demonstrator" > $@ + @echo "import React from 'react';" >> $@ + @echo "export default (() => <h1>$* Demo</h1>);" >> $@ + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/README.md b/Ivette/src/dome/README.md new file mode 100644 index 00000000000..049962c686f --- /dev/null +++ b/Ivette/src/dome/README.md @@ -0,0 +1,57 @@ +# Dome Framework + +This project allows you to build and distribute desktop applications. +The proposed framework is based on **React** [1] and **Electron** [2]. + +## Quick Start + +We strongly recommand to use **Yarn** [3] for installing the +necessary **Node** packages and their dependencies. Both shall be installed +with decently recent versions (`yarn -v 1.5.*` and `node -v 8.*`). + +Then, prepare a directory for developing your application, and download +the Dome Application Framework into sub-directory `dome`. +You shall setup a makefile for your application as follows: + +``` +include dome/template/makefile +all: dome-dev +``` + +Now, simply type `make` and all the necessary packages will be automatically +installed and configured. This can take a while for the very first installation. +Eventually, your application shall start with a « _Hello World_ » window. Now, +simply live edit the generated `src/renderer/Application.js` which is the main +entry point of your application. + +## Advanced Usage + +You may install the framework in any directory, +provided you set the `DOME` makefile or environment variable accordingly. +By default, this variable is set to `./dome` by the template makefile. + +Type `make help` to see all the predefined compilation targets. +In particular, `make dome-doc` will generate the Dome Documentation locally, in +`$(DOME)/html/index.hml`. + +The `$(DOME)/template/makefile` is provided with usefull targets, but you can also +use your own scripts. All generated configuration files are borrowed from +resources located in the `$(DOME)/template` directory. You can extend and modify +all the generated files, simply follow the comments provided. + +Typicall installation places for the Dome framework are: +- `DOME=./dome` for usual application developpers; +- `DOME=./src/dome` for application developpers that also have to hack and live-edit the Dome framework; +- `DOME=.` is also possible to quick test the framework or make a demo in `src/renderer/Application.js`. + +The last option is not possible when installing the framework since it would conflict with your +own project development. For instance, if your install Dome with `git`, you must keep the `$(DOME)/.git` +distinct and ignore the entire `$(DOME)` directory in your own versionned files. + +## References + +[1] https://reactjs.org + +[2] https://electronjs.org + +[3] https://yarnpkg.com/lang/en/docs/install/ diff --git a/Ivette/src/dome/doc/README.md b/Ivette/src/dome/doc/README.md new file mode 100644 index 00000000000..1d046ec45e3 --- /dev/null +++ b/Ivette/src/dome/doc/README.md @@ -0,0 +1,26 @@ +# Introduction + +**Dome** allows you to build native, desktop applications using +[React](https://reactjs.org) javascript technology. It is build upon the +[Electron](http://electron.atom.io) framework, featuring a full-featured Chromium +engine which renders the graphical user interface to the user. + +The **Dome** framework provides you with the following facilities: +- all-in-one pre-configured rich development environment +- live-editing of your application code +- a collection of ready-to-use, well designed, scalable components +- easy integration with any other React components from your own +- binary distribution for all supported platform (Windows, Linux and MacOS) + +# Tutorials + +- [Quick Start](tutorial-quickstart.html) +- [Live Editing](tutorial-hotreload.html) +- [Application Design](tutorial-application.html) +- [Styling Components](tutorial-styling.html) +- [System Services](tutorial-services.html) + +# References + +- [Icon Gallery](gallery-icons.html) +- [Glossary](tutorial-glossary.html) diff --git a/Ivette/src/dome/doc/app.json b/Ivette/src/dome/doc/app.json new file mode 100644 index 00000000000..00507a9a78e --- /dev/null +++ b/Ivette/src/dome/doc/app.json @@ -0,0 +1,14 @@ +{ + "opts": { + "recurse": true, + "template": "doc/template" + }, + "plugins": [ "plugins/markdown" ], + "templates": { + "default": { + "useLongnameInNav": true, + "outputSourceFiles": false, + "includeDate": false + } + } +} diff --git a/Ivette/src/dome/doc/config.json b/Ivette/src/dome/doc/config.json new file mode 100644 index 00000000000..5afa1619947 --- /dev/null +++ b/Ivette/src/dome/doc/config.json @@ -0,0 +1,18 @@ +{ + "source": { + "include": [ "doc/README.md", "src" ] + }, + "opts": { + "recurse": true, + "tutorials": "doc/tutorials", + "template": "doc/template" + }, + "plugins": [ "plugins/markdown" ], + "templates": { + "default": { + "useLongnameInNav": true, + "outputSourceFiles": false, + "includeDate": false + } + } +} diff --git a/Ivette/src/dome/doc/gallery.css b/Ivette/src/dome/doc/gallery.css new file mode 100644 index 00000000000..128e7f8bacf --- /dev/null +++ b/Ivette/src/dome/doc/gallery.css @@ -0,0 +1,68 @@ +/* -------------------------------------------------------------------------- */ +/* --- Galleries & Palettes CSS --- */ +/* -------------------------------------------------------------------------- */ + +.database { + width: 100% ; + height: auto ; + display: flex ; + flex-direction: row ; + flex-wrap: wrap ; +} + +.refname { + -webkit-user-select: text; /* Safari 3.1+ */ + -moz-user-select: text; /* Firefox 2+ */ + -ms-user-select: text; /* IE 10+ */ + user-select: text; /* Standard syntax */ + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 14px ; + color: #4D8053; +} + +/* -------------------------------------------------------------------------- */ +/* --- Additional CSS for Icon Gallery --- */ +/* -------------------------------------------------------------------------- */ + +.icon-block { + margin: 3pt ; + padding: 2pt ; + display: flex ; + flex-direction: row ; + flex-wrap: nowrap ; + align-items: center ; +} + +.icon-block:hover { + background: lightblue ; +} + +.icon-name { + order: 2 ; + padding: 2pt ; + margin-left: 2pt ; + vertical-align: baseline ; + cursor: text ; + display: inline ; +} + +.icon-name:target { + background: orange ; +} + +.icon-name:hover, .icon-name:focus { + outline-style: none ; + text-decoration: none ; +} + +.icon-svg { + order: 1 ; + width: 20px ; + height: 20px ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Additional CSS for Style Palette --- */ +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/doc/icons.js b/Ivette/src/dome/doc/icons.js new file mode 100755 index 00000000000..0867937a8fc --- /dev/null +++ b/Ivette/src/dome/doc/icons.js @@ -0,0 +1,82 @@ +// -------------------------------------------------------------------------- +// --- Icons Gallery Generator +// -------------------------------------------------------------------------- + +const path = require('path'); +const icons = require(path.resolve( process.argv[2] )); +const index = []; +const sections = {}; + +// --- Indexing & Sectioning ----------------------------------------- + +for ( var name in icons ) { + const icon = icons[name]; + const section = icon.section || "Others" ; + if (section != "Others" && index.indexOf(section) < 0) index.push( section ); + var content = sections[section] ; + if (!content) sections[section] = content = [] ; + content.push(name) ; +} + +index.sort(); +if (sections["Others"]) index.push("Others"); + +console.log( `<div id="main">` ); + +// --- Gallery (per section) ----------------------------------------- + +console.log( `<div id="content">` ); +console.log( `<div id="page">` ); +console.log( ` <h1 class="page-title">Icons Gallery</h1>` ); + +for ( var s = 0 ; s < index.length ; s++ ) { + const section = index[s] ; + console.log( `<section>` ); + console.log( `<article><h4 id="SECTION.${section}">${section}</h4>` ); + console.log( ` <div class="database">` ); + + const content = sections[section] ; + content.sort(); + + for( var k = 0 ; k < content.length ; k++ ) { + const name = content[k]; + const icon = icons[name]; + const title = icon.title || name ; + console.log( ` <div class="icon-block" onclick="window.location.href='#ICON.${name}'" title="${title}">`); + console.log( ` <div class="icon-name refname" id="ICON.${name}">${name}</div>` ); + console.log( ` <svg class="icon-svg" viewBox="${icon.viewBox}">` ); + console.log( ` <path d="${icon.path}"/>`); + console.log( ` </svg>` ); + console.log( ` </div>` ); + } + console.log( ` </div>` ); + console.log( `</article>` ); + console.log( `</section>` ); +} + +console.log( `</div>` ); // #content +console.log( `</div>` ); // #page + +// --- Navigation Bar ------------------------------------------------ + +console.log( `<div id="index">` ); +console.log( `<nav>` ); +console.log( `<h2><a href="index.html">Dome</a></h2>` ); +console.log( `<h3>Classes</h3>` ); +console.log( `<ul><li><a href="module-dome_controls_icons.Icon.html">Icon (Component)</a></li>` ); +for ( var s=0; s < index.length ; s++ ) { + const section = index[s]; + console.log( ` <li><a href="#SECTION.${section}">${section}</a></li>` ); +} +console.log( `</ul>` ); +console.log( `<h3>Icons</h3><ul>` ); +for( var name in icons ) { + console.log( `<li><a href="#ICON.${name}">${name}</a></li>` ); +} +console.log( `</ul>`); +console.log( `</nav>` ); +console.log( `</div>` ); // #index + +console.log( `</div>` ); // #main + +// ------------------------------------------------------------------- diff --git a/Ivette/src/dome/doc/template/gallery-head.html b/Ivette/src/dome/doc/template/gallery-head.html new file mode 100644 index 00000000000..30ff5781d97 --- /dev/null +++ b/Ivette/src/dome/doc/template/gallery-head.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>Dome</title> + <script src="scripts/prettify/prettify.js"> </script> + <script src="scripts/prettify/lang-css.js"> </script> + <!--[if lt IE 9]> + <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> + <![endif]--> + <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> + <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> + <link type="text/css" rel="stylesheet" href="styles/gallery.css"> +</head> +<body> diff --git a/Ivette/src/dome/doc/template/gallery-tail.html b/Ivette/src/dome/doc/template/gallery-tail.html new file mode 100644 index 00000000000..e29004ae183 --- /dev/null +++ b/Ivette/src/dome/doc/template/gallery-tail.html @@ -0,0 +1,11 @@ + +<br class="clear"/> + +<footer> +Copyright (©) CEA Tech 2017 +</footer> + +<script> prettyPrint(); </script> +<script src="scripts/linenumber.js"> </script> +</body> +</html> diff --git a/Ivette/src/dome/doc/template/publish.js b/Ivette/src/dome/doc/template/publish.js new file mode 100644 index 00000000000..4aa8e4fc547 --- /dev/null +++ b/Ivette/src/dome/doc/template/publish.js @@ -0,0 +1,665 @@ +'use strict'; + +var doop = require('jsdoc/util/doop'); +var env = require('jsdoc/env'); +var fs = require('jsdoc/fs'); +var helper = require('jsdoc/util/templateHelper'); +var logger = require('jsdoc/util/logger'); +var path = require('jsdoc/path'); +var taffy = require('taffydb').taffy; +var template = require('jsdoc/template'); +var util = require('util'); + +var htmlsafe = helper.htmlsafe; +var linkto = helper.linkto; +var resolveAuthorLinks = helper.resolveAuthorLinks; +var scopeToPunc = helper.scopeToPunc; +var hasOwnProp = Object.prototype.hasOwnProperty; + +var data; +var view; + +var outdir = path.normalize(env.opts.destination); + +function find(spec) { + return helper.find(data, spec); +} + +function tutoriallink(tutorial) { + return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' }); +} + +function getAncestorLinks(doclet) { + return helper.getAncestorLinks(data, doclet); +} + +function hashToLink(doclet, hash) { + if ( !/^(#.+)/.test(hash) ) { return hash; } + + var url = helper.createLink(doclet); + + url = url.replace(/(#.+|$)/, hash); + return '<a href="' + url + '">' + hash + '</a>'; +} + +function needsSignature(doclet) { + var needsSig = false; + + // function and class definitions always get a signature + if (doclet.kind === 'function' || doclet.kind === 'class') { + needsSig = true; + } + // typedefs that contain functions get a signature, too + else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names && + doclet.type.names.length) { + for (var i = 0, l = doclet.type.names.length; i < l; i++) { + if (doclet.type.names[i].toLowerCase() === 'function') { + needsSig = true; + break; + } + } + } + + return needsSig; +} + +function getSignatureAttributes(item) { + var attributes = []; + + if (item.optional) { + attributes.push('opt'); + } + + if (item.nullable === true) { + attributes.push('nullable'); + } + else if (item.nullable === false) { + attributes.push('non-null'); + } + + return attributes; +} + +function updateItemName(item) { + var attributes = getSignatureAttributes(item); + var itemName = item.name || ''; + + if (item.variable) { + itemName = '…' + itemName; + } + + if (attributes && attributes.length) { + itemName = util.format( '%s<span class="signature-attributes">%s</span>', itemName, + attributes.join(', ') ); + } + + return itemName; +} + +function addParamAttributes(params) { + return params.filter(function(param) { + return param.name && param.name.indexOf('.') === -1; + }).map(updateItemName); +} + +function buildItemTypeStrings(item) { + var types = []; + + if (item && item.type && item.type.names) { + item.type.names.forEach(function(name) { + types.push( linkto(name, htmlsafe(name)) ); + }); + } + + return types; +} + +function buildAttribsString(attribs) { + var attribsString = ''; + + if (attribs && attribs.length) { + attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) ); + } + + return attribsString; +} + +function addNonParamAttributes(items) { + var types = []; + + items.forEach(function(item) { + types = types.concat( buildItemTypeStrings(item) ); + }); + + return types; +} + +function addSignatureParams(f) { + var params = f.params ? addParamAttributes(f.params) : []; + + f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') ); +} + +function addSignatureReturns(f) { + var attribs = []; + var attribsString = ''; + var returnTypes = []; + var returnTypesString = ''; + + // jam all the return-type attributes into an array. this could create odd results (for example, + // if there are both nullable and non-nullable return types), but let's assume that most people + // who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa. + if (f.returns) { + f.returns.forEach(function(item) { + helper.getAttribs(item).forEach(function(attrib) { + if (attribs.indexOf(attrib) === -1) { + attribs.push(attrib); + } + }); + }); + + attribsString = buildAttribsString(attribs); + } + + if (f.returns) { + returnTypes = addNonParamAttributes(f.returns); + } + if (returnTypes.length) { + returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') ); + } + + f.signature = '<span class="signature">' + (f.signature || '') + '</span>' + + '<span class="type-signature">' + returnTypesString + '</span>'; +} + +function addSignatureTypes(f) { + var types = f.type ? buildItemTypeStrings(f) : []; + + f.signature = (f.signature || '') + '<span class="type-signature">' + + (types.length ? ' :' + types.join('|') : '') + '</span>'; +} + +function addAttribs(f) { + var attribs = helper.getAttribs(f); + var attribsString = buildAttribsString(attribs); + + f.attribs = util.format('<span class="type-signature">%s</span>', attribsString); +} + +function shortenPaths(files, commonPrefix) { + Object.keys(files).forEach(function(file) { + files[file].shortened = files[file].resolved.replace(commonPrefix, '') + // always use forward slashes + .replace(/\\/g, '/'); + }); + + return files; +} + +function getPathFromDoclet(doclet) { + if (!doclet.meta) { + return null; + } + + return doclet.meta.path && doclet.meta.path !== 'null' ? + path.join(doclet.meta.path, doclet.meta.filename) : + doclet.meta.filename; +} + +function generate(title, docs, filename, resolveLinks) { + resolveLinks = resolveLinks === false ? false : true; + + var docData = { + env: env, + title: title, + docs: docs + }; + + var outpath = path.join(outdir, filename), + html = view.render('container.tmpl', docData); + + if (resolveLinks) { + html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a> + } + + fs.writeFileSync(outpath, html, 'utf8'); +} + +function generateSourceFiles(sourceFiles, encoding) { + encoding = encoding || 'utf8'; + Object.keys(sourceFiles).forEach(function(file) { + var source; + // links are keyed to the shortened path in each doclet's `meta.shortpath` property + var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); + helper.registerLink(sourceFiles[file].shortened, sourceOutfile); + + try { + source = { + kind: 'source', + code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) ) + }; + } + catch(e) { + logger.error('Error while generating source file %s: %s', file, e.message); + } + + generate('Source: ' + sourceFiles[file].shortened, [source], sourceOutfile, + false); + }); +} + +/** + * Look for classes or functions with the same name as modules (which indicates that the module + * exports only that class or function), then attach the classes or functions to the `module` + * property of the appropriate module doclets. The name of each class or function is also updated + * for display purposes. This function mutates the original arrays. + * + * @private + * @param {Array.<module:jsdoc/doclet.Doclet>} doclets - The array of classes and functions to + * check. + * @param {Array.<module:jsdoc/doclet.Doclet>} modules - The array of module doclets to search. + */ +function attachModuleSymbols(doclets, modules) { + var symbols = {}; + + // build a lookup table + doclets.forEach(function(symbol) { + symbols[symbol.longname] = symbols[symbol.longname] || []; + symbols[symbol.longname].push(symbol); + }); + + return modules.map(function(module) { + if (symbols[module.longname]) { + module.modules = symbols[module.longname] + // Only show symbols that have a description. Make an exception for classes, because + // we want to show the constructor-signature heading no matter what. + .filter(function(symbol) { + return symbol.description || symbol.kind === 'class'; + }) + .map(function(symbol) { + symbol = doop(symbol); + + if (symbol.kind === 'class' || symbol.kind === 'function') { + symbol.name = symbol.name.replace('module:', '(require("') + '"))'; + } + + return symbol; + }); + } + }); +} + +function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) { + var nav = ''; + + if (items.length) { + var itemsNav = ''; + + items.forEach(function(item) { + if ( !hasOwnProp.call(item, 'longname') ) { + itemsNav += '<li>' + linktoFn('', item.name) + '</li>'; + } + else if ( !hasOwnProp.call(itemsSeen, item.longname) ) { + var displayName; + if (env.conf.templates.default.useLongnameInNav) { + displayName = item.longname; + } else { + displayName = item.name; + } + itemsNav += '<li>' + linktoFn(item.longname, displayName.replace(/\b(module|event):/g, '')) + '</li>'; + + itemsSeen[item.longname] = true; + } + }); + + if (itemsNav !== '') { + nav += '<h3>' + itemHeading + '</h3><ul>' + itemsNav + '</ul>'; + } + } + + return nav; +} + +function linktoTutorial(longName, name) { + return tutoriallink(name); +} + +function linktoExternal(longName, name) { + return linkto(longName, name.replace(/(^"|"$)/g, '')); +} + +/** + * Create the navigation sidebar. + * @param {object} members The members that will be used to create the sidebar. + * @param {array<object>} members.classes + * @param {array<object>} members.externals + * @param {array<object>} members.globals + * @param {array<object>} members.mixins + * @param {array<object>} members.modules + * @param {array<object>} members.namespaces + * @param {array<object>} members.tutorials + * @param {array<object>} members.events + * @param {array<object>} members.interfaces + * @return {string} The HTML for the navigation sidebar. + */ +function buildNav(members) { + const title = process.env.APP || 'Dome' ; + var nav = '<h2><a href="index.html">' + title + '</a></h2>'; + var seen = {}; + var seenTutorials = {}; + + const indexTutorials = require( path.resolve(process.env.DOME,'doc/tutorials/index.json' )); + const sortedTutorials = members.tutorials.sort((a,b) => { + const ta = indexTutorials[a.name] ; + const tb = indexTutorials[b.name] ; + const ra = (ta && ta.order) || 0 ; + const rb = (tb && tb.order) || 0 ; + return ra - rb ; + }); + + nav += buildMemberNav(sortedTutorials, 'Tutorials', seenTutorials, linktoTutorial); + nav += buildMemberNav(members.modules, 'Modules', {}, linkto); + nav += buildMemberNav(members.classes, 'Classes', seen, linkto); + nav += buildMemberNav(members.events, 'Events', seen, linkto); + nav += buildMemberNav(members.interfaces, 'Interfaces', seen, linkto); + nav += buildMemberNav(members.mixins, 'Mixins', seen, linkto); + nav += buildMemberNav(members.namespaces, 'Namespaces', seen, linkto); + nav += buildMemberNav(members.externals, 'Externals', seen, linktoExternal); + + if (members.globals.length) { + var globalNav = ''; + + members.globals.forEach(function(g) { + if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) { + globalNav += '<li>' + linkto(g.longname, g.name) + '</li>'; + } + seen[g.longname] = true; + }); + + if (!globalNav) { + // turn the heading into a link so you can actually get to the global page + nav += '<h3>' + linkto('global', 'Global') + '</h3>'; + } + else { + nav += '<h3>Global</h3><ul>' + globalNav + '</ul>'; + } + } + + return nav; +} + +/** + @param {TAFFY} taffyData See <http://taffydb.com/>. + @param {object} opts + @param {Tutorial} tutorials + */ +exports.publish = function(taffyData, opts, tutorials) { + data = taffyData; + + var conf = env.conf.templates || {}; + conf.default = conf.default || {}; + + var templatePath = path.normalize(opts.template); + view = new template.Template( path.join(templatePath, 'tmpl') ); + + // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness + // doesn't try to hand them out later + var indexUrl = helper.getUniqueFilename('index'); + // don't call registerLink() on this one! 'index' is also a valid longname + + var globalUrl = helper.getUniqueFilename('global'); + helper.registerLink('global', globalUrl); + + // set up templating + view.layout = conf.default.layoutFile ? + path.getResourcePath(path.dirname(conf.default.layoutFile), + path.basename(conf.default.layoutFile) ) : + 'layout.tmpl'; + + // set up tutorials for helper + helper.setTutorials(tutorials); + + data = helper.prune(data); + data.sort('longname, version, since'); + helper.addEventListeners(data); + + var sourceFiles = {}; + var sourceFilePaths = []; + data().each(function(doclet) { + doclet.attribs = ''; + + if (doclet.examples) { + doclet.examples = doclet.examples.map(function(example) { + var caption, code; + + if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) { + caption = RegExp.$1; + code = RegExp.$3; + } + + return { + caption: caption || '', + code: code || example + }; + }); + } + if (doclet.see) { + doclet.see.forEach(function(seeItem, i) { + doclet.see[i] = hashToLink(doclet, seeItem); + }); + } + + // build a list of source files + var sourcePath; + if (doclet.meta) { + sourcePath = getPathFromDoclet(doclet); + sourceFiles[sourcePath] = { + resolved: sourcePath, + shortened: null + }; + if (sourceFilePaths.indexOf(sourcePath) === -1) { + sourceFilePaths.push(sourcePath); + } + } + }); + + // update outdir if necessary, then create outdir + var packageInfo = ( find({kind: 'package'}) || [] ) [0]; + if (packageInfo && packageInfo.name) { + outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') ); + } + fs.mkPath(outdir); + + // copy the template's static files to outdir + var fromDir = path.join(templatePath, 'static'); + var staticFiles = fs.ls(fromDir, 3); + + staticFiles.forEach(function(fileName) { + var toDir = fs.toDir( fileName.replace(fromDir, outdir) ); + fs.mkPath(toDir); + fs.copyFileSync(fileName, toDir); + }); + + // copy user-specified static files to outdir + var staticFilePaths; + var staticFileFilter; + var staticFileScanner; + if (conf.default.staticFiles) { + // The canonical property name is `include`. We accept `paths` for backwards compatibility + // with a bug in JSDoc 3.2.x. + staticFilePaths = conf.default.staticFiles.include || + conf.default.staticFiles.paths || + []; + staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles); + staticFileScanner = new (require('jsdoc/src/scanner')).Scanner(); + + staticFilePaths.forEach(function(filePath) { + var extraStaticFiles; + + filePath = path.resolve(env.pwd, filePath); + extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter); + + extraStaticFiles.forEach(function(fileName) { + var sourcePath = fs.toDir(filePath); + var toDir = fs.toDir( fileName.replace(sourcePath, outdir) ); + fs.mkPath(toDir); + fs.copyFileSync(fileName, toDir); + }); + }); + } + + if (sourceFilePaths.length) { + sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) ); + } + data().each(function(doclet) { + var url = helper.createLink(doclet); + helper.registerLink(doclet.longname, url); + + // add a shortened version of the full path + var docletPath; + if (doclet.meta) { + docletPath = getPathFromDoclet(doclet); + docletPath = sourceFiles[docletPath].shortened; + if (docletPath) { + doclet.meta.shortpath = docletPath; + } + } + }); + + data().each(function(doclet) { + var url = helper.longnameToUrl[doclet.longname]; + + if (url.indexOf('#') > -1) { + doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop(); + } + else { + doclet.id = doclet.name; + } + + if ( needsSignature(doclet) ) { + addSignatureParams(doclet); + addSignatureReturns(doclet); + addAttribs(doclet); + } + }); + + // do this after the urls have all been generated + data().each(function(doclet) { + doclet.ancestors = getAncestorLinks(doclet); + + if (doclet.kind === 'member') { + addSignatureTypes(doclet); + addAttribs(doclet); + } + + if (doclet.kind === 'constant') { + addSignatureTypes(doclet); + addAttribs(doclet); + doclet.kind = 'member'; + } + }); + + var members = helper.getMembers(data); + members.tutorials = tutorials.children; + + // output pretty-printed source files by default + var outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false ? true : + false; + + // add template helpers + view.find = find; + view.linkto = linkto; + view.resolveAuthorLinks = resolveAuthorLinks; + view.tutoriallink = tutoriallink; + view.htmlsafe = htmlsafe; + view.outputSourceFiles = outputSourceFiles; + + // once for all + view.nav = buildNav(members); + attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules ); + + // generate the pretty-printed source files first so other pages can link to them + if (outputSourceFiles) { + generateSourceFiles(sourceFiles, opts.encoding); + } + + if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); } + + // index page displays information from package.json and lists files + var files = find({kind: 'file'}), + packages = find({kind: 'package'}); + + const title = process.env.APP || 'Dome' ; + generate(title + ' Documentation', + packages.concat( + [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}] + ).concat(files), + indexUrl); + + // set up the lists that we'll use to generate pages + var classes = taffy(members.classes); + var modules = taffy(members.modules); + var namespaces = taffy(members.namespaces); + var mixins = taffy(members.mixins); + var externals = taffy(members.externals); + var interfaces = taffy(members.interfaces); + + Object.keys(helper.longnameToUrl).forEach(function(longname) { + var myModules = helper.find(modules, {longname: longname}); + if (myModules.length) { + generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]); + } + + var myClasses = helper.find(classes, {longname: longname}); + if (myClasses.length) { + generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]); + } + + var myNamespaces = helper.find(namespaces, {longname: longname}); + if (myNamespaces.length) { + generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]); + } + + var myMixins = helper.find(mixins, {longname: longname}); + if (myMixins.length) { + generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]); + } + + var myExternals = helper.find(externals, {longname: longname}); + if (myExternals.length) { + generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]); + } + + var myInterfaces = helper.find(interfaces, {longname: longname}); + if (myInterfaces.length) { + generate('Interface: ' + myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]); + } + }); + + // TODO: move the tutorial functions to templateHelper.js + function generateTutorial(title, tutorial, filename) { + var tutorialData = { + title: title, + header: tutorial.title, + content: tutorial.parse(), + children: tutorial.children + }; + + var tutorialPath = path.join(outdir, filename), + html = view.render('tutorial.tmpl', tutorialData); + + // yes, you can use {@link} in tutorials too! + html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a> + + fs.writeFileSync(tutorialPath, html, 'utf8'); + } + + // tutorials can have only one parent so there is no risk for loops + function saveChildren(node) { + node.children.forEach(function(child) { + generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name)); + saveChildren(child); + }); + } + saveChildren(tutorials); +}; diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.eot b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..5d20d916338a5890a033952e2e07ba7380f5a7d3 GIT binary patch literal 19544 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.svg b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..ff4d7ddb6aeedf32398e5f02be7aa31759373ccb GIT binary patch literal 118258 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 F|NlzvfBgUe literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.woff b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Bold-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..1205787b0ed50db71ebd4f8a7f85d106721ff258 GIT binary patch literal 22432 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.eot b/Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..1f639a15ff3cc66d3b22b55a7f28a8cf0d821b03 GIT binary patch literal 20133 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.svg b/Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..5ef8ef90048c8f1600aa087b1b7b7617341986ea GIT binary patch literal 121111 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 bk3Kwo?~lIo?A7h-H{bitvo{a#fA9YTdsBSf literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.woff b/Ivette/src/dome/doc/template/static/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..ed760c0628b6a0026041f5b8bba466a0471fd2e0 GIT binary patch literal 23048 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.eot b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..0c8a0ae06ed09f6a7be1b84defae7ccda65cc2e0 GIT binary patch literal 20265 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.svg b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..d86c165fb1332ba91e2cac838a747822d451f26f GIT binary patch literal 122494 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 a`Nipnzw?7<ukK%e{lgzT`}*m#AO1hJ*{j_E literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.woff b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Italic-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..ff652e64356b538c001423b6aedefcf1ee66cd17 GIT binary patch literal 23188 zcmZsB1B@t5(Cyl`ZQHu*-MhAJ+qP}nwr%fS+qS*?_RF7_yqEkvIjOEQr@E_WlA2DY zU1dc@0RRDhn?@1<@_#l3=70SE`u~3u6;+Z3001oeWpVz4p$qV*n6QZGFE{k-<NbmF z5C;H6OiotumpcRi04W3jfXtzFKo=BKR2BpP01Nxo`2V6T&mb&ER*{|w00123*Vp-l zUfy*)u%WfS-7jbL8=nOL00h)(Yt>`u;zaN}4#cm9;TJrV-(X@UcBa<99LMh*@4q%a z658XBslMZHEF8<P=0EL!Krpp(H~Hmw004w!008U=%oK&`&5ZSp0088pe(y8?f(^hu z>E7&@{N?(7eZpUmz@dN=nOQrz{c^wS0FnX#0PY&N6gaW6HT=~n{pJC<@{8T1$@+6^ zeYf9vRsNfg;6DIk0YTa5TO0p!6u+9~-y8)juwn@9Y#p5d0MvdZfN#I!0Tg>&FWEU5 z|Hi6+{*rP3;X#<_($(1DH)oCi@&o%1rdRT{zZUQp08_jLv;Wy~L-D@<?DP_bmD{?Z zo{^s3F0cV47=oUG9>{>Jz!cCi<L|nI0Do8GwqBhgEtMpOG5XU<bB$&l-(tQHYi3B1 z&(cE42-tEO4p1Du1bVq{V9759kA*B@_%F^)Ky^U~c|px$1RiTqME+S10n(@W4;`Kd zE>N&yEV4`qxM9cFbYFoBwRPh0IQ;|D4fE`%?=h|lqJ;7JoM{9rYwt=vI{#0HXKY2! z<#w}XvnSt|MJ*d;NbJ44`;PAe&RTb+XD!k<C4wSL6r>2!R=;EE^{LFESrNSh`nAZy zJdKpdNx@pe(!A3+AV&BXQYU^V{&dPr?JKPV%ePh+S55%E+dBOB&H1bBof1*H_{a-+ z!cgZ+Usy^o=wE)TAy^eIT?c|8O0}oLlvPLxS*Hr89LbxIiVq;$a;9EcXAf!ExFAv9 z$`UV`>9;72Jk<4j<aHoT!r`5(DBP&*s0{+x?jcTyPy*o4J%~qSTYw$rAs*-x0_Z?H zJi1#O2)Y4Mj1a^&ph7#;5j~um_!F*8zf8N#c8PtlCLKc$9cA}Itg>KOIkE5eE@faJ z39}&EG=8uhA^cB((f&S2FWCV~4%n|(SqA=b3_^_<oZ=yxK&tJPzISoVH<~xAu@yg6 zBs2&0|K~zA*g){iaBjSfnow5<OeS0hna7#W+CIJ!9f_WseE7owg2@3RCMYb%Qi{1e z+h0+P1^q;;8e2Pju{zk{U{T@coCU5se!w)d%M4DRFNt2^glb$B=wV@@Cl!K6mQuYB z(nG$7k`?0fiLR6(P)w(E{x6a0=fG82fYkFKSzT^et}tIzC^`fSmKAGymmPdMzjEo% zj-csB#D#HBIL>sJrN4?<Ag%B^6lKl^CN~B*W-B7~bX#^a{(#sVDEHVy8@)mMH@KT` z$fxNZj*&jX%pmACY`;hw$RGodsvb(s07ldxt3?MK`!3n0#^&BeSK}fZXz-S1I1`#O zO@tdRt}=Ipi_%rux_mRgGMcRmf^A@{`XWPU2plXf78i@tsp<S|L9PgYqz~K|&O7I0 z<LSxVFCoMq>ceLlQ^nbEJeEQHU#H2z>}YNxKUs)6R0XaYM?<}-!OVDmq99p>I#LC# zn&y8e{%?p3T=wS~o0C=39sQ0_$>}1?-VzM$9F+AGZyWvezPCBr&7@Wvy=%}7mCy=i z$IP5_NDZ@7_FE{j!Rh*3bH1g}N=OZ?Hg*S_llA{XpllUGmk!coM<|PYbZqLlO&e?i z#c1~36?63{<)oTK^unXh81*MMn`weAFhKj1gr?(}c%+@pFT`e1`6h4$;Qd&)e$CVn zx<ss&_wrW4i+%IYq|S0k*QmQ0P&)3F=%Rbb1Z!@1zGiMvo6k>Q7|xI0Pa4uv{~fH& zO5R*Js*nq(QtuSBJ(YH;RKb2kd08RbX0hMs&Qs|wOnstj5zVY`UN3OzE|95Gz}Ks_ z=xl3zVpJ*A@vdBX!c{3X<f`$&{2DvMpCdpFWvOD*9$~W-F7(L#X)|2pj%mI~@i|^W zFAXb8RMSxDMe>IGIFyYE(Q5gvQU6oJ48jb?^z`iQA0YMPBx`6U^yMVzC8tg1CM9Ub z4eRvu04wxgfAGci3?Ug9-rheb7$892K7b_ZD8`gVvZfw|!Qc>}qtyF6F#L(4U_A6P zK+PHv0#O2i1~tJ<z+}OEL)i7!L-$yLk>g&V#NPpwnV8&w016PXP=9Obe>s@wn`HI% zP4o?LMJ}cJ`^)1AGV2<N8ye{8>Ft{s8k!jE8yL9v^*wI;{~^SpC<7dV35n^Sfr*0Y z>Q!I;_g&1$U`N9EM#aD|13q5wR%ZjO00lDzAk7Dh@jv71>6!THVS<T*A-n<~G6uZS zz`*-8K?VZFkpdarF)cEFnz9(dm{jR;jW|V~#Q>!Sgasr8WCbJyWCZjCBnLzab_s?L zV2Koi!}O|u|A1$XLNE3Llu<*}ME?0B@JH|uSj8lg2s*JG`oT}_5B?ATqwoIDz)#N) z#&^%x$8rBSxELOem)&mvHh3qVl}Fuue*m~Od<34_4u8pQ!V~G@5ecv;8(5o)C>cS2 zPz?YE3r&^PB~F&sCQp~wCs2Uk08xR#K2n0hKc)tUd#DJ>391T<bF2)Fb*>JNcd!uA z5wa4KW3&{NWwsWVXSf)d8M+#qYrGttZN46#Z$SS){e=1Ydx-J!^NjWOcaY&Q)>qkE ziKbJUU1sAA#gnQvI?X0m@6On4HrpM>8!=a&E;n1Fa!Cmp?!5;3f1V>7XhLGtVTNH~ z&W`j}jusiJR+rMUzzt58`NS<OvVC61p0Hi7x4W7X_jc#WXYqM`o-*?9pLs)4a*nra zz9Er6N@NVvm`txPg+^sim>6(sfh<4(4k45G{(JWVz?PUE0%^|Jz`&Uhk>J3C{D?6{ zy_xE>-@d?yqo2OOd(3ThP(T3enDAz9>)FcYt_z|l$z3EdiF2gTpw5`g_IdMTL9`eQ z=2XKjgxWX|)ganMG)_m{_#f)M$COPckHq}dFEOb>DLD&l<YG57nU$?t-I$Sv!o{+{ z_R(BQ_YMTfOQQ;BeBsy~dq?#N{RB2+D*Ke?$jynu<5uk4Nq@CwT#~Dhs}k=V5GqTl zW|>K!{$vdlwyBb@6ReAOvq&Jx;_yo}aRk0nNB~h{26H5vgdkPS6QoqY8B2!h6vl^T zf+?_JJ(Ud>bl_86<IHvxH-qUFIV2Nn)$3RvciMB^Hh@c1AzxbaM%C}tzspw$P>Gfh z|EyAS%42~k3@e0cgclA<`D}?Xl~;i>8KY2BIl~WKU6*dOgq`It+&RlvvM4T1JB!X+ z#m0!?3cHW7$&eqF%(R5kuSm&Py9`ga0H-tBQIayxdm{llrHN-(f~zgnLlxO9;-i}8 z#sZThtWhYtLtV++5;U5a($ke}T^WfS$38v?98b;IbUoOeK4RU{tNnCQX0@NnYfVjy zh~rCc$qt1VEy6@%@}0Ydb;2M{O#jhplLN~on#!mCH&eyRqJwQ{+cv8zDSaU^CyGD( zqIl{`q`t=ija4nSZ-v)cV|m0Es8O-iy&BJnTY+Nlo15#JtxgW}(3DpDen0g>m-ogl zz;gh8UqY$1-YO+u;Jtxjybh|UWQLwkb(KI_VwNh+DDAn7!n*D%#VF)CBR>6;+CEGC z!r65|$bQv1CjEiuu+S5`*@REPUM*;|4(70+BVeNuz1c)9>U;^o0{d^Klqw+4+~{er zt-6X8NS*cHV{!O+XBgo{B{Ht_@-me#%Fj|bJ<eEhc+Pc$mKL(B`BuyA-kFQ;mIm{A zNc9MNOj76_!@q;MpqYDHxStkw=T0@pRJr6o@MU@m0ALiB;7Do9Ycd4YE0_C|_<r`7 z`<#=~OA6jOj4a;tvmYI?iO4seJX;)-v@6;g!YR&yn`ykCnh{dYUxi)8$>)b*&PPU? z%^{3M1Ca$6)DrG7EiMP>q{=GWk^d~-ypZmVR_uh#CYO0(T!JX2-NQmxlqe<Po0AGJ z5kgy0jPdLy0--fRhT7nq;VmqO&hkAlu%QV<@|(I5>clCvQFodqT<`EIE!R)o_9Jec zh&jW<WbKo`DBLP43w@lxt#ul0%Jn6a&(HV{6fZAYyp>e2$`3AwX_xw0r#nPth98mN zGSs%P;WS<Z;8F3V=fst#89Nv!Frtm6-!lE^MkZ`Asx_>7LqEzBn<A855fi-~_wlk^ zT6K+kQyeG9I)2vkTBEh@97&E_Mf`nF1TIsm0z6Ea5DWo1p|J*62M*x|onh!NZhfU> zetKb{BM;TD%(A8x@oVCvsM;q}Mzw7kCPVO=IV)WLt%{jhnY$Up;Nryur(od3Rr}uh zMtSyWYsCR@usC3n6|iZSm3p*wj9OS>&m;@`X**tW;QHbD{hebUt$FeS(&K#@YlpVW z#R<T5fZ!ty-DP&L0rZlA>qkFCfEgoPB|U-b19pJGOAx9PgX<@DU<2$S3Eic3fG}`? zKyt7F<{=B+h2#X$O%%F~j;};c?>!P^^Xq9mC6lu#1&d@uOOLlie&$0@@zz6J3q_0f zFgkn>dQXD>`?XD^;9D2Ah#$R~Cg;09py1mQwx~-(^pt*A>_T#s-0!$O-=BM}Uv2jL zp#%f~{P_WZcUv#^hV)txd48Sps>PAcXgu2@GxtEqYdRZN7KEn=Ed~YguuHB?`Wxe* z@wXbaezUcTh{ymP5wX5t9}t3qhU%i>yo0Xew4<u3qpAaHI`t>>jm%mS@yple-5fjN zrYrsBc<W&s1X0NkA)RV7nu8=iXVx%j{ibe6?1%fyUH;XwcM!)v_0&D4hjy+N{;z?Q zX76BH&kf^xG+pPsj==sANS9Cz+I7#j6re92p!i{rdwN^2$`CQI<Q*AN5Ts~P#wbSU zA+cbaeAq!1jud`{;@?{gTND@@R+o$^4&uo~Jd@@y88IUJ$(<>Q%G4cf`8ncJ4tiQm zv+g^}=eV1i8w@@=?n*sDxTz=3*4W9wb_zHdTOO$(yYjv}oT*?aH#|a}eNuTpaE?MV zJHr|CmO=RM`*?K`5`&W}qWq;7T*f*4j%Pp!NN+$Lln9}~t~Wxg0w~r~4#@H%hi>t> zK13-5x&?z~E|T2Qpi>9}By?<KSi=G$;sNVAug3bXUc0n^bZcJ=>y1~Jql5MMkc0eh zaa1^kiL*<r>|^NXnJMG!P8=Q?pUrSDYV%s53+I{VbyP)HC^Fe3y1Q6Mz_9n?UUA<n zyYo-4VLVyii<98DW(52M8cvR^xl~wkG!FUK6kC}Y7<eQ0MV-`iTtE;poTvl=?L5Na z!FoTO3Q!vbCs0*;`e@siBWR2$+>OYIOosKNo5-dnMzDQ&lv8A+WcKwKCj;EKlCjk( z4A`!>4~pi}=H#g{Ue4mmj$2~3B&?*oJ~w{GPslCHlYdRNQdKK5y4&m^dOA+5R!>qN zy<JKk`)rG?wQpZDM}$I!x+=lSjtVYW@A0;}lhq3k#^tUGDyAC5SHTt?9xCR@vVfxm z0nypd17%>iji@nCu0lX)$r1#p^jDO#iYg%b3&O<8S%c~^M)T!)2ug)O<p<$J`oeOw zMa?kS|Jk3*i&wWe;T=i;zyj~eb4B0>yKPUPCndXI-Pr@xY292t>V!kuU%R<VDW!>2 z9t#D_jrehm9H%+T{d51<D3y-M20d@M`#c4MZ0vpcLy_wACeGn<a0th@lEd#PFx_`P za16Mx9FyMZweAlZnbN}fVA0jcBnmICb&%a+a*1=Ko&WSMw|l)Gl8eUc$-g|a+UlJ` z!_RMgG2+c(J?f$0zBBt5E^76CX4jkBWU@y{d1Lhh8wGCyczqP|Bpxj|U#e--QapkM zf+y7DNgVEoQS2V2gG+<}0~2)9P+pu+FK6ZGuK@LrC0>|$?@_q|ikmn_Fi1ZYN|O7a z6Cs9iQR%ajYh)}e<U%kZ?Q(_S)+(U}Et_PFa8^!o^b<(hOmciOtdYD^aE>?!^#-w| zi78Sc`kU8rLHzVmyX&NE^j4#QkLwYycjjSij8@iN=}8M8yWRDO0*;FAB2)F#CU^7S zpN@{BD!DqR>wm$4k<=fX$}WS6s{XmNwH3Gu3wGv{<O{j$buZc4(!-IJqArQ5Q{Hdq zgm3FT<%ZkBN)7@qyY%VTkS`i%+{GZw&4UzUn4BV849bOOm_sAcNwM*@dRb`cUHP}R zJkZ-A`YOzf9n)aQ&t`S=dM*j^JNiq8{M%}CZJ5}%6#K&_ZyB{Be1!beA9W!E9h?$; zA-&*gSYXh8(}Hy%T6+0)b^dzfOjsPTkiI{<ZzF}Too~^ZZ4&p)J?w{;B;kvDos20z z(1Uy=tX_c_!H*Op*ySt1W`DlBu$rNi$Y;yTG=vkQ(})fev`oSWC03JZ)7lxSZ~2nD z4##@l8oD4%C#Kij^doK)H}yPdlx@cPHV#vaIXq@&Qt!Y*Jb6{_*nHS`ukX1K`hnV^ zl~}{F{p2wj!sH@Ah)|f8%n_<>tY(|A``6X3M9KG#P}|IDedKg{QdnvSD-Vq?4!J}Z zGGizB_1WLS!YQUKL#zebLg+Akgh?{=$+g(z9Wol~6<L4kLp~yU>%G5tW4^+wDY11) zy2k}qnfq|J`%Y{6Y>2d0>(h^|I+L!3QgL4QYqS~QE^*>sGJNs%hbS;Che09X^1NN* zNF7t*Tuf6?9;dK8R7FIOcf&C!GF|`<I{<zVhPjxY78pqv(44LDaSlBw{z+LcHe{;4 z0mV%tp!_Kpk4DH`uN~BDLPb4wR%xUY#NTs(ib8ZN4K%`%g3NL2Cse>RI3Mjp=OOz! z2^JcCHrQ%(i|O+C&iq?4qv>YF_fq&-kK+Tp)fMveIx&mglR)n4w0nyF+SkgFn?Qk@ zvO4ri_s>#MA`g>cMhKT82-^?LrF1O`wuA(->iHJf_9<F|o?9y**7k_aAfKvncGCk# z`V1dPlneXO3q|sgi&*dpr?l^U4x?-lo|SMI;F%KC^gs)aC18P2Qo@JUkJPH!@nYkA z|2Ftclf0BJ+kWM^A>Q`$YVHk@K0DDh(L3{Q`_A%01tznh%(Z_Yd-lg>oBD>IK3A2J zDIJPMI*^s5&}VxaQfA<e2RtVNPbD9iZudb?4C1sKN={qKyuZVb_j5=_ypEj2sqoSQ zk<^l=WYV51?M-Snz`4V|<-WkX-)nsh{aV}ghTZe$bu);6yZdCUra9VvTK3C$J}Dtv znUuWOYme4vsStm((pq+fHCvOxz*gh<0G_=@!`Dvw=(4J77#og>A9@jzU&{^mxi6~2 zQ;{V8HmC*_L;|5rAx{%Ry9f^5tXZRR*@`hkpiHSwlH5_GF7#owQObn8826?}p~<!E zCI^G=ruyZZa^?9kMg_BU)l2ul;EjQ9d-$uK_NbNvmwc!y;;!11g&Hu!-#}=dV&@_n ziWsNC!q3Da4>MIvnNJKs70^;2D!1JS5V1eZL(-&BrV>e>B_>5+p4ohla%~_W%(!Gm z5e;+UeUI$z{b5w~X6t7pm!18&f(qXwg2&?JON~FJveWK0{3bPemHTTN_{DlT_=OA{ zFFte?p->*VsvhT=70HEdmK(qdPC*|okw;kg4~Zb_Wu-VrJyBgITHW8e{rL##*cgW) zF;X$|P8>4RfQfxJQ{jCOSuPGi8Ss6c_Ov^^d_lS*#n!PiJ+KP%wN8%b(=Ni9fHU6& zdepLaKGntt@dflu&Dq^2WVTeF4A+|?ok_b%&`$~%n-*)B#2=a;<Dno$@SHebwU5|_ zwc6RA@|Ph{<w{pZu0flJNxvDQh$m6T=^>D4XpUT^Va({R`K$h2P03e+P%m@)%?Jv7 z`qfr8-ChU|86d7Gz-&M);NpBKTaOp<#xZ2L6G)ETSG53F3QEMnp{61h&n&!0m>2|L zZW7SdOsrk2bDU#?VN@lTX(?EjwCK06!^uE$d|nmZ#>WTTTHnWaZsflwS<79YV}ma& zH<c>1Ze?zp$nbP1GyI*+d(#Q~fzYYFj9-g4tzIl$b{|FVv(h#nEjtUlyf*55#@O!F z_Sa*cjqlaDIyyoxO;C3Bu9xLdhB81srJht_K!}z81UP8zP%Vjz+!rKOt=E(-W_Es8 zX$($nT67_i`_ZKL*Pc2F8*n^I54*gkwVtdw<fWhAW`nBOF<J2!t<5v(yk5rY69zht zf_T)vT_g3>sABuqgCjW}Ux-eQU#W&a-=E#^k2UH#+piE%L*lO_{K;>sPOAOjrRy^( z_(oz`kdSb5F8wJ(Qo1_^N-n7|IXo76q4s+@9hC(hW3N(N@Qsm9c!-$t4J)9G7;0!y z6?=o}SBd}Rrt(%Q(yLL{t&Qi502?`n`BQhi5?nV*f%vpTYVN?k4WW)e>%hlt&}W8J zSdU??ncJ`UsNdePwpD}at&>+K#QedYUNLMBdX)BMYq8sK8dsqZ)mF7x<Y+*TNwoA= z7-q7}TMb^zPh6Um9l6`?k4@SwwmNDq5IEIB)uqt`Qsb%luv@#W$#kM4ZwIOyx+UpC zoi97w(>KOnDG{HZP0svNo$3&P3jUO>pHu*68bCh3AUbd!80aY#QHy|JXGS(+<}x%N zt-ut3bR<Ks3rvMdYqm8MokU3#Yu>-B_VC`H6-IYnjI4cYGqrh=71L~c{Vbp=j!IAC z@=qhL>`K_KweNQqqdrs~rJg>+Vdm!F&UR%64m}MZ-cExTMC(9gEoGq_Iy0fkL!}7g zeLhg!&MG3RJk$X%_3i6n3*#vRsFTQJL0hP^LX|5KzOf`36S|jSc|GCzBZdXSGnCf6 z9_26EvYVP7Jx^k#@y;DNwIgZomIMooO)42AC>j+EndvVWVn<sF&=QmelB)nWl$vUa znDTIxm4JA1*&^Ziup$K`4?j8X==e<JWw;vY9|--ZGuPQ<wfbf1Xz@Ribvy@ub}Dkf zS;}a?A2Po+b!~;h8*X8*Hq5g-4O~xj`PXjqngOuCgTC2%#^P;#?;75R+y+@%^IGC} zDg4li`lhIQ6Y3`N<0$IJoE-S8^^N*&(&=V%yi|i8i0$>Ht)^|V0FPn{oJj5>x;~JZ zQ^NY;`yuXur-jIUO<Gk-7XPb!oYD>+!wm3(NYB>Df~bcWeTswS?;07#<>~NEW7e{Z z_D0u@Q!FPJJJx%Fo{i!zd#%O60)D^^d3ziS*_X$+WussMED5Scb0bn>n2lLiVkqR9 zO_LX!HuJJFYMZuzSu&5uyC}zuW(V^^*ft+M_5&VR1Ez=IbFy0*K)wH9KVr#Be_SZ6 zWvTwz<y!7?Gq}j86s+_zy9&pU{xo#_dBlg%Shnt{^%#k6m$lMq3K(Bz3xj4Qpx&dH zynq}GYb^KYWWn$%<gpOKAZB!)REkXQ!>Ts%hDdv}!=amVi&5>GwW3~XvU*7Wa|DN% z^z$_|ZknNs^>DgrdA|gIyErRrP4A_4n-!<(`+i=$t$9#Tk4+YU+o{peA{P&wm#GKX zQQi+;fC%~;Q<&ylq{F!Iy31z4N)`x)L*UtmF4Mn?7i;GcAVC<e_g2`Y)kAj!#>)t% zX{WW(XlnnSc$35Fm7Phv6L<3laq3Vn{e(pKeLE;?yIFXO*<s2`69YUA<v9k8BWsA! z>kY;T`C5Io2a}EQiTONe{C>%is1@;&T}_nF*kg+xCzbz%xYj-RGAnbtG`1IAcq?!E zdX)zo0P1xGU?c@6S6AQDdV(a>b))Hb_VJGRvyD2qJv^6%U`Gxa`~_SINpcu3hsFS& z;sOVZZRF6d1xJc-0MsB^tbQJzeZ_4Krght%jh~(9o50T*TFGC|tDEh*^1#}g+Pm%k zeL9mNaZgJ0;Q>GBV%P2TdW4_Qd1F_Uo7n30{jQsE%gA3dASgQNW(%Vi(T|a&xI#jb zyF0_u)To4ILdnwevvA?v$bLPV{((K7QiA3%rV6Ch89t?~rx4LHdV+$2oEh^v5y)G& zw?=!<twe#C5<B^1B?TdQPv#edT;PUQXXnR}0>x)+9*y;=4*|C)w3S6nnc2a&D`VJT zYeHXd_qsR&ak)mHi%qy9X4SGti~6ifAD0Q_Nj0}w7Ng;v9a1VUg7<VNcwZk-I&N0X z7_*fwo<I^p4sgs`i(*a7r6z{BB@?54%i0xI+P!!RoV<4-B=dpwRoBi4pn3ZdKJ`IP z%>5}02<gL*$RlD7)0a@2AjO^cJuHL4kHs@y$gnL~2$|AAd9*fBrj%Sk;twr18<2!j zI$Q?lIA|hAEcS%wH#{Q_^M`4zQ<k(Hw)Un!eaBWgaaxU7m&0u*P`+T67$d?4#yYU? zWyJ0q!fe2x;jrdnhvEU6mcf^zm{%_Aqztn_E4IYd05omm(iHR(Wo>aaF&Xx<?pB0T zDC))qpoBMIHoSfd?)qrf%cJ57Ijwrfl-{9S$yAQh3`AEA9PxyHWH$euA(D@ZrGnT8 zj)C6+6m$+VT=0PK?KG4<{_}<XE{xwNcF<dw_j%#GRm0`ebege7{kxXu8LEtyS7nb_ z^@yLxLuLCel{r;re=Rqsz37zQ2Q{*A+J_Q+2r-%|odyi34J35y6rrp(;u4`t-_t|Q z(`>vpA$EdXwHjc%Pw3}UHMjk&a5jUTXZ+<yqUV~MuBqqvqwGm;i$_G)Ch_InK2`{G zy9r~iRL{t5U>3>ekLT!cNGPVzAK!~Q8Kbv0g2Vd7KWK%35(w(c441CjmRw}L#w;N7 zBHt^@R`0@NN))$jId9|Xe^+$L{tN+jeg@#E)7)6CTzy)UAXiarWCGe_%dSuX`McFb zalQCx-<U?mA?&(ah7IS15^6+ll`+kO;FNjH#VwK{kK?QDhk!}a()(y{-(FFpo5-xR z;`sV5!7+`uVxxSKx!<ttFfoPWq)G$7@b_53-I^c`;mFKohnI!6YI2;;KtM|2K|oFy zx>C%<Pz)|bbKYQ7)e+b87D*S}DTD$ApAw;M7(lklf1jI7BL}|VY(KnDJ#ARlpAS;b zN=;2}Xuj?y#^f`z&yEez;%kN5U*dOv`R|h!yWZ$Np09-SwvxKo>LfU;{`s+2OqGB0 z1wC~RdZUTg!G4la)8HSIqwoj@4R`rm0<=oDyxbhEcW6dv_3kuScn+{y1csqr8sriC z6k}6jqg1(UT{3otN@`*$2l>W@z$+b+AP5xvdb4`FkNtVoe6{@8f!Jue>%-ofg|4>t zKFsyL$)(Yrn6|d8z*O%%Z*SbBcH)!!7R1>wEM?CL%?3>js)T&Dq!-!hvk4d)Ork3> z&dwUeF&R#MmmN&qHv71V=lvkpl(FXM=aoS=vPRyv03%36NWcQHf#LSQzd({8P>Kx0 z0E&nQ)HYz$j52BbV+{PyE<8PNautLv@-V-#UupvSd*YiV8AG1Ll|QYMKgMjR!K>@3 zPBVIG(811-+VwnNT12+_OdphbMEUCb2FpfaV_U2x_WjbQ25v8tThEq`f#;xWUL#rH zwI*W6NP#VEP=-|sCe2|qMl0z+hp_M{7d~sSwr9Un{C8iF6@l}ZO^&xCXFTf{@+sk0 zEhxWjhbSMJj4t&jaeORYFCQ->`k03VNSE_kll!MH!S*@P@$jMrvuAQ>*xHD5{03mz z<k(RT`(M8xE+<FgJjz&qy;Wd#rL`vFH1ByP{%o>Xi!>>H?J@gT&D#hMXpUEu*QguP zvS>4Q=(UZjzPKM{ztt*f#W4DWa~mA{h<1vsR!VI6%8E`aHHQxrRQ};iyMh(i1nryK z$*8{+Wp*#vajki7F0ZF6w+078FNjn!tfksL=d(`Cu=G9feRuUhaWj9U)3sCr5Z$YN zn2!J%NCwKxL7MLF>;|~8-c%HC{}&cBxFuT;@e2VZiy*1)N7aM}lpe38Em}X9l@2tw zUuPs$v;voGemt2prSf=JOJsePCSOYkUJl$Y|FKHA%jyn<ZCV65&C<E-(}lf%aJ0ko zkVJY819odg$4|v6`qt9t=$G!9srRY5Nb0|=agrXSbb=1G@~kZqVi-nN=K6x6$c1>4 ze0gCJgodNadJ2caviT)@1eE8FCwW1^hqVVPDSYtfxq3$26V7-vW>I;>W4FIuGT0pA z0%TVI>Vy-f6R-BN*1jR;lZGjuhsxE^6?EGP)iZT{izyYJ2F{MPFKSAqd>qesQJ3hY za{E+eFnxDN=Am_S_-^@fJX&bajk6k@M}8ldZjKg1?%q1O-4(5dfFkD{FjUP}`5J<| z7Hn9US_T~SvMbH%h#ls%T`N(@O)U=`UNTe2KD-csF1D~x{k%S0=3pND{QF(A0rf7m zAE=$eH(EbX^9js!e@fCSxvh&i*wS7;ZO*06`5nECMyKTy{9WSA;!GyzQM$$Cqy2}- zB<tI;|L}thzvmyHOBmNT=eNcyN6QyI*GXd$QN7squewnhHpM_=_yvTRRe{2Q==%?j zmKaAFH8xQ+<iGt?_33@jL~%PXRd4}LUSC7Gt$KUoOVQ<jOE(|xr%KiflG|T2zP;|P zdG1+fHD-zLTRT;2{>EtV6ZBb<`+x6NI?eS$1D^$Ap02z}|5$#4p#csHt6%9q%kdA| zgQ(X9-(^O(hY}p(o^{LMh@HzuEnyT!zKmB->sOeElCki2?1c_N+OEvxFkY>td%a!s zY6g`4cs&VfKWT#hM3v^4MY^MMx6W!lCVAbJPx@rF6GuJ6Wh6EQ*uy9mPy-^$5TN?O z;&%ZTGyumVCRq~U#KSc*B9K-BapxCByLBqw+XmqQFT7@Bcs-rsw|=)B#b@6mzGY?W z&NJkhPXxhYGV5HT-VghRs(m|rV$gXunvcgnkVa=Bdsv@eAM)`(KPJ4T2d3dgB+zOV zVt}vfmATeoK4gJHdl78!^-u1n)0cr8mg7u7=0~^^_jg1mIT{oc5}6<S2MgYD=nM<y zOASNY!4XI<hcYTqJd4Z7#8yH(c6EouMzwiqz0_2nBz7jE4|j&X;B)hl?PrGh{xF-z zTGiLUcDfSokn`J~Z^*7a!ZIdeo2=}Zc}M5C+OcCBLG$C7WkoT`^J$#2BG820Sp<N{ zqO2;;_>$p*lZ2{el~f8dNdhTLFI4!PV>8yJGT#P)z<|5WpUlz9Cc8&Nz~ao2mxf}K zNy%L0h<A_6RUO_Xl=UKqs;3Os7!7PJ?A2Ma;f#fp285XW=)KvM3dO$dA>tQlai-%g zWU=Qx50fADPW*7+t-#8n$kt-W-Ct1;4|)sT=&pJAJb%T~Ylja`{1v6aW3Vx@zY^#% zQ*pa4VyCNQic~C6danal!Q<_G>rdxyRFH%!Z9BLS&3+ws_zLZuxIjNbJA*}hu`lVI z6t%@;c91#~t-yW<8lWUdWTZe1n!hojGyu(=iz=bjMG@~ii1@<@S2>?RpuXwih{nAv zC&<IQQqy1N=iN2j)PDH_`)p2|*Cyp+Dw*Um@K+IgWh232EFO|l6V3O#EsI1$^xErl z_Ysv98*i+dk8UG9CPdeMfK)A<kK<=r>r}4S+?6Zc{+Xk{_fq_K3-YEq$y95q<@0g~ z(*qHD0z)^8mjkwIq}~#T;fEPuMKPL*iPHVio{nqx`lbePYo9iZQK3S)*R?t`xHub> zeUav(tgrIJ=WJ88PX3d2i-C9b6g7U6lh&{H%=0rIU1y4y8Unr?Aa9#jfqPmlhG$EE z%NrlYD60k*U&2<AZUvZ;|A!Nj_aF8&S)o};PX^W}gs44i%B@_1ub9h0k!tTYqXR!) zN3Yo*_ykF!L%bdnqz1tpa*acwo=Vt>t|IWMNy=tWHT>J}^2A+0yWG~@J=$Bp0pxwE zxYBF0i#j0{Do(*ZK-KyH*m&|J9jxXe;qPw)tc(jJ1ahSXAx}WrpWx7L%2uAyFj@R# zF?saO<vT0PL^d^X*VH9_2aIU6R5q=>E@A$QbY7p4#^wk7uC+S=&W_<EZmY+GNk8<T zC7cq>538fkBaNjrWX1E$LAJ{s14<l?4oitmnu(Oah*TX9DVIBulN6<$-ZGmtp%?V2 zCut(Fiq0cAO(*+AoPt$FGG>8X2&dKnH>J*9xghgxf+lUV0<~K_gvz;%Fy(Yra9hzl zh!9<YhK^k^MBw%Y7&;Y@NFwI5V2P(p>kIwhao`a8uMN7E=c9#;3sI>D>H81Yojb-) zjFg4EHRO!XL*SN%gGJT>6DErMu3i3FVnBEpQ;;<;WOJ{tT5O-stxVswM`W9-OxBaN z@Tb2OFVQEXUOwk(UTse|w%sveT?DhbZ9b8o56ICM?E1J5%(glpxLcX@@UJ?It#{pA zR^D;&=EVi(B&{#qg0{{}T(IrKFaLt&E_@?zic8%A^6ZxBUv)AQSb5O7Eb-~g!D1g? z&$Z!wclJD`X=S4*QaKq9296R#ze#SmmWE$|-hsCld#?{2x7T`AywE%NM|SoNT`?U@ za~Ez54ddc<ojkC}s$9?RFAjx1O3FRU$?(#fj_;y>{+4@Lu4Vn!;EJ~ib5wAjZ{Y8$ z(R|}ZS-ux?E$;%_a|)MFo8$YPNqjzcP6A>r)<|j#)GBjGJP1GtF&&gI@RJ|0^m}^} z3VxuBx(rHvyC{sv1`y*U_LeW95o|zKT(`U_%RY)EYlbpQ2-4Mb7Dq-d;jp+HC|<~P zOw?HV@SNeGQnLY=9)(`%*2n#?2Czeu{W81=ugX4CYQJXkxvUsio)$aAWooC1vsJES zcMu0I13P;$g}&3j65%pOx7;ale{*{tK0?8+D7$Qr@<d){`92nzV@;2wG?{u#ZoAYE zJohifa;Z0$s!ta8w}(N6mZdyiUxZY}+D6filVDESO`x<j-=-@Mk@EpW3e1xtc7+C* z%$Bmj!Y~5O+$TT)Q4pxB0ceA`W1<VY=5IMwAE5D5-K8<qY4yxtIuIlT;yDzcoI5{H z7-_PBw==~GN+D4&H?y>l)37vGj4Jr^eA{cNurrB{Y_X-hEr_unQ%EBpL=*1`hjp8l zKAvN);uqkT`S3q~AiWS@2XH+Skx-SHmB*ZjF|TT~jXfG4N@?1Fp3Z9f<sMBqph`Uw zJxJ1OB0ZE??iTm{nP%RNTbE29Jn!73b=*`Q*Tq!~BCFa!Z49Bmg(MZ%>b|eheU3*L zo}5=?U^|>7bbqHo9y9i9sDFo7*s4MP<qtl7kYp)1%$+hR)N}CUh+Q*!N-J}<E3X;G zrdu}M9T@C6(T~{~cVK0cB}!(G0m{;-t0wA;F8o&MR4)!oeTOZUw0LRRm&;m{T#!Rc zk&(TO&CZuZn^?~Yj_ALg5O(AM-gkF?r+8avyzVATPSc1<)X*kEEIiqd8*C7tAV=Zv zcxBxYRr}X(pP9PjnX&i|*CI7`$p%(A&Y_0$@S_Q68^4Ep60H*XXa~7ag}4P!!;5cx zI4uc@H7S~&{R-^9Bk?)j`T@V6Pky*<P5WA>CB+o3o)dxp<bC$x*MAM&F*o$wTe^a4 zL&WpCfFlbpe@fGp+XYw(!;-#WUO&f7!@LW57#wZ9t(u2o22f*xS-}`Na}FVSS#VcP z9SH@75>+*g2PdvWmGr~yaJjQ(bnpDu7r3lkVy=j%VAmyeaiNEs?Vz6TI%OO`*u#Qt zo_r;5WEf?O!?@yLc)r|(YubfGihrOGtdbP;?%`Na2th_gQ`dkT<nK%!2jD=KR}VNP z=vLPjPNxAUV~r#^Ao1vza%Vv&Ght`4AV-P*GK?hbjDRnp!XT5McBD}Kn%ulW>w@k} z=yUg82Q<1cyLw=vq5&qhquRZdgvDi)<Yjf75Y-?ptFcmxuNe(~rPJ;*ruG(%IvFiE z;ol>I|0ppdrFc##9%V&9d&Niin*JskR#=qDBT61_Zi7bqV_E1$h)+C<8MC$x(-)5m z?{^GnUacp_h{OB+f-eHyI!w>&7c?51f^A9_W?~9-4$Sc2(O^FnB35M{0{u*SF>sIk z++C)rW=$8-X1mO$*wN!8*)+%HXkUAmi_*4Yi=jx{+t6yGJ+GFfs%eVU`PE}PKkOef z)zn;97hDwdVprIIaC34cT^$N&6n*Ib>c)wHx{4JOCD7D|($+Ds<0a76k1@Z`Ea%H+ zWmx*JAW0${7<=KoiLU<-DtFD4g?R0{TANvvtAmG2py_!?!AC?$a-u5~bIWYFy@<$( zv2CVhY%F|f&n#;@rtSfGorkkW1f*iXrs7|8EsMlFVO9(!^lK#yrjt2OHD#_cPm{Ag z9reS$=)VD;ZpNa^yLWgRmM~nbA{?Ox^IJNFd?3%HR7rLuSV}x%z&k8*jeFnB`w^P6 zVTE1#Vd)5~gMGx8fek8=lc;}0WbGPOmlkzScPM{|<Nr8cgD<cA7#2DPTS_ROXSKg{ z@jUnsi%>hN@|eHP-EGgL+FxT{e4{zvcfe#oS8OEVbn~GHeI29DF>?pI_EAs2c%ZHT z9FoZn2p4hrQyU&D7c1r7@l3LuQs~Z$LNUnaFQx-q;s+NlUM=esjBYkHfPEVcMr5z$ zrL^aZxgJ`3>>79w>L5_oO2cBS3ev4_fQe<#N_lhNXYUOLxsI?zzqWo#evvCzZgH<X zf8LZnxdG)=z1q^Q&S1YPFM5__6)7*^A)%N<5Y~-BWUh@Z6o|sg#-X!dl|+GtMZw}= zgbehMxylB4vzi)_8*h|x$5|(qF~i#cI-?gAT@G3O6*E3a1%*w1Vn(A$Tb5g6Fq89k z7gD}TsCd7B4+wc;u3)#W$m#L-lG7aKv!bvq%c=E(fM1r?U^3+O4jF!W64<FEsMTlL z7olOV9#IQEGfDmX7!;vQYL;{WAi5#*MTuZC9|&l2P3jv8^$8ym12dr8d;alWY4#?> zEfXHkf8EV2_RRvueR=!w&?wtb2;6S&n)pe)+=maR#fem8Nz%J)+@Ui2?jwonj4%Ek zc+B|T48O#0%|G7J@>BnLCA*nw0236*$>IU#6;~R{D<~ukHwtXh<S24C{`dyi4<s9) zV#tYXj>I>(gOgWRzaKZRLF0Q(w(2-2i3~kCgY#)J?is4%N#HoSe>NGi!`)0}_|^rg z`?)ulkVPKCUY*JIwdZ+z8qd1Wk|dQi5btUM#=3Mvr8ZyN#8Ayp`Vm&XJ^tYUM!$V0 z^+OwTZS4Ajwbtm%Oc$-iXf_98`|<(x?k~0P3c~9u@(N(ymkRTcaR!MC0+RG(UY(oR zo`MSrt}6Gm#m&hZ`9a31cz2n#*m(+_Ut#Jaq4DR%=qOe}XwmDTLJgRU2!^zPM(GmQ z1kk>*LJy3!a`sOa6m{uj9*l4W3<;$i-den5u{Oq5|9o`JqvaR_PRa9&epBjI(*k;< z7o%-}S%51Sl6cGTkf)k9Y(55}jjQ&;7quAMq4eq3G5*i{`&Z=0Qj@hWwk(GyRBG=} z%;)3V%ONkhDc%q-9L~^I4mX9b+iBkC$%)%Ze|E3$KsV3&{gv*{PyWt7sW%E-N5Sof zZ~Vj3*`ClzS$=BY+si*$4rBaL6SqDy1Hllc1Zd$R&Vz8I4N4*>c~Aiqb|b<J23P%Q zA|2Yd!{GsAkW05bYR>vq4iIP%BYNVafMQjoDy2`kwsFtEF@0|#xoYic&_)3MQLpO( zB=f8#?FzHxvbYW_N%9*5@3Rz_Tb&Iu9L$BA?1gNmr~fkE;Z<K_lz91xT5q>lr=`TA zg&x|`uAM>dxD~oF3V?Qq*Q`g_tWpRp^nFM6l!xy_!H<1|Gw-?>?^8REeZ?bg_Z8mC zv{FNK=MSob?@iogv2?Ichj)qkj3sW@*Zh%`XVP4ZD8Pd1u0sWuAi(UKP48P+t#=#| zdu;6wIx^XTyOF`j-$Q!XBAckbTD(!3NFg4`=pxWOS{^JYIC^>I$f$1NoDBX1Ka>p+ z0Yw9nf+#7g5}+cvp;F7<qnm*%Q<{3<xD?K(q@|rM1_kc!q+@EMt&<FKmT&8WqEz`5 zys56mTV}hx997>;*Z$m(j~?DnBqEolCd&E*6DkkCa2|Q^NNi7UIp%&IE$_8Yg?7<s zxMj8-sLuSf-E8zUJDSYj18lv(w?l3c<S9eAEk2?&HlEe{ok`enrkw$%7g3s5Fb7yq zhthBJTO6FCV`Ilo>9RO11_TrTMSI9p#S4B>>3Q9sNDyfz7X3YZ>Jqn(jNJ>oA0W3l zxk22<4nFVk#x#ebP!9DsL52zf5)u*?l9e)99ian+{bKHXb2kLn9kex&rDhm@{O`(y zGyD8{a}-|UnA|<_D>&Ql31Z-5X!(kVFY;l3G6XGzV<{Dxh(_&isttjYPz)%a578Y@ zwkiz{HqKVtx2Yay&6CCH%~whrG9k;JG%jN+i;~tNuk}wz#hfxv<?xRbfE6G32QImq zR$G)?Es{23xI<grJP(E27qJ-F^Vi##nh>P96_?Njk&FFL5Yv1~6H&QRF+Fc2dsMX6 z>+($P*4@v&`?~N%bkyf;K0?o#189|=(NK(1biO*y(jK#)b9G|ymkV76pG{umSR=;X ztpVSuZlZNUpYYod$cc8JJZ-7iPg<Q_WlsUpzcL2n<}Teiuc7+PZ#N&^i=!FOp)|L> zW_&eZ26^I2g+u!i{$`nYQiT3Wf7=|zWvu<>L9$Q3gUPvrPrgehyRZt^#DSeUCyqy2 zMNcGTNCCmG#s3{Qct^*i%j%fJ!DIRso#Vx7SW>S?{?%wnt224npT!&W?X-XVY&e$~ zwmjrD2(c9>-Kb@Dz}|uK5uvDV23d&@A^kp*hvq__4-ry}%UPDBM2%0IXkQq+&kUi7 z&9>FHv)8{qjh*>A$}I}rBwPO49CMdivDMQFp%h5HA|JfPtI0ZJa<fi~LtF|ZDoBtF zb_(i+!P)DFltH>GVLZlI3ou)>EaF<s1BMTV_|^fDvN$c9zgz&ST<A~VJSI?)keUEf z{RrfhrsPF3ghzYHR9Wbi@6l*h<5kYuSg5wpP7z<jKQ#2to0SCi_h3K{$`gPQQ`}qY z1C<~#xTCJT4zCj{qJM&@w$=>u8M%je33E6;a6oeay(H$vzgx+$H?tCZ!={|Opdrha zwsqt*o6jUI^Wq-2{q}DjPd;&-(q;AdNLv5!Nz>u(vJ<5By^p?GURuh@_|V&QytwZ9 zc!T{&qpQyk)?#(-YV1}xAel1G)Skev(a=$dQiPl8C0d!l9@!n!e&8R`owyL)_v)h3 z#w$xbfgM<Cqtec)yqt%s6C(~*2?X|T1j0<1Lob3N6e7~FN9*_b3Y2>34ifeJEA*rx zGr*XZs7KxhJA$Mty@fBss$EG&#lR#!oQhnmt9Hx&C902uijOMGotX5A!FoPr7A)MZ zf6bHTS<B>#m+6?;5P%|lq9Y79uqo6P*n}01EDwV=WEKT_UImrlN4lO&<o6+8UXa7| zK$i3_X{RkDn1FO(SV$BFRv||mCF&fd+3!j-^(MQA%XOm0WqM^gk;P94y2F<CP%ByO z>&8-6Pa$V012AC>WTU~lU?_h{eCC3mOey3ThqkKx*HBpv3uGdn3#p)=icwg3W-(WX zC>w=fQuLxM<<vDazb_7{Qngpv7c3;z{eUMY2t+o9oSe5>)gt!#+J<r*QUX#!U#gc3 z>(VBya^vvrklY97LVM!gLl3FIa7|8+B8Dx!{u^dUs=(n`u+arFX4TANeP6O<8q?!) zwo-t{((*>9KyqUCNJ%v@T3-=e#>;D@D1p|!{it-brHSwM6}VV`r%opGbCKqs!_W5J z;CX9Q?sd53Y4Y9UjOUK70;?%iNj5uXAi0Olw$eLTQLs}l0uyNgNQ>+nJO2Q&ysvGp z9W>$)!W6RJ-&+PtvqsBkr_L6jX09nHQC1~f$?8ffl|68<pBlPb^ulR?or^15Rs?yo zP<TiAYFrrHXTa1JSwut|MsVr9(A)*kZ}TMZTW}9YLu(V6xKCv903~9B2><hE3}F$l zgFLtq{q7`>NgUfk35HSa?R>(j6(BVT2DxxlaoS)6|FU4ot1A=0*K?3kUOKEHwkZQU zOl|)+r~Zd_(iPf=C59}5W!2-vvKL6W7`6N!UM9$xwls*$VHAK`^U~BmM6G>%!0WaC z*Wi6<0=kjnL<Ng*>CdJ}VI*ArvQl~7IN7_vH?^YTpGix?nP(dPD3KO_g4}dq5hJlu z0gv7UD#?S$i@z&G1N-&Z(xkr$b^zpkpx8F*8w)@DOdNyJbhVOsl)ev9T5~sSU$QeL zVdj5-lPA#VejU#{)c>ox54+qx{s4b{3-uzEBDYSYZ2}Kk8@GnJ5Ds~A*ar!yy%U{F zD75pi$R8%UPC=Q4B!Pn<JcQ*o(x-y}s|A!z2%w4)iH|Bl9ZmX^4ugF*3^@KM5j1?R z>)AAANytIEW*!?2*EpvsVh0i~C(^Ozp^hIsuwZy<k@&^r4*c9(%RXum)a@^wAY2X> zjuCV(Q;mbhFRcvsLO-Yzb&j%1h8r(D0f6L}T=z&_N81bdY|a9qr&zmWuqzyv7AL9X z5BK(z44zWs0=6*h4DBUCr`FwEHUgkp(MGK1sTHtL4zSDtd_h+H=i<6%PLmJX&eN^) zY%%CL`yY!H>=<OZel=7V5jch=t4|@d@S8QkmF3t4knP=cD2f}Fzg?AL1aT6;ChhGb zS91k**CE}l%#IYeoB4LmF+$y3mjbHp;NCMT6kr$&<(Y0F1`IQ4SPIlsMy8J6+H~fS zVryIrk_v;I0RW0J#XEwYDwLE#9|YC?3(I`tr<83+Sh#Sc7=z`72{`nd(k1YgbiRkn z1<ZwtpWbRY+lOb?6bt=&`E0nPk7w;dMfKgr^7g-L7I^sP$!gZ`67mKQ?6vLrmqW`9 zGD`r}<<k7qn|YKK77<@V)LpJc?$?wVSlTiw2_;~3b0tFILly($QWLnu`Q+WO*zky` zI`!!A65-`d{l#Hwo(T`uqToLrWZHXVO0bPjcP5>eLFH=x=oSca^`c$Y+@XYvXJOIx z>OzIE^EDup>)zn2k@edCS7C%eh9Lgnf1`tSgR)N>Mt|5=OXo#IJhmY3aAuW&>6aNy zfG~S_9}kOmn=1o$OI`eb*xr$L(cPi{IQf$$$N`@JfxfKTr)F&p#>X~<kiJ-I^psR6 zm^6=-h?Rz)LP5gq0<WQST*`Yvkp{eGNt2zsMXk^kAf#>fY#jpe)B<SA2q=-!gqAtz zIY=d-Mbec+lsX8sVr?lexBok!J3d-jhkha(AG_Bzes6i7nK%aSwu|y6eVI*ypQxJ~ z)O{Z=LGbj~1`k0)B*$5{WDZIy5>h2$H!8AOa8CF%S_~)EbYvB}#HjB|(}!pvQETrG z@s1K#)ugV;yQKGoc7tr#p!jDv1bG@$A`LZ;0#?A5f6i|99BciY>FBOt1XR<rxREap z<=*`bv~yOy-e%Ny`E|pe?5bw-XKtnHgtYRdXQHru^cG+prLiJmgHMJ|m#4-0doIz9 zt&sO(^!8z1NAv@S|0foBJ<ugAvLpGYlf_yO2N~C9P@iMUSUS#N(>0(I!wUqAecgrn zW(Um1OH1j{Hqa9*8@R2zTfJs=jLyp!dkoHVE<?G$PFq`VB~KN=rGuR{4Bi&_U$&rj zRT%`o97H_;*+uqk?F&ZW+N^EA81U5fc9I<I9$``uDTaGhRlv5Y3i76oetnu08R5*< zb|Xu|6THTmHCYo-%t?@B5r+?IYm*Zu?&S<Zap~lsdq8K0=!DqOfpnnRsP6G~WbQjm zCEw>qM)U{A`Z6g#x`u7RiZ^~MUWY9m_l0OfFh2Q6KA>4$Yabj*n5jmZ%SVHU&bb}c z{|TfSTju4S{=;djQrIE}${_pX(DM_W7G!7u9v}r3^J0Hl8bovSDkgT65_F2v6DKK` zKy-A!L$uXYnAJah;Ak5TcmMswo+I5#AD%lgb++f@qtA`^tjeALkhN#txI$O%_>x@5 z%(5j9M$6wM)AHZ-VH4*Hj<-**tLr_bV&<rVoIJ;@`T5VC8N55ivuIj!ZccXL+<uv3 z1{dZG$ai^%)UCXJ<+X#9H&}mzXs0%*itZu=fJPDJKabG9)^3SJrN;j1;7p`aBee=u z-<t7PtNkVBM8k@bw4F=R``>X~d##qHqdr~RsXjf{3LYxe<k689yVb4_2{c7uGckum zx_=Re#RU|HBnJUErX2@Z2rQ?|T2!iE!QoEhej^U<Zi%k{UmQ;V520sX>XqW+RGI)1 zS!%4(fKSkMH5yF-3oXMUq%#(|cOKY|hPDHZkWOgCQ#5*X|E0~)Mf!a@hKum&Ex5dG zLg*C*h5olLAVgyzDiors1g_AI(qXOE;>SeKFbVC9N#SoA-;R*J1EJ7P2z7HhC`wtG zp0u9b-QAKC9of$8+o5Lc*dyVCTkxv!A+%e;E8~`R(HkOEz!oZ10G$wqj;=F0{q8iZ z9gC0-EOec)P;kgdOQnkXcB|L><2i-L8g5ztnZF>^qO3osi;N<TR;{T3FGGd2s){?{ z;Qh6szY&j|tn^;g<@rTCz%l?H;yAt%bptz=hb}5>4-LnHHkl)8l7f+%%Zuvt4u*I9 zm6TaX(CV~;t{Q=MQxSDF&9V}ms?rcbv|4@?y$*^8meUZm8ja$xp7S?1<^Iw@h^#~N z1EX1iHnmjk5cI^~>eQ`I@9u7la{Kkp>yzh6bLVu=p}t*I1ikvwWYDT9qNp40W>m^= zrQo(3k5ZQ^b?I#pU7cFMaC@T*zjpSM$#DxJRdb%2xcuR@*Vc`^FG-s}CvL@sC7b0J z<ad+!y2k7kwR_uUO?-7p#a&YlO&!WztUZ>h|N9SvEF(&qFFY{$^!|78^gm3Vcwp1M zhZeP-D{0(p_iP*1{1WcAZN~Cv<-hG+u#g+`+P>O({qrb)$rjp2)y`jol<WqsQ?eWM zvJ0CQqRntDaxA-n0@)3#a==1>r6vV+T!|tYEh!btowFP8B;myBUwbqtyFu^LXwPma zvcMe)(ziv5-Mb&5ao)STClgT$!|gp_V3{QmR|i^>fQ@NaTj#zce?wbTB*EQMTnTY8 zk<KWm#T3Y?XgXw&`?kxxi!<50DG5XpgXV=vVd{=~Me&aFQq_E?c~5tl_w@S+ReH<P z-ASCN>X=x<q6({mF{Xx2bIZ)?j+s+?-VSGN(A=*D=}l$snm-{l#ycu7Ye&Zy#4wTw zc!{C~>}cmXH63&2WO>qhxRVoaomH`?eZjfAs^Hs~&UwP0OPL0|nCx{0aw+f&JUxF` zNk<0_&G_)KemLY`UEnOf*-L>F$f3~NZQC1zg5X$!;k?xa&T08wc+l-l4&+Wa48M80 zBA)L8$w-}LKdj>lJ%eD?$n;i52Wv**lrD?TT|q3}B*rWLb~)IB`JxM=zMk}KAd)UW zFFr1oDqD^q4ffK?TY|ZY_6uQv?hboOlD(&+r>iH8^b(V@!)z`ayV%U%(yr*KY<fs1 zB$+#!w`gzb-n^2Diw9xe``y?P>*b%1w4Pt}?UtF3IK?4D<!d=<v-VAIoIhvx*oDG? zKH0US2W^_!wD86TpM39I@4vhoTXt29AjXH@AHQ|>jo0q^Y{BA(7rwXhzWb4%9(;-7 zZ!mh4D*lEYq4kQ&@73O6qEYEUb!fy&kYV*GYG~Pgw1K9SkoKmOjLt*&TZVM*R0(PC zREdd>!XORZyCu13ay_b7bT1r<Bk2KeqCT$OKl+Z336jN;itgEt&;W10KwgFy=<PBf zfdcc*l!&8KR|>&2y%8C1HUi`8iC&7lBmBj^8T>$Q27tp9em?sJ_%uE9o8h1S7SUS8 zKz;_oNs(TDRn4>(n?dS2gOZ}@m_rpjM`n-@sm$@Vh|qBF5G6H(RNw;$f;5UM42v>_ z=GG}<V+ih?rRkU~q+LG&K0*3PnXBfXh-RXdyYOh=m46CVS1bZqnhwxvh6nIaJ!<1^ zd<*N>i=g=dh-d|%d<CMNZSA+Vjp(SbMJPPXWMCC!v_W6;U)q+@Uh!(|cv;Ww@VzxJ zvv0qQjK2Oqq<P&s`CrTW_v<qtm;9jo1wj389^p&)%^<|FD2e8I%tkPtG+ST^%JZ0R z&GXoT^E|dNmoqHZ7OUiWl&i{Eo`;D&tJ`#S$@1{F=I?iInp!n;PQm8yw{5Dap1CAf zzGwDxQ;kH-TBGyHy{FB1W+FNMn!Nw@fpsHS&De7S7auBU7|}3!<|bL*UfF{*rOIE9 zcKYgjtOtU@ez86Yh5zQ${Tipp&m#z}Xm!N0Ly17Ae!y}EDl(|$R^6_dqWc{m?b2Cc z^yhFQu+o*L4#@WH*S5Htt}QN-9cl#D7O?Jt38|d?!rJci=<U`<h3dDi?X(7==U+;; z$FM_@VTVHK;yOG4jut>qVh(`%Hj7h`N$K=FTjDPb@b<X#v$vvC<~3vNO6WvwjbaBG zK8oB1;X@A{YHz9833e$ow_B9^PEU5BuoYvfQK(<pz9ubOlhVVX(3oY#DwX~J3{jZ_ z1`ve^GnjZ2%`(xWW+aF-9#<MXn6mHE<zcbWJ`bbB&h%NIplCrhlt9mXf6Mg@!99Nw z;q>ae@Pvp2lR>Yeu@%qJQvN{0pK>V_h|n)yw@|euNux4O--i#iOiVVbryZKu+^Okr z`nc*MIZ}n>!Fvkos&C)-7od}}cR_Tjc@WVYe>;gfdS6rwDXNSuT`2^vO(LTaJ)vX0 zb@)7A)ZWV*+PRn4?4hmD@VWm^D=9@d59-a1erAElixKQxJBt2QV;VKm=)^%!kR?GZ zqy9G;#WC+nqark-#qC$-`!Cs7o<wSO$Gvd=v*s=%l(fMeMxgfR^Jzw)V=TRD|IWkM zK_eU0-opmsWU_@tM~2yLc6RjWvKzEEcM9&fqt4cT)GefEn*(8`@V#$BaY^7-svUQe zQ*rFrJI?prLXz3Gw=nC+;S1>vR+jdAscgytxYf+B4pZ)~^2hE6z;4^Y@64ewj~=VV zI08ONJVvzWM-9eN%~yn|v>d%&fD+oqt`-K&HA*DiE7j>>ci!jp%ITKu=;`bk6Q$Tp z@Hgz(t^;O{PwI%A<86Ls4vw1J@8dEVGZI}LLGxw#+L*%gD~^7&t?hSMUpDOglIBO{ zm*n?T_!SMq)|Bk=kvRt^-8=XBvrEY8x;MI;zWUB<`Fz%bFHRiC#m|2}XL;kYm(D_* zoaWp%jQbP}*zeYE!UM7P-Us>D_AOu3tFS$H?&^{|uVE+aDc(euHfJ{s(}F9GuLw?? zQ$OBhGEsE^Z>;A(=6)3I;9W#}BlHr-?!}`;K4=yVMhFBB2F~Qh&cq~9a%R%1$FMle z{Wzm{^@FqLY+Pd7<*Mk$f81;Bl0i{T4M|fT%47AcBnjYtDmEZ3Xd1gWHmD5-aU=Xb z0fz=BBy@Ck`ip@if3Y^DGxzDzDbp6;J8|0LYOg0PuWydWD;%1#Xkpca+69v{b8|DZ z`uAt&S-6D%m`@cxh3)MIYMTcq9pru-e4yl*EVK#RVm5|`C~YlPY-KHBJqgX5J58SS zSVH&JL%2c7!v^QaclU%%?elE+5rcE1x_ct0=JB66-Ok>9FiCJHWDStz&iB`&&R5j` z-#+6ulG@*RCq9=A19$IM#!1z`d7PvVj9bASCn|QwwQ|4HEtf0N8~n{lS!NHB8pNst z^_z3J<6$4*5c%mxm2<>87$3s!d5ZN$(c%6plGs&ItjSVBl7-$9WuwKirfkBilGlxE zc(71t4Xe1>gu9*lKYot@p*V0W7!EqxO{#ngjZ%^WO8`ZNB%P$wY8WW`T{H?pcI6NL zURCmD{hk!xg?0pA#NFhk<w1B7iYHgk@C>CKrp83++wAnUH=tgTDpVC3qGec%9a!6K zBInEs!k+ZdOgK{CyEeL=3}Nre-`<B^BT?Y~X!0ndhmOYgYzkVm9)ui5g<Wy;lZnmO zK`r7|PdwDHW`Lh+w)65gxF5R*?hL+4HgZ>}oZhC|mVTjvIjC9g%;vhv30qc{jVA{- z9;m8Zdw2@<que(y3z_H|wZ(2)C21r;2l|&cF{@0kn27Y+c!+)gGW{kW_H7OHKc|vU zz_iDL^k6*};tK-C?fn()jTIyh-&-mlmK)RX5qRE)7UHX{#?}A4zrGb;m6zUylMl@Q zC;m=u9EtD3b?Ndj#;bA!5ca!Y|K11k-Hj8E@clc!_o0#uC6|O_NP`S$#EUu%JK*<o zZLCy%q9_Eu0ic{3PtM=?hi7&9pv<e&YPANffqf+a?WuN3&TQo?0i5hR8^}8i?s~Vp z*@i!FT2?O?S}o=0Im_9z(@4JWJkA@EF#ktNuL0n@eki<y647{Xc>+dS7i?W97I*^| z1wK!Mv6}Uwm8s|@?W~H3CeF2^5Ifrt1aTBZ0ag*zq9Z;wCOV3ive2uLSl=JL&L9yd z>XZgeFy`!+LAf~ELHg6qzpQNdWkSkjL)`8)Ukt<hBjv$XEv}1^x8sx*P4(OVbY*|k zPF2|UsK+Pc!uQJ74Jw&0q@6y~G;m6z+?>6+FV_AL(pWOO32SkrJMH0OMb?&)FNJN& zeTp<AV5Aqf<f&;x1Q4=XxnNNe2|d!)YE<-#e**ueBB+W~MMi`JeOVcvf!>PkG&&&! zc4E#MW~DtSQLF_n1N0|uUG^5?&k*lxBER@Z>+$`|c<~hZlFY2G_H8Fg8HMsla>4fj z>ETPo2Z!|XeN1Ujefh!s;P$@WP`_nm{-M!swDW^+yi9+<PmKaUb&nXQ_^F0OG=y2| z;iM79Re2{`u$r@C4bNjNaktz6g)|!fHy$Z>L8&mi3`&x8$`P_wIYK5lwMVyPR|1XM zqM09~)kp%i6T3e@!Pao7%Nj<oH9S4+P!C{alLffi3hdLdkSO-1s`Hy=%Hv6FmB3oJ zTvXM*Hnp-g8W^!N&f8vVb?eh*-f)6%hX_kTa}*D$hZu+Yqk(8RTI#LsWhbFxnu8c5 zBPbP}0Tc|TyiY?g8pXiG21Dp56dG!wIW|I6rFtz<sbFrMPRB~s&?wGG{73P_h72kg z=pB&Tr*}?vMmj`j$@FMG+(vW5?6$4`xW9>tMBuh9JJ-=H-}UY-d-iRv;=-LTRU-Dm zS^cvL#zbD0<Nlen=K*?A*PwB?xu^^OJ-o-BJt^}OdJOMhRv8`sZR9s!xu4)hv|RCD z%9NPJu0&dRFW-k=+yyTet>}EA*X&dK!a^Hjrr%4i_Bz>uuhLtbvW6%(CsCV2>DyPN z{RsonK5tlti>PsCBGIU=65)^qB#fi?+fxSU5rWlfJW8t~^r|DhM0j3Ps>2$M5-Y(r z(;Tu8O8l40q_HcJLfFBi7E_k^wJ~L0hrs9d@7I@}==EUHGGz)-Q96x^A1Dko8VvNC zZm{S7v>(EEEqGYV^?&@Iwn4P~g#N#1ulP<K|4D}hEEG;EfQ|Tn1ntt(004N}V_;-p zU|^J-RlcgpIiBC<D}y`-0|=bGDv<-D|4IH6U~gnEW?*9A0Ae5j09ecm;Q)BrV_;-p z;7Izr8Avkxll&*c-pG)`Aj*IY-U9%H{su(=004N}ZIdxbn?V?c-~aCZi-VL>giwN$ zLxv1aMI?lP1R6R?kyIo@$dm>oh=`OBf`b$h=_XPnLvaWhLdhVsghJ^MB!p6mWN9hE zp$H<yu}H4(_ouc&93I}g@4oN;yYKx^T_809z)S&3cz~D=W8lY-GzFyXGU|R73tk%o zmBv$*b~#f-pKDd`!X2tA=9EQD_1qiAUYLS6OPwU5_sJsJCQXtf`5@oA!%;q}qPmEh z?Vx1V+^#u6#x$|-FHytD=ngV|k@Hn#)GV19el#15cagCzEcrF^3H#<H^F;SpXAsrb zc<&c*Wb$a+FZf}i?!Z{IP15~RPe>2nsYNq`M>^_KrlgW)8+lVhT)z%9udjICEf+D$ zZAn~B2*aWNiFuCa?Qg^-ZYq-RPJ@~l>sK+M4zR-cnr<QQx3QtWx?|mPalPlxR2LCb zP}8dGj(Pv}QSaRq#{*Mv=hXVBH)>j+asQHcV(ZvdO*HfeEX$hoUSj$l&iK8+6W%FD zHhGsR({QJL0v-0d;T^e*>Um1NMV<9w{}N@gV5jj+7u|Kx_dBpVZb!TjAI1rM7=vD= zZ+y6o+=aR+UW^lXLC@GX1bx2)OT-KDVVsc<|DoqA|9rTO^s$13crlK6A)blK9=4Bt zd(M10SIK*2YAQ-y)bD`MI&h<^40zv2VgxR!73y=Y$$R*V?qe?0#GIE!nN))J@)>1P z(JSsyTXbv$F{xE4ER(P|IeaL4)59#!o%Dx%Bait$_xKNzP<RB-k3X?S{oQ!lV_;y= zfx;w)E`~RZ0Ze>M3z+sWJz{2Kwqj0WZed=)e1Q25iyVs!OB>4rRt44~)+?;v*kaiB zv3+9KV0U28VQ*o-$I-`ej8lp;iE{zx1<oH_Zd?UiU0l1kUT|}8dvMoqAL9PS6TmZ# z=LIhpuM=+`?>62id|Z4+d|`Y=d{g*#@m=Bj#-GFgLO@4gnZQ562*Gbcc0w6K>x5nj zGYC%*ekP(NvP@J-v_bTon2uPJ*gCO);yU65;xoj*NN`CcNvr_EYm!EiZIX|qw4{8b zc1XRD&XB$#!yuz1V<)pq=87zrtdne=>;>6Ra$#~Ea*O0H$^DQwkdKm|A%96BL}8V} zEk!Ox8^sdEMT(b{WRyyj7Aaj&W>D5q4pFXAUZ#9TMMfn^r9ow#$~{#PRVURn)k~`X z)U?zh)SA>*sXbFqQ$L}hr7=O{k7kVK0j(abN7{1QQQ9-KFKK_%k<xL{Nzyr?tDqa8 z+n~Ei_l2IAUX<PeeLnpd{UZi^26hIE3@#WvGn{9nVB}_0WVFiY2@d$ln8BFOSj*VW zIL)}rc!lvT6Co2flMItCAY5d!$K-~|4O1o438oKBznNK>%`x|}V6hMY02rv4asU7U z0002*08Ib|06G8#00IDd0EYl>0003r0Qmp}00DT~ol`qb!$1&yPQp(FkWwHj<dT9I z=Yxb&5kiEBA}Bzip>doL0{O{tghI^$I0Ow>-~`Z9aRyF+D0n+w3rs*r$lBevv-4)( z%&Y+{;Q?_Ni8%lsM}Q5axC?L$N!(~0M+LVUCt%`5<0-7*P2*{-8YzuuaA(*W&tlDZ z)_5LU#=FKzoW}ARFA#_E7jYbW)%X$1@okNtV8?6NMH?*+pW_-$G^nNlhkJ*}MIQr< znS=5=r`5zgM;10R9BGX*Sf_Q5-hKLY7{^43*dtrbj>PYy2MdR^HHl0d(cZ%l`*K@{ z9xjU9yK>&(?9nUDG08C_EE78z5p_hrQfB|jsY(2y)}>gMFhgF*N=H~fMQzKh>g7wW zN_m&7hfCV}IGd=ABl(%)HRf6utH-$|(R|SsbfYb|xnfZ|g8c>a^~AR!y2APnnZ;xc zf9{3qr%!7E8~m>1vv?k5yP9hW>eBPSJfFD^B&(*>y+z-k2bRR_vN~1CrYV^O`H#Nj z;nPo5s>nDF{eoSTqh8|o-e!4&{j2WJSe9sR@w5|(Ii#h^cThqZ2kd-VUcQQX!qYlC ztnTskD+;Vidqvcn{5It*%e!-23&_(e{Eu=U3W%(T004N}ZO~P0({T{M@$YS2+qt{r zPXGV5>xQ?i#oe93R)MjNjsn98u7Qy72Ekr{;2QJ+2yVei;2DR9!7Ft1#~YViKDl3V zm-`)2@VhyjUcCG-zJo+bG|?D{!H5YnvBVKi0*NG%ObV%_kxmAgWRXn{x#W>g0fiJ% zObMm5qBU)3OFP=rfsS;dGhOIPH@ag%L&u5@J7qX1r-B~zq!+#ELtpyg#6^E9apPeC z0~y3%hA@<23}*x*8O3PEFqUzQX95$M#AK#0m1#_81~aJ=0|!~lI<B&t53FZ9TiC;4 z4oM7~dCMAhiBU{!6EhpR!F!2iFGu)EGru^%G467k<IG|<JE-P9HQeDIk9ojD9`P}J zy=Oe(DJSspgPpwOIWO?@nXhbO4guyek6P;3M?LdtAV?!27O;>-d}1+6XksbLS;j^7 zvyv68Vl`j*#wA{Hl2csfHSc&MaS|^Hk|;@%EGd#IX_77(k||k|&1ueXo(tUMEa$kz z298P&*SO9V$(20GXR8!Qp%h86lt`)3SKHL!*G!?hfW=~|jOer|RqfK1R;688(V`x1 zRBB3HX;s>kc4e8;p)6Pao9B$EskxdK=MDHm!J6u-Mt|f<_e8WS9X5kI6s&J4+-e_> zE3!{mU1?R?%zwYF>-rx~rl?c^002w40LW5Uu>k>&S-A)R2moUsumK}PumdA-uop!j zAWOIa4pB?622)yCurwR6C|O`;Ac|F3umUAvumMG5BVw=uBSf+b0R}3v3<d@&vJ?ge zDp|4wC<#SUM6wJB2P&}!0YtGR0f<pput11du?7P~u_ghCQCPSH0Ek$z1_4A_Sy@@Q V0sn=t1dXu;07L)*QLkt0007vJ)35*l literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.eot b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..14868406aa7d728a88d63963f119635813b5d30e GIT binary patch literal 19514 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.svg b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..bac8c03979f56051d3e2b72cb2008865a07b09ca GIT binary patch literal 117269 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.woff b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Light-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..e786074813a27d0a7a249047832988d5bf0fe756 GIT binary patch literal 22248 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 R1dXu;07L)*QLkr2008v)*B$@> literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.eot b/Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..8f445929ffb03b50e98c2a2f7d831a0cb1b276a2 GIT binary patch literal 20535 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 Z%0#`NexefPFV?Xj51H#Y#AC7WXn+Jg($4?@ literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.svg b/Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..047fc73b406572fa39ec17e00eb26d88fd9b7d1c GIT binary patch literal 122967 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 M2T#9x^Vtvof3xEc4*&oF literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.woff b/Ivette/src/dome/doc/template/static/fonts/OpenSans-LightItalic-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..43e8b9e6cc061ff17fd2903075cbde12715512b3 GIT binary patch literal 23400 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 WxB>r#ump{<1pq_<0a34Kp8x=7I1^|9 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.eot b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..6bbc3cf58cb011a6b4bf3cb1612ce212608f7274 GIT binary patch literal 19836 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 MJVR|eexoq?Fm#!HRsaA1 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.svg b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..b2ce45def77b17dfcecbbfeb545146f88d927792 GIT binary patch literal 119398 zcmeI5Yl9ofb)LWLSHN`c$t=+qpaDmcV@tB)%S3Xli)ANqxa4qWqtWhS3C&8I%Wu!~ zo~i;0=su^LyCg+f`+*$H^o#21s&jeIsZ-V8{?p(5>S6VG_xY=jKmFu8Pnr+bPgbvv z&pvta?BUZ-?!NQnlTV-g>36^N?LYedkG}VlU;Ow7t5=U7t$zH|KmVJ*{NC!x&C{np z@4ol+>Gyx~{ng+7?1!u7gXZbeAN-dmt0(uz<7a>J^ywF0eDT2--3On3{?XGPe*WyU z`;VW$dJ6EVfPCpGjWx{&FODysthk4orZb<s`p(4n+x2=a{1bq`x;s95@$C5QyWf6# z`uMGHzqot(ii<Bl{p7g%_{DdgeEQklC;#;7*(a|)zx(Ld56?b-vbz8D^N+v0dG_M* z<~KZPGc<Nvec|Tiv*&lKUw`uP@zu>|cc0(f{pveU+I7EsvU>LF`Q0Z+;M<PhUfkth zZ~BITdaBNR{OZ-mpL}%l(Zg>)yT81}rfU->U8DKupT1yB|J5J==H-X$=09HdsBOU0 z^V@d6T7P-F9oDP;cDTQ3hyCM?eQLJb$Mj*peH=Cq&3?Put{=C}VZG|t{i@q^`gzz5 ztM!TpSlx7+hnv1z-85Zypp8}6@OcZe;nyA%SN5x$ZTrFIc++oIHw^R#o5!1>xwqRk z?f%Q#X5DR9>wCVqeQehI?Y%zS=+l?CyUlh*6CFL+46Amx+I2KV*W2v}n?t|m7F%x6 z4o9BqX4f5W(ofwlUHD+LI^6WF`l7E5x{}-ZG8n)1_jLR=n=*cUiXN~VJ>Y)5uLY#( zHoNykLf*2hA|T6!bwI`)VQn^>=4(sqR}t3!o4G7@=PS>puQ(TmJ=txU<_VL0eX+L5 zFGh2;?)ymtw0g2yZ0Xng>t+MD@NB&l{6|;LW77}GG<5A27tmp>*O-2Z`+Bp#Z`T86 zeADvV7E9e=&zshM9<U+n)oza!##tP@Mjx8BJjxAz;-+g?H+!xgZ+6)4Zi7+3p&hR7 z<V|#;>uDCN?;5jqWUF^A&R4FkYxb+A-?n%un%uOz-0{9y>6d1Qi`njW1%vm>n4WK( zF_Y8u$5&(2bZwXJy5BWC^8VpwyXBes^?keRaA@uR{-#?G4>vm=yzgX0y5WIe>~pv7 zxWaJcE8B-1URS7g+dk^c?QVG3?pA6Lhd1!I;lAZIe5voS`W<&n4Q%f_rpH>=-+7pH z%k6!;?bQ>x{T;5iA2zEE6R4ZhS!<fl(?k6)($kr{?)$x_P&3VR((AVElV{cZLc4JC zZP)UM?f$WCVFyiP)7mz}sxc?r4D@>ku-R-6J4i&wmAwhb7Lssm_P}VEsekPI^#Sg% zS#9-~oh~$+2BCpitlG9Up_4G`>us|+wp&`}cSdg4-m4Qg&2D{YG!7ex49yG-3!=s| zKvtT5zuHIw*WGGZKQamZp@DJSY~TzXXzR?eY4`{;Inq~s2dTW>F>s7OUEqOkdWK=u zG_aH74Nu4~J3Zq~x7#1|>>cfC2zLFKNjle?K_fZPh}v%3BjbVi50Bk$z%kLOMuSX8 zGLJ&*7)?}VdYb;_wOnp@+ca}6G>9QlSLxe&rH5!Yj5NA>v)dfR+|XL_H^!Um-A*^> z*KT)!TuChxwnr`P%RI%f<~zC77G}kx@YKkC5(vqK`YXQ1kcqL~FakD8`{T`^PhGDW zY};Wq2+gm@wnYXQNP5M%=%Q$5vp){pf&O4`7^{^8!=9!oPb0}`8KIqS-?Y6k#?_G< zw;T0=&JJ9*-^C?)A}~f!)A#ISdOBGh>>BEv@1riBp3lB*a$h}P7IKq5dYiyqFN5bk zpT5(!Ci%n-^l3=;vNQRTUC9P&*J$doXXsUr>EKuUjbEl^fmop3UK@Snc9R66Z?LTl zhlUWgY|3m#x3SUQFa-y6XN8q$tWQnHgB|sE-PlHRU_>_Rd($G43}>eqm0}|@L>lU_ zi9o+Q-fV#I2eJMQH{`>i#m*|cU|u$|x{Q3^_Ocf|E9MT#=MGG^8rSc8yA5;CACoAf zPbNmFxURKp6F^x2NlAxf$XGR~-c|$K^5NJ@c?n`#dbwHcO+?i>I!mNt)3<JU8hk?| z5tIJycYL=$wnMktVIH<NZ!#qol<W~uOr8x2HiAxD?`1fMI9lC7xQAYsx_xs%&1u4X zBQg$3@`+`j2|^$=PTz0wgJ$_;k{&Sk{I+i}-!0aj=Vf9*HuRHw3Mxm3E9RDFj<(oM zj23_FI_{39ZdW{3qbF?lj-~(CS0<$2WY4z1pHBM9e{<E~cAZTU{%T|KWs7CEN$mGq zlwV!#*BS>Vh&kbzY<y)#P~MhFGUIxK2b1*bu?M-;?f%#@<#=!T`Ymn)<zSG6LD9SY zAe)1H?xr>7-+DdW@a@!995OdZ64&q7np}04Io+gND&}oq73xTz6dETl*`uqi9>)4k z*ZHnJ5f5aKs=i{HnHuhfjpAvKQm}rH3Qc$T-(7VWfhTt$^0P&82uZdnM5lKT9TJRQ zJwW1+9avF^X}jt8Ly!Ex?GPzR%^pQ;@JOAQ6NAV#`^2BPBsXH%j;`s;dfJx8Wt?ao zNoAawyL~_1<$quLhp$DJ`=-S^cg&Z4>f0^D*zF(fL*J|)bxl8eQ8q3x|IY0FhpWNZ ztaHwzGe5q2kpC7Nu@S)L+%VQjYf%d0F*0l1zug?L^$kgmjTwr~aFmWReLUE%oqn*J ztJ`lkIieO78#<Uyd*AOHo|X?xYBSx;2UpE(`fRVy6niTsL3fPt9E}ilh)AN_dtJc+ zBRsN4%!+uC)I{{DlOtUtwtLO1__hqN`OCt%lcC`M>Ha;v>ff-*qpa9C(QUfSU6QBT zZXfh(@>E+VDUoFs^Mt!0o20%C;y#Ur|7Nq@LOHgY0VEe*)GBAB{v&)MjZ7at3k9_Y z?XW9+li!D9hqhuU4=rp4P9p?u>^sPTsV)5X%i9(MQEtokBo+Nu1K28mW#$=!uUlei zXaGf(YJxzq%{ArE)|G-ml(0X>s_3vaq&7|H`mH;@Id~alw`EZvv1?;Ua$%U2-i$hO zi^9oZ$Yts2cq)Q2g)>e60DHv1@9&{p$QzxUp36LQjJu^Z_S@#M={vp+4P%^T1@JKV zy%zq|9}(mRM-I)yvM@=o2Xu&8H_uB4hL!v-yw!v%F<@A=JZT#EwW1Vtu{+>>VVgUV zEB)km4Y24A0xE}StrI*Y;gwmv5&dh;aPBcwkW7r2=xf&yV(sn`MQN8~c(NBm`gtmR zprlNclvX7a_*5D5q%sY5W@pdOpGY^Fachr^i)2sVY}ZLNxVgw1w1E%@f#v)1$R?j8 zT_r8X0gzihOa3qfyMs6fv&SIl-h*0b73b10LUNGwi=ywDMMVg$f=RrZJ|Gl*uX$p2 zxAakC-SYongN9k7Yc^&^Lk2afab^+}Ytseh$GXR)a642BTaDSr{%eAp_JD1mJ>q(O zRpA_jNuMSB#4!p5IwgCJ-5C35w_Kl=G146JNAgU3i{8WkiHP*6+3X+f!_Y|ZHV<1m zvfm-L13BRRuDdrZ!5)Fe1}jQj)bBL>JU!M=(sIu{LD|%Q{%J}#$XGAhxZSMpu|3n> z%0_hqa7Tu@RbmhOU{inwN&b@gM7C@+5d_-Ibhg{bBJE9Z#ABH?rNyyYu+jaasE0_0 z44;U}z`!xTnq4Nz<Vtg<n~}A)=n|{Jb9G{I9R`RGOp{SJG>`8|akhl(4^YnSuD>5z zMzPuO{F@zmuaKqh_6NnNs1U-;kLf4R<V)(c#nCCxfC_5@S6d6)h!FV9JgciV+cE-3 ziA)LZlV>zSi*?}pC`4kIilC85o)iZzaaABs^i3N~7|fz$n)rE;o#0U$nNpc}G~I@s z*`zm&vu>6mN3zgr4<RwEydF1XA~e=e6R2IfA6!c|n1s%no3ssqV+yQv6R~VUM?I9< zTX7e~l{Zj%ZYCP0r3J>@;?u_bBup`TAD98!P2=<mkI9`$f}jih+!L>-zBheyOk+q| zVS3zi60OCEtRLXOib+Tc4SSL~%;O%4zzxU)Z6IoVQpQM`f=N!T1tYX-lT5O#sruf@ zAj`SwXPa^h4FhrmW1zP@Q%le%r-BUfXS&j|tOMQCFdG}PP+iZaWD>a|iJpzIW{)Qa zs42JQ9h(7JFvbc_WkANKg;Pk773T09yH%1N=0)CtI8G)?c9Ln32e*6x{oq<B&4XrY zCduNUkSWuIk(VP-w+6yDu^T-Uvn)F)|1_+R<S3XCT1CF(D$M`z$cUcFrJ@036pzd> zAfU{dbw^_(4@Ouj=D>r3M8a)`!EJG1*h6t)%|5QjM16xNw8*PtG_gnJu@u-IjW;$H z+`zx+j(Gx0Z7~tD!$M5YZKjRpm3JgxxaW>cDhWk;&Zm=qQ9`SQA)}O}3q@;f*2wWF zB9b|?yDFf?nrZxc#o&k)aa9UkH3}LEt*9|nGEqH1Zjly6I;m45AA#U>gyxL4{J)mc zXn%d|l(uEiGzK;odPbgC?ctmBnF#4<VT3qzj{TJs;ntQ_BKx6HWsrGD@-)&<uJx8u zYprK3w9N8-2cs5A)4Bl`r@Jx2N8rpH--JBy3|O>1#E4$&dM^rMNkLr6q(1%06|4On zvhG_EeY~Ka1=A}3D!U_w%U_HiB{TG9`22N(==9`oJZidCfLlKpy8jvvCISz6WIkC- zfK}SWucxPz)K~YMCo|@;W}paLAD{^2^4j)szk9HcTKh(79}qmz$)R~jAKIN<t0O7j zDST$XLKg{7hx>gemdyujFN^DnJxGyHT$&U;_4V%5S7j+W`au+}h}=FXc%+-^Go+DD z^8ofR#KMFJUQhq@N~U*1S>h!%$2!jA#`FbWfxE_Xnw3C}WSI`Oj02fSI@}E1F)6yy z6bqIu9wR>|!$HD>>5y@O9;CdVSc?)(TvS#;{6elRO*tJPnMIy}AMgRAu(I0dEM`xp z%p5Ha8bd_O7$|E>cjK3}T9q|SedP~~jB;hk%E_=GAu@g-hzUBaS&?^K-O4a>2h%Mc z`W>xP{imy$z;Nd<kFn9xLGp4?7KnzPUiL~!Ad-d}Ts|=%dP1{|jI^w!>_g_i(hRvV zGk1)F40g)IvsA+vq{O?qP3BIMq6|3{lu>0YRL&tg1FPp6%q$uB10I-<Hj^eD@)>I6 z0W&R8MC@((MFc{fp$8-+lZh7DQv`8@VN>p5_pyirLM)ylE+QSaXocA_9wkaFf@glA zBT~dKsJE@wYFNIa-#liw$GgyNi~s^^T0!QIke&N)dm<D)E~_%Dok~emoq}{TLR{Bh z`EY<e+C4VL_{}5B{i#EQ1ZhyjFG<%Ds~>eE<0j;RG*k=|w-H4k*&s19j?{`5K)a4< zA*&N*(GnxP9ZIJTi^~(I+XpzCmC`VjJp2Rxl{gdiA>Pz1YuJ>)By7?bQ*fw+qlFE$ z<e0ucyOy<fe`5SJyjJ3vrIRf*V6#)sPt?JFMHU}6n#g`js*OCrMvTyYlQgl|1z+4Y z*dAq6NeeTIB*Pg{<fLuryYlji!;~WB4+2W0VYei}rY-fKUw5}_3sFX?xj9L*27YTo z)!W(*Zl6I>B0xiGpHn&*a%;k(>EVLHVCH{)Ao)!a2{WgkxHbEl`dLD}wW2wN68xzl z>#|YaQCX8)oC3^~rBho!)KqAam8)l+hN<K`v}Rsec@5=-kt2q5Lsy7(H(E{{$T6v* z?H*giYPuF^A>cOqTbi=0$<fvV>=7(Lk)WC!A(b>~;mfwCNiT8uz3Y)|_c_0_Q!*3X zW`b<Jh0Jey*33t>)FjnNN~$GR;Ia=`BSiRUg3Qp^5*o3J#9m9L8r@`Hm}SP7G2}ah z9oSyeuHGVKD#>Jy#1qjih6_%|8VbLn$fOn|_$`a70>Iz3LZdYy(^xzpKbZ?OfgFe! zVkfrmq=3JFJqG>0q<uPsbm)`WVC4mqppl0L>j_CQ>hAmz(IGjzCQD<YM=StUr9T^q zT(cusRjmSr0`l`r`9RRk6PfeTU@4j=Toh|XdL;tA0(ID@3MCF5mR7pM2x|?B<z7O` z9uqRH9Y45!9@1ci)hNeA_M^#N)d!}C)uC<Ar=BW1f=vAhlzrNeNw;hG#Od4p#r5r2 zpH8=v_$nQV$+v;Iy4$APl)I?|x-Yqf>6`rU`X;2p(@l2b{3N(~LSiB=MF@)1Y&lly zpri|mplOonvDMZMuEdH3<R>Ly%z=p*<!dqnofVj{Xv1fT8N6p@TAO0n<PR`|O0Y3h zaup;4@Dy4dk)t5B#f%YA$iHsL5z3pQ7`ASTZDk^}s^Eh1dN-y~Bp$hd)O1uZXbv!J zS_7CKl>dA^D4V7*gpRe)JoHqnkT8(jwNIzn&<6&*z1KDUv_F^yo1~n7d3Cpq>Q%*+ zTWoHg;ZqYf>(jmdtLt`3r4Z~zBZx20wRNxoJwE!UNLsW@=>!}cG*A>n_6XLK){>3y zV)%0x&_U^*l6x}Rt<nP$1kKo*&(nST>#M#I(PvrKCygkE6-J6r7?hTlCgKo~+|3}m zSR~y#F|;Hn@oM};jd5%nag%N5-1~2?@4en;Gc+1t0_>uc7<bfa`e|;jTio@h)g?$8 z8Ba+f;;4M6<#@z2B*rSIB`o2IHkts2l@R*@Qp3}dbHCs585Pn;*oiE<RT%L2`?TzU zu~h7@MJrtYM(bwWh|Uu6Om~(t?TfNG7-Y!;cMAFWsumds=AJSR!X~<`iRC}jcM6bM zRmYH=x(t7NAW^0}Bi&>`AW8hj_r-=V--$*(?mCjkWR>kHraSkeQRhlQ1mWp<9mwiz z(lYNxY#T>{h$1ssr7Q1dKL6z3%=~mR@Caz~E*dj)H;2wRV=p!;w=NEV2NKVKVCE$# z*$m6aU}dBitYL8n9^Fh^YdI7Cgwkjgi>&xYrl=LGgol9aZFwp$m|=0~5njj~GWoPq zQ(6%)H-$07TTPGFkFQ6o?TSMsB!eI4)ex)5FzqEk!0s|&mT<y?b4O-!5cL`CQ#LRv z%-CQB#FbDcTxMcPL)$QiP(D}!M1y%I_*8_4#pXdRbIZdbEf@i$9!DqRK=a;`^WR=S z#Aa&BTP=qu-whikQ>tnQ_!~>x>K&;xbLB)nc$uz~<&Zf19ts0RvJ=v<L>T_-^*FK` zb*2Yo-f=>hv$O5&(Uz7qU8d0%Ik4A~S>*~CU*q8<jTuHQKy~OiFon9RP?VMJFk;ps z>XC(G)88Y42SqIiJt3d1ohcD2@?Ydb>0Frvxe0k^BhD>r?^^Gjbcug={cNaKdNu-P za@m%TL(XJ2mHY3=If_T~>st1RV3E(NWZGh8i9+>U<i53yLK$QQr3#jDC+fJ$f8@sC zjaFPm$K}sbR!b~``G5i2$_0i|27py6Mui8a3j_iDMOhgFVm)fgG+R{_aU;<%OD1UN znkZEo#zYYIn!8i~l|n|^?T+x2LF_uM;t;iAk+fQ9?$w&r$J3h3QQnufsI*BTsk&&K zUFD};D$&98@npim?x)B5C!_H$hGnagge*jGAK3U-#S<6>Hicx0t3T1@#>vtB^t$mA z#Uxr3FW+K~_5>B06VW-EmjE)HJr<e~(kHETfK?jVC?3&@d}5*{`;Ckd!>ENwHM48j zg@PFGab}nZ=9vE#|6sfH3ugFnj}t`zrbpyw*PSNmT_jMGDZk9^Fg$X7*-dZdl5qn0 z>iR+RZjYuF19lb>QSoFAk%ycsiDjknoml+m*FD&sQU|@FRVGFEldIWdypc;Q$tA0c zz)RK0jOfpbu3+cNP%$oWD+`ZU;K~i4Oy>@3<(2eFcaWJC$<w!3+P4ZEMi&)h6_BbW zv_VV5NHLMWBydPy!4AuEE3U_6Yu%5KvFo=F3MBVy<YwoL_}^bYFPV`%;##&fp2Bz| z7bq(qq}@bUdJKBON;I0IszsRNcCUi+-GkCf__;kF@cx7PtC}crOQQejiT}l@8-+&0 zL{aw!vnXPsC(-RhJ$HLzJPKT-C+#CvO@Al5PIbQO+9yriKaB3PJqZ}!)#I)e__78$ zpz^HC!6sExfj7S28>`atq^{v7@#Vwb66KDD|Kru|wnH|kTdiTRmV{=Dk`6l}K0YAQ zC_C~Z9p^dHr`{Q~|8~{-sSJt7H{qh}s8SOmJV<Dkx~(Js|NW}XQ;&@dQcA8aS>LRi z>Tl|}9w9x9*WLed)if!@T=Zm#l;(i~PgJ$Nr=(xHM&46(zR(ZCUnH912qIq03!m)o z(^LFUSGU<Wd7+r*WCr-|zGb5wvZS9fq0<fh&#Q*Wb!64xS)r$zDjtC{RVAa52Mae? zOD8nY3c@2K4hM0N8Ne$kXJWZ}BXY8@O3is0f@h<fm#oK5nQV;&_pngM_B?1kUbapS zhXje7XLe4i8^E`rlrlwDfV{&}DX9#dROUu$gbgMLmiHjh**;Q>1k2<xAPaH;Y5Chy zdse?AUuh`;<;lq<BUvOW+u?u}l89N*fCq*v=q_aXpa6IPwF92)uz6710y*@eOW5OE zZN@;U$QzjNuvF3xejp#D@~%g1DNzdShV+_p6gLP7E=FytswfiyAo9m_43nW8q(+2< zsiFYri4(AWcs<|@RWgK1UL&hYsv8@(MIh!+F^^Gu8qEbxwiL^6HvY(}-CId6`fHhP zx~=Y}34(<1xl!$uMu0h0SCd#t$;wW~js*pt#wrnbXcnId|CAQe`VVeGKgqGnvyl%L z^|Yy0c}FU~maph+^+;+3bEoI3*0G&O47WtXmb9(V2{aXD^o*OrC>dq`pi+L-7_ja% ztu4>5#*eP#;ZqYz<EQ#V!idBv5KC0W*dAs0HeqsVDIeXp#C#@2*qVbar%^J-7-+ql z_ImL+JRYNE%lPJRNvTNKX;q7MYSQclLuY1#=t{$=qPtXzhww5CVv$B*lSnHBO3|}~ ztl<mF>ayKPAEqCj{neMT{z-IXau5_Oj@r_FRE44`(<iY9E3rtD0#IE?S}2;{X<eU{ z+6ETO1TzR}MTo5-`Ytp`ZiqrFoE~-KY!Irpy&_GdWo|dfKkXI1tq2$U$^hB2SSw=o z*jc7fivl*<m;w!8s&!M^kbYAfp<zqKqE_nzGq!Nt#KgvwaWc`;qLzYIiTm_m-CYkB zN#HCfDsMDF$$`3+yPzbDiq)L<jYavG+blL3owOHYvt=nM#mc(5RMZ9#m7=E@c}nS# zW9oys3YSTt81?^0qLw58P$wQiOp9l+BoHBjc!m|0+8PD^)5Ob`DVPN<Z4q(Pnq&p- z&^V=<t{suNnOKSaJtT%<(t4H%p;gDqKBtPFFWK*S-cNbjGWqgqpePK?<3tnh#m4o? zZhv&u?S^z!>Ng^xK*0hSZJxwGF<h8cjWI5i!Ba?w{4hr<u90Nf(x$1Q78MB&xwt1* zvqBq2c%?W_%jMcLW*=k{_#)O%NpsB`lE5c3vn1V^W`%>P^bnainnmVvGO{XzkjP8r zHQ87V?ua~9+A5Q=)B3c9ddRybm)XP|D;`x~PF~M8GAn~(t7=M{ThwoR`3aSiF*P!v zdTymuB%In{B&{W(C*PT>xzwVH*ixTVSSA5J;Fu&;e63yIlS^VfhWo<IEiQv_$nc{K zMBaQL)>FkUch;&Pg^wB;Tkb6m)0TC(r&L|?N#Y)X$C^-~z{47YP)ZLypoC3?V}l03 z2+OLHY@AAR6gn^r80d{QIGKOp|5P_@o`)K4^uSE45eYpZP3C5Ij`6s^7Oqo58!AWE zo-DSeLL`wTaa%Q1WyMy(J;KK=$Y$~EDzYH=s!t@Jm6fx&3|4q@x-1?^jF^@i`5nA6 zR1c}slBX>e;)fU|tPZWHs*AxTXlHQEp-5u#=yD6jQ>!@|O0WL^<Euy86xu3_Z(-;7 za0msnbVjxX(}Et!V!r0#5U;o0{(pJBWOmU>a)AWK44b%ct2k<Nfchdz^iw*8FPHMA zA`Pwik=bSZpqh*jYFeBaSuKq|5fWdLO!Eope&^5o%d6+bhGkmA4pG|<#e*Yi1QD<> zQV%>gtGI0aVViR=KTjf+Xa*_Ts+cvU^oTT>Ubw8)5K91iExAMEiU8t&c2<~dDOMvs z>w9Ox_u;CKlah0iYf1RDXa3byJFx!ztT--|=W%Gviz!)wwY6+MHV{?U!Z8|Vv>l?r zbdeh)Ok?ikNw<ySI2K`?24pi*1DR>a1hQa*bfltDGzck?nkEf;lox>kZAgPi))<-t zbXG>vDxMfuLJ#R7i*2^jMT~>^5!?t#EJpWHD-{W`K>^o8zDoB_B?e~hSI6YONtVqk z?<dzo_d0ed(FR43O1{YsvPnLESg0??l@Jomk)cu1s`7IOMMXS@VxwY#)ZBtc_;mCL zU0Ex{gA+$teU=K6<x!C9RM^%b8JYo`KjwhmlZYi3B*~DFz~0bW{5JZmZ_7BRa7jVE zRRCD(6w8_G545I}Vl3hUxfir0-@Sn`Ayx3s6u&?W^g$LxK8@Wud@QU~&Mwt>k^7S@ zr7f?ye!B$3R{Fb!T99Ycg2%LOd^Q@LIy#hH6XVs>2LT@St4s@nB8ssi{mQacQVe1n z?d(II(`X{4a0$_OgcY)jG&8{^lU=p~^x8IHy2510Txt^+M#Tv2L=alXh|Gk(AhRv0 z6M1JLi84XkjIV^G@%hV8amBK#E$Q19A)NiuifEKtWpa^0q*oJ=Ymia_h$d!wP!H~) zo+1~5eOl(G7!)MFTdyCjhstZJR+@?)%_~_~ElSRXDk<<$4oEta7XC~eRFO^ZE%;z| zXq$#L_~LjJiZ)x5UgpArvULv1SlO`}c`~hx`>?*>vo}=18gprz9963z!^hrN8W2U) zj&*?O5Zx6k%Mqa(*bYu8@cGq1QH@nX0i+2QdN6V$C&cu_tWAn2+>pNM9`e7k(8PI~ zb*o%QVA0K-h}n{Hlnh#LvvnOf|4L)hNgC-k@=b_}o5Q$5`8JL_dUe%Vf}_;g9U6u& zm!K-;z~jq7V1lL3h>q5FY^8<(Sv%G7g}p+5f_-jkWDSCdzd^+K-T}Rka4@L0+KTMk zS}yIQJ2`P>R)J=XWT+IALEzpN(x(+AnGGqWN};skDO+N-s4`THgsS=^Eszie1SLq+ zj8iKJzvV$-ISd?b4C5#uKQ+6iVv07<D%<kGkjo503`n==DTqE&*&fkBs?TgN;kp2O z&B;90VJu^U$#4>t$Ey(^$~i15*lJKt?uX%|e>{jq&+=%nEe2fvletJ-IPK!gt6LhY zF3$%)*yQlIRRM$w5=i|knBDFl6wY@2y-WwC6Zd>UE$g5ceWKJ#&&!Y?IDC`6LY7o? zlFz@sdJvpjmK~)iC6=isN)p8EAe4xwj3Xc5_^Py|JGKN5!MA6UE8U!ErDy|Rg`3%W zQA*4xkEBqg$*G`L>p1BMh2GX1Q##Fdtn4K$5=DyGpfiKcDVR2HkJrz_5^B-|tcg{t zD1m1@W?*SY^n}fN2f2Tx;<SvWQWhopNX|0U+?3TYiK1<38Dzd#NrOhJK}5@*&0GKf z;<`JVQ&r$vb!`gAaoc)ev|dteB8WvGz}8}~Hsz<)tiiy{=hjk{ELoe-=Vu|lRya<< zDoSgi5XASGWLXC{qz6(-m^96jsEPyl2;Y0KP9Q#ngLe9!ShLQF;PzUhWlUKAg2Jg> zU(zb;2m6r|+^v}nsicmuISq#sNdD$}ILJ-p*-5;fW{?Th^kM5B6ylNzVA+j?5I^}N zGGvDb0O3Rn#AmaWGiUuv^bIyfQk(>%lwEZ~-f;`R9d$&f8d@D%B^{aoZB&#sR7zI- zPCMrqOpF=*lub0t$l)9smO&dBvUI50j9`^{G<u+jHZK&IBq8jIzL;Dyj|{SAn`{hw zRB;#wr5EstBn9*nB~z5Eid7XP$uD^E1bT6i7Ts_1Ld;HiHtqT&<Rgu#!tfooLnBBG zxW6CzbXt_GD}7=A7loB(u^e{xzpw7Z@?4%wC6vwNs*=DqKBDI2R@1JmUd9Sqg~;<r zQaDb+Q4*FC1C~Y}ktEEQep9x?()C=#jfrbhNQSY-!ZJ3JirtX}HT;Ngi7hA^vXl+G zB30m#>hQHREb1aj)=x4k7|y*}NlVfw%PUJND{3iUmR@ld<&P9bO`Dtlb2S8{-STL2 zbcQ-Zywt-<U}>`9eAK7uw*K!`Tc_dNC=k#RgF0l{T7Igt=?SbdL_1UUROBTHs^oZ3 z9*GwNOBPn2$bUjKZIoD`Fk{2GVcD#%SSCT!B0k6cG)NLz4SCKEY1u>#XmZS*%dc9) zb~+E^X}_r|gh?W{!-O(PBqGWr?dY*Mt0;)(X<*L{PJ2gLmNO>*FA0=Rgi;hsa?W~| zYCTluC8o#?^_;pb1!+e2L?EOqB&N6lcg*Fn+|Z8GpmO1$6)jA@(Ltj!s+X~?$7B=K zNxUzflOK6un2}K)v}t&LwXRRLYeM5eaHd|-A3kZQxT2tlOCqmY`cv3AJ@stFdNw*a z^>p~1wjgTbHS_pjt1r|>E2qKXcPbEIx4O-U<uSEQ!H7|+3PJ-cDbKW#8>LgQG-OD& zY7e!S0jG?PMx`kjH;UmIOI9`ge(Kaa8Opspm1(ge5Qa=iK2!`LgB{4<cL+NvKqZ_t z4p201$AoK?tOUMOr4C)%kYlC91tCWg1}(Bk6v;)&`N;xkV)$}iTi_GkR}9c@54+Z= zC|qIs&1GqVjO*HQ4n{LNQ9q57G7mWismUggr4xE)28BS&%q+GhFGl&}po2^`4qH;! z*eEebF&6DiwxwCoBpGs4MN36`ew`O3^-4mVS5T?&G-km#5u2jY_u5(qiaEAVEqlr( zVK8nc$ojg~;!NU7SRAS$G+wgh2q-oHCAQRr_VGYpIQa$3!9|KD)U19|E=8ka$uxki zAb@165l<qO_8(d&e(IrRV&J=K0%JkS31>!PO-jHTq1I;F2mNLvAWKf91YzX|(YOM3 zOIHo-Jz}+hQF;*j7Nrrv<iFiPX)N57+Qw$55m2C&e((8Wl61BsB3tRJ)>PI~x!-gX z$po!x>a7Q<pX!-?*LsSOp$BSQ@s@saPt;2tV7hGlB{xzS#u2lS>3Yf$NS@NJoFrrx zV<|5t;tG_s5uFeL)weB@+S#t-)SOesBCD{;1Fr4%1Dr<(b8r9y97FXuVxSb>bG%}a z7?J{r0)I*$Bt-U!91sFPrqez!`z8tYQ*m+mg9@~1R%r;>mbceM9UC9-=D0rG7<b0= z@quCk27|TU<Q0d3?xjnPf7P7^hTwwHU<XT%3~#uz#RsgH(sH&^$kIO3h|jYLH5Sc4 zSz->2l7yNiNH9zQ)0D(tSrjW`pp#M#U88?8JZVd#)`p-*qGa0B1cQ=0CI$tl6%Hob z$|uZ=oF?2vRuZD}MoX|tp0E@7Odw8qfQ0B?ct>SKZC9Jw54C2eBapZPpzmR2m?7O& zo#rO$qiqYc@LmZ@br3>eQkx!M<|nx)4tGFiWOw<Ch002!Y~`|1It!Y4a@rJ?<+(+D zCDciUr~;)M-Hz1`e#*V#+vqTHoesz0`<zWc*CeD!yiBqzKkisZKqS|U;H!#8OXVt5 z+@&q3SV%c!h$y$E&Q=el(Kb8Js-6smWtzovWDb-#v>Af(K&Fjl@|ARaol+=xXN{?H zq894#hrs>rMpAaFJA(4l-L&4LBY9|*hfVu>x&zdNnM@3;BM#6#)BZp$t>)hoi%K9q z6XILeGPPkBQ?q;|UC0!>_dBY1mv(1vl|a_=<V_|Qk)>^;gMBe3c?F!)YNS_Ml(hVt z459iW?w&RZv}qAoq%Mb^N|t7W*QAA05<9F9$ia~*Q{|<yQ0Y7y4msq{Hfz-VnBmkA zqGtA22@oNuRaW6aG%Gg6WGV1n7M9|YFhfj;7CKQel$ATc;b;w#VeE;hLC5+?7^!ST zl9bERZ>%6Oe>hBPh;^I}lwgG;HLos>0K;`jJ3w7z7L$^xc3l71$%!ZuGxHyV!tO<V zOIx{8mfFq-)3T(Y7(1HNFIE@9MmID9hn;$b6{iGMjoP|!Yv)@s@0=`_vRFo*@B=)p zwuLYYq%+i}F+MBKX8A6eI+-Ba0>_;#2Vhv`03|5`GeXvu?q^^j)n58Ssq(Tf_ypnE zwHmQ+DNzOvh(>`aNyS!ZcbmCw*(Gs94Bu%9Q}b^-6mv3Bi6xyzn2fv8JlyaDynod{ zS|uH>oN-2$65p~JW5{{tjY?pl$lHU(9Jct)`XSatvkDQ?^O@z&$v#;Wtq>5caZ2T_ z6|Lj~d`Sr$Kw^MY7*FJXQYMc&$U(UQ$*d5fE=m54uVMEkoIG(vtv<XSIV7w^?wC=Y zL`%|~;>nX^-ADo|D}#7!lpnDVJgi;gI0=%u27YXb5>(ci8ekE~8erU01ClRmz&=<5 zd`b-%SPi(w;^LqS&Qv6uEyjVZ<`iMFk-L_qRq_a&AK^DLI-&gP_(FDn(-ZB?V^%1q z7u98Y_~f^#Q!Oqz!^w(?&kd^NV)FzJg-Nyg5Q_j)WuQ?9j0009PGLt0@JwvQU;=qM z?J;F}4Czodc8|}&N-2Yw-HbJ*nXpM`>d7<8v8Ho6RmP4rV98nog|MYhBt>@Q=~%@( zuykP-3{hm7B>Vb+ur4%Op3R~*<e$6Iifq<&y_bC6%aOFK&s%V?6qd(f-r1sQ@smE_ zsC>ovaCG85$+sLiDN#cr44IJ;veH~4Jl4fz_xAdLV=+Ri{5rpx1t+9LzC`;}8jL5@ zDh_nVK5Jct9g~QY<eBeSQ@EniI(|jOH{Di+%Q+_pbAo6{y4W3`l)>DLoibo2p4erv zEg4gJ17pwJ-wLK|TfUZXxvO1JLzufHu)VYSfg%4;*$xXNvC_D`EtK`EpUHYFUO*Bv zSsJE>4`dj8`|#oD=>DN>dR9+3okCm5v0ZD9omI}eV~HTuFGw6zo^`Z`ln*9{rI}N{ z6W(LXX6c|46^9E-+A1Z~q<tzeQ%=e3FN(fXG8s3bWElg=Pky%rm6WxU{+l77O!8!B z<g-tbU=<gTc~IDYd3pkpdk(i`AiRZjO~L3*Eax$hj8aW|x}W-O2ehCBcp9w*9;_lw z3zNo(ED}H`crZD3QjwBO?M=g(7`aGepjw2D)TkrZg4pt_EuZTcPKE$7#{U!?ackRd zsU>kfU@Dat*II)rYZ+K+rP!y{blaiYW~em@^p>c{LT?#bys{ZodPmRFVw<^XNiW;) ziA~n418FgxnFx~@i0)a+Bz}_3SC4GCEgs4V0F^ho&gaANYf;Xjge3u4G=r?Ds>(L9 zk@ZhU=@PiHbwODmf=eYBt*Flu9d<5{(O1<qBPEaC76whNvIdv#k8w{5Ctkn`il$Z@ zn@A(u2d2|T-|Bir*vmQ|PdZ-7BS}Ev9}_5VDAFSVNj2881gf#tQikq<=i4jwy=K<% zl1i}fSB?>dXDUm`GJPt;-~*x(4C^@Kz<%FsMTigd7;3OVZ3mS;p%G|+eZ)~e?zBOS zCnm4WKT9bR6{O7t%8|&nQNTn`Mb^4O`7z0_B%UK_kK7EvaL+*^G`nk@axM-3C}VLt z*$kOgLW!mkNr|=!L7DtyCx}(DM}WTZ_nhq$hHscO7}F&Vu{3}dz%6&nxT?=|T(PyD zM1ti@=qT9b6rMDaJt8k&srxCSNqG-RC~ie|j_gOdsh022Nrag{L%v10$syRW3PygY z7qSZSp{F_3yqK?1hJ|4^u4Su_1Z1R|&}@ZkGHeajMSP0niv7f>`Oh*6SWjk5s|HLo zRIf)8c9w_gI;2@or}|V{N72kGh_z$c(sG9i9_a-lfq8)81yenacZ#A7%BDi_G?KC> z)U;~&Y%7pxiv1?rjjkY#pztyvtQt+ziE8p)6-=Qu>5xhtcq*TMkQ^bNk`m^rIi{na z06`HooaMeeTUzhXab8ySg&5&sh%#kB8H0w?s~87~q^&jDZ=`5+(L#N*wRDluQ89H= z96yorVGzgc5iYijDmY<06p3h*S=k|g5hEu2NFP{*=I=x(1&B$6Z*Ne+ukn2^jQLPu z%%!>9>@!^>2++BDmV-c)i1Qc^O_*#NJ2Ulbkumbc%4WYAiMvHXSj4h-9<@XX_yyf@ z!<q^oIHL&7WAC1l8rtir<LNn3j6-jgT4@xVXxRuG`$!U6lS}R!B7>ji$O>E`|4{E_ zGI00sN3EdqbEEUoFapw5=0}u<WQtPEz7CE;ICk9S0hDN~GvZAP29W1@a|1{L48;NO zjL0cTiAjI=Ol}<Qo`zrb`Os_J<2QtEj?mqrMT?}A+KaELnn>nXQO(!a%u#52I*L<8 z9;_;3HjE4!IZio7O3bnU$+zglc&vr^o$8D53i3F%%7HJy6p}0Dy15~okvTgOWw0Bt z@CAwsFd!Burub6p{zRSRHmT4*m+@H!)vS&jnl_HmJ^4iPYVwFy)3KG8Qo&&&Yuxo{ z%%8Od<0<m6N6YCcsv_EwD@=T-C#9=i%B`{ZsY+4Q0)jEUdQQi<IbARwhM7!EjoahN z;b0ct(7L?%!6?|m<@4vG%mBV6m(B3NSV~b@h!7#e@8qb&+resS@hP|wxIG~VT!YDk zx!ayV){nmKE^9dQ^HI6O`!)_6ML775w;QTGA7vumw{cKiALBp?nz8~gI28@3{*z1t zJd#pOHn@pC6WLgRfT~LGQ;mgfSAo5#{6GO1IwOj&Bo`~4sJY?|aT6jj7^YS~g@oq# zB`D8FnTz*r%m#8GSWZRpmK#&pt3gSH`jn>WU>o}(#;;4TGP8Gf6eUEAIL`8NdgqqT zbzu$|vb5@INAslk$yO~6;#ldR1KmVhDQVl%*9}F?8dYupf!Bf;<se{W_^{-h`JgEP zAq$_1y{QIMPYL;C)O7=w_dOqHI^Hv5)?u#kHS%y+vA4c-ySn9&4F862dF}T3MB3;5 z@+~_#?+yEI<y;ZWTmYd|DiW8L%<K$sWntujsb#iYwbk(_LSY-nQx@DxAc%jE?u1vc zoC+5#f)`og<ZV`abXSoR)imS2Ep4l0lx?)J+<N+?^om_nC}baO1y&)qMcgUR!mo)< z2;pnTIAJyHauyDwNnokH@vI)&fylf%39G0;Ouv#;<&`u!7TRl@2*gFlCX>`<i!3jf zv1Kq?uunQ))vl2jV7U)=%3;Z*fH_iRZ<g1omX{+QC95!|W$U<>`B{E5!>@uD*7r3l z{~QkSz1>@R#zdw|@$Y+?>Uus(+mYwVr#RSxH0*J$A~P0V@t_t*U!9gK*|9TnG4E4n z^WIWri>|zN_BTq}z4<5UwORJ<^S4m~@XbGo-uw728Q44l8|V1mxFG8E&3EXzZwF<b zJf^V3abq@eX%=xXpOuEUvkJ(j@zLH9<z*nBk1~*_bCJygn|3FKrW^}rkn)e5=XY!G z)_nU4JIe5#I;avs`Vn+dh<Bigqb%5|ixyZ19c01!JyWnz+UE2ubMg?-&%>K9RiuLd z>uJr`P?{IxR0{7q$P0oT8eL9D;Q(ETWN_v_rAm+6UI`EO)W|XFCueTo_pBW&rLW)t zW@ax^q?{23v{4kLWDTpP=^TD`J1Wn`CO)k*v23lx+E&NIh`Zrz?GrDCrTl(<*fxsx z^#8^?n-OmIVw@y7oo8Jf{yRO^`gX4h|92JGPR6yXcM;gW7-wb92RA2D%;LAgX=Nm- z;8K1xm1+Hf9NB%lr?lej6U7(fRL?gPadCD!rBm<1yS^BwdcK*6%Zcb!fcy><rL#2s z#W)}I&757%8HZ~Bj{Vs?acAR9)Hi}~DG1tQ?S_AEfjC>;$kz!szYcL$%Fnj&QYHz7 z-SU1%^090v5NlRFItQv5tx>(p=@QveRp_LbQs|R%u6#>azL>tP586w^H7<}%?KrE@ z3wvLT6Iy4vT*|Lh6J<F`k|cVqj(SCatp2f*%1NzSI)>4+(4pO~N;~TV#WGMg?`<jC zT*Or^WAnZk7N;qwdaxoxPRQUE{GA1ugB>12K@QC_a2#f&N*CgT#0zaB5R0fBU7^=J zX<N`<U(${}7HQa*tDlE-P-A|t3N`wyzj8tqk-cpNGJ>f}O?xhOeDXFR7H@iOET$VQ z=ujGE8*9nV+G11vrWLKt+oBw~;2>4~Vw{gVzqf!8PwUd}#p?@hcgpI$^>oLJaaQj= z9gnSa?X71yUyKue@9B8xK!mqN!gRXSXt{cxg^hB1)KZqZ<@ZXrdKTN>vJbS{!jcWW z-HCnuuAJZ~qe<m>u35Bv;a7eG#w~AEd>1-7%6C%XSL8~2Cx&z$u`Md*x-GVPt7?li zef(FWjF$?)IDU~&I(x%PSCwGq9DsZFq#txFyZjdp)=J8?T?n79f&v^A$uF%|QX@(Q zh-wh*m02vh+D0=gamL45=`iOzu-%-MHGJuo+p#;71eteimU3UC6e#s4c_T8F=ES_b z0!qmjJhPm!{2&K;+0o&4;F8WpNPVWLn5Aa?pWy7R(M}n>bw}|S%dM(*V9iE<QppP2 zQb5sNJKhZG<Z?>y=%VhYJuNC%YgJjz6Djeh$}_A3)h%4qTWaz-dRmWG6}xtBrIVj+ z)saRII(JB$OSlsx0M0-M>?kzbkEj9+mD*7_%l|Y@0#bz?+L~Xg?_e`_0y2rjw9yDM zw`J(*3v6Ml(^Hh#R-%R@26%7^NvIQ{hZKcS@2B3|3733gZI|az=k+)o7edyOIYKV9 zK?91zH;q3v^x0l~rL*C5SnPpAUNrTR35JmW8BUej(F#9Y@^?2*-<}qcbp8VC&Wsgo zi#2&x{_R9G8v!f8PPGDj!KT2r(eR1`n*;_!&++^B%8k|Oof~iJl^eGroe)YLk@gmg z`R>Mf>Tjk}>cH-&H#U{pnPWEZt!^E=8)v@1naVdkmG;sXowfdsN-CxOVMXQLIL-de ztiS15=k21h#RTr}peS^5?QChT(E=T~##br|y&JC-d?QP5T9$Z)7c}-A9!aE)u-^T~ z)iHKZl`&oI)Uf^HUn5_6H(tm1Mxx%dMD28hLeFj=xbwRz&Ar`{UFN2W<Ca$Dt~l!H zYnSHUjTc0Qa;6-yM?Qd7=@62!gp~vtybaFY{==*K*hpEws!vH}A&AY0Z3)_l*4W=l zFLfd@#l`Gu77HH^<Y~2u+|F~*fmzg&NI#UJJ*2ZcIGj=nW5>Rw(2w|*sXmZOx6MqN zc9KwhQ&C<{K@)wE;|8f<RmTh}>#lQ*bYKF<4|DRC!ccaIYoi7q4y2xyHzazZJN(Cq z2fDHLX{ox5Jzr#|sPnaOmkX2`rzg~1i3#<PI&_GK>^X@<??q0Bd0U-K-uj_;HF3I= zeO>A5i@=QWveUz$$P|wekaB{T$sWB>$jj3xwj*-ZFX=5CBsGXW*?^=nY~DH{eocq% z{e(K_OUDkV-+WYyDdJYDoqGdRa-QN1PR6%@Iu)4P5h)yDlJ{n)#QA>1P8EhnBB_HQ zdY(hGzVmmX-;JuMPcPzAx}RWns{>nF5)?WSL9$_6H^{iyxZ2KdMv`$=e62awxV^9M z<Fk_bxnlwtWZN01C8Xc|IRSU$wI&i%<@ks+Mapg26y=4Kf7WlpQ!19l13lxHlzp46 zd)s+}@iNmlb8wmiYV+SkfInW^`eqJJbI_`o>b;80$188&OxJ0;Sh?`SlDAN`F>vSC z2!q6D-dq$kT1Py+an9DObg&a;#+I+Q_nYWIB@Qp*&}G=5nC#oO?xPj8QwMb*FdQi8 zq7d&OyE$4jJ9Tkx4E3(A_scSj7RZ)Ai;e^FqWQO=Hk~3V?|$R#!5dYZm*Zt7HlG*X zM?91YfgrOg8!{eF_@y(d^Rb(HrvNKiiL=|1TsjlN;u9VBpE$eDx3Tvs@UXl@Ap!NK zva~KrC_y^yffts*iaD3xq5-OUdV3`=o}cwTj@zM}hjJy(9OS2BD$0s%_X1H3=gP1p zRP|a1i%hhY+YUG8_3?@+h!Y>Qc1O&YP8ih+FHl84@Y#G;lvFUE7S*>zUVF}U*fi<5 zJ%Uwgmx$P4hHNQk!z^oWc22c^5V5Q^GdkzZ4i{#Lji8G6Cn$=vcL*P}I!O!Z?e*zs zGlqvsCxRJwA@JpR_2~2hDvHx&I2OES)+Wf_K=F=V=XkqQ-Paq;=j!+%8gzE~f31Wr zaWM<gUoD^ea=aqMA=E{IEO27I7d`rec~zx$`M-;0)tBQ{nLqfEXNT82;0Z6sYZ!m< zBj1uod#?!4%ki?nAN(W@A`oxTC%vaGX`H_QgP(a`i{W$Zx4`Ln3#Wg-x6SFx1_m8D z%Yoe!Cx7$K1KwLasCu5IOMBCzEz(#@S1doD=K}GzGcfg5936aQv4@KLjMVCV>h^AB z$_C->#xd=v)qK>h$gRGmS1b_X@Ji2jbU*hj`<LT1ccmIjX&ONROrHWvoxy6y;}CYR z?}4a=H=nXXMyLa)w4>k@U+{sGNO^WGyXZ8pUaLy1nc*@N9uS78MLX%6?Ix_H5S!Q; zuN;KM9uo#!;f~5-h=b&3_`vHuSsCK|oy;t?*IGMDT3#DQ*(oRS>5W}lF5*k9Md@JT zvc_bm)Ux`<^r-@qW6<rqm(-G-#>>(Kc|P6_qBFMj0#?Of{80-%{NyDJDkGeJ%ef!Q zj1%1FP==)><v>(`N>=8*e5Edj|Eb9AZD)#Jj&snzU&FMa<n`@mt6q+CzrSC@)GBT9 zhO+6bCeEK7I9urUa+E}+XubrqzYhwk{EeGR`$}$}flW!C$rEd^2uejcl}2yd&yO<7 z6!f3o(~L1qrqo`z%qqPW{NLY~HQ)BO#`-ni{a~kKhA)43Im&VC<mZ&H(Q)e9f{0_s zVY0&j^;8Z|dmU76aY&mIc<H?S@H)M36<;n^WEB<c1W>ZCSFyidH9*0FA^GYlNy<Gq zwhvWoA8@4{p`ywRa)to)PLh73-6kwfu)Tmo|Fufdr=1*1RVsnmxA$Zwx2PjU6!Ph5 zSB1`u=gpgX$sqKM4GQUHb9zGv&C?mWMmCa<_NH5%TdKks-s^$O6*tkoOG<EH1M0lJ zSwych^u75g!~Xj$etP+-tH_HjhfcY&8X$YKTxdDA+S>9vvK;W!>ofgNt0Vp@l($bA zN_yQIgmay9paThU7TyMSL6Lk%hHbYLB-v_7v?U7d*`znU=oBIqit&SUa8V-UQf~~_ zYkM{u9cRrXQJ<xD_^Wmmb9C;o)9YQ+0gxOgq(l68otyr|eeF{^0Md>c;sD5<EKR5N z1CsN)`)MtMJUq9z7oJg51xGi{*8b-Fw_NL%%DhyF#dhV?6;3QC(9%vOJTY%;pjpb- z`045oud^8q+rBL|H@#Z0Y8$p}@)4WD+5`G-3m&$6OMAAsi_XN=l7v-)rQ<>MCUiZQ z_BZ7huUgc>7o_QMdL)1-gct-{$2gJ5P`wumD{3;m+cX{5X61MXR#Nn!ic@$4HTTn! zkFD+4K}$NVot~&Divl}sfz#w^eU-yH2i{<cO+wTeqV(awJld>sHw%SWHPMvof%ujc z*cp;Wv2#qKO3ZW%mTRk+M{h&Yq7JuLpR~)3;6byJ!V^0rn7v+HG@0u39$AfmO1EtR z3;E+Bqes^XJTySEz8XDTCV!(r_T}k#I&RbG9dmk1WwN|UcI{<OgvZ!kJO5N)<OEWC zJBe1HXf4&q@z6W}EfH)V8;Qf4+H%=SZ@itPi;dfB*fy2udG}kwieyJ^$kP#llibTQ zNA2^8{8v+Wks|On#JS%H<!&c7)1TglwbPQ<yRJGOI9TB|tB&79(Q*4?BKRoN#>v1; z8)=C5esc)sLssZ3?G2&eaI_r1-*m2^uh%0tPOUZZ+SBiT>)Rha{Pwf^)vrJK`1z+V z?!NPcJ;O9Va@2A26AmhDezY#M?V#3fZ$>K={lL2(T=+<>c`aE0AJrVk@R9YUY9MHR zl*;0*aRGds(pd*1(~QL6>ZPx*@v>JO^hip+R%;^}`dY1xMeOu)QT%LqukCKDV_o%L zTRypribowupu(ucM62f5iO&9dYfm4e21jDS0Y5of)T__z93A)sl`MKsB3aV5?X}5V zWgfh43X6sRrxpYjLwF>ntJp8T=UBE*_taax^`0mNYuuHvQ|-c5@VIF=0ZhqQwo2y} zWwr<Q`|C~e`m^qicZnW&B&i(AnI2f2O4V}WiM!MTap>6|5I4g^S&I;_WL$=$y>yKO z0_OTM@(3)eq`vf|7}My}VtZgOf*ln=@XHc-8h4}M8YjCgQ($pzdI_<y<unhsq<7xZ zJdW}+r|x%eXdc<Yj$<@|P(USt;HOSbvbU@wib#X5AdJWYGXdR4T&UwkB=v4PG6Hk6 zFv^(hN|ch$`qaamB;u>fq&<tZ^VS}v9oep7C~+!r#z5dfSc31iNCYj_t4@(w4#Sd4 za}6CJ0y|n|nY}VWWn_q$!WYz<@QD#mr!VN63VAKSRT!hpfZqPA6D@+g3a3eoJRPTM z<hLMUw4{alp+hWKzf+LO-8le@=F@xab!WOb`L;|@eCze!mU+8Xg~PkOB~t+bM%CZp zbNWua9VNU%pWltl__l@1>0~)ZGQDtK6^^g}#(KYt-N<^M?)jG94vBvq``m37)~zb5 zWu3zJLi&%h8I5?z5QkAuhSPhi$rTYqm=XL6Z;R~Bz4OwD*L+zdnFXaM@H{LJYtP-> zyCU25vysyytDGsvpo4cTbEVRLv{=X6vl85~Cr<>aC3kFZ03|V|_wcfU%P0J7zqJ!< zxJ+8>pmJ5EQ%GgVY_)bOjU8Kq?@-oF6|_nY^P&`0$?M=CrZF20y%=+gWn<yoy0A;d zyx1H}pY0dy?Bz+yqi{A3-dLv}BI)g8um0>*hQHwjow~#+4{R%IRRIk}K^cynUh~b` zb!)G<NoNcWD{6mnYUE2(dPdtAb&k-^fA=hVMMu`2v$=DAjZ*+I_m+n59!bUO$R*o_ zN9IODwbm)+4M{|<u{fU4Djdc)C_}${5bbG|ZtV0t&Hj-C4Dh6Av(AJB^uXIm4a`up zoXu6fFg$Wv6yI$+ww~^2kPH@JdsB44LwOjIL*<R|(={EQ8r@Aqm1N2Cng>$A=X?F9 z$L6E`&+Ak7m#P2DH^83OOtdi|-TD5Pcb|W<`gN0HP4)NJt$j|JtzUlU3BxxBwVWtW znDY$O)+#}6bJ*qH-qwj10cAWF0cF`20Tn#}T<|n<`OA=snwKGE4woSng)KvBUKb(n zv^>8Ina6#8l<xAtFF-CHdE1-3te<&~cEm$UQn(UlCo<6FJTTADJTOntJTTACJWxr2 zMSWB*V$t}#P`m?jUd`=QY-+Qg({g)<-ZEs7;rTX;49_F;AT8);8Kt<*U)uo1ChOG# z%;yU*2gA&$%4Z82`gBP{pDbwTR|_y7Ex_C@>ClTMpyx|K&kPi6)GrJ(Bl$m1pg#0i zKU)I&$r8|?8OV`cWk(nK=NdZWpDSqWpKD-t6w_K!14I8@14I8@17j~yBV+$uBV+$u zBV+$uBa3aDW<@o!*tS{ZjDN1$yo>#Fjg0+sja)qPGyb`5GxX0jFi+96O4q>9Ki9y} zKi9y}Ki9y}Ki9zGd1hyP#y?kW&iLmVS!8(H@72g6!}G`@!}G}4Ki79JqZGFp`RCGF z<ev*B^3Mem`sV_Q{ByyC{<(l6|6DMUe=eBFKNn2sp9?7T&jl3v=K_lSbHRlExqw3d zTtK0JE}+mq7f|S*Wgq3A|0;QUa?w*khjK;NUff}PHPi~W#HzKlGY(}cXt5ddjoR`( zZBDbBy2<SC=YiSp%mcIAnFkiHGymMh-_Ik9zn@1ITRD#`wsIa>Y~?J{-ef#K=Sfj! zraLLh3@9ne4CtpO-tojGWpa3I5v;#WWH%m$A1wj>a0%#p5lC^cv@&&knq_EFZK3AY z&>79Gpfj3VBQ=Ju=GMSab8BFzxiv7<+!`2bZjFpJw?@XATO(u5t&y?j*2q|ME98vk z7G$Wo1r%y-0fm}dK#}GaOsKg96l!h(g_>JHq2?BltGT%2tdL~+b1G}X=v=@`yfbE% zXV@wIJz)wfRMG6QEj)t)ovuJxRl<g{l7yJ79w8<xMu^EO5n{43M3|xmF2+@WJT^)8 z$L2U+PEzk)c4aw#J&Cc~xg@~u<xKO~Q+iFva`Q>H-R~!<b}y^?Pqb71Kay2jGMfhd zd95B&CSc>ix<F+w5TQ=WF<u%vH&w(w!jzD8JOt-<N-{abxYAm+<4S9V$)Ra@uN;)R zn18TQb{{(lynFfY9j~4{nbg7kc2WoTa#DwJ&Mr5O)J`&r^8mF=WGFL}u>>LSg+2L( z^9-_A=}mU1!niiE!niiE!niiE!njgaVO%LYV|<&KF`iY*mp!YLFMCEOU*^Z;n125> zIe1ccnlDhUsW_toQ*j3Qrs9n8O+|%qC$Yk~lUQNgNvtrgsi-insmK`5ROHK^smPZ- zQ;{!wrXpYVOhvxznTmYbGZp!=T-OpAa!th#k~Ee?$~aB>7Zc(-!PPEcSzbe!FK6eb ze3w*VTsf;SuAEgESI#PoD`y$w&DObzPDNYT1-7hRbD1-!OldfPZJyH!&|jbCj8Y;m zd_9AF`(I&P`(I&P`(I&P(@|mEDXlOIp3ArYxgF2`=gXe`&zC*>pD%m%|8Gu{Q$<qS z{#qI?U?q}@U?&eSrXA<D0(m%tikpZUDhbUo1*+P~8Icf^ZAFO5j~`;(xUTAtE5jAW zmEj8G%5a5oWw^q)GJMAPGMq8VcezuQoYUCY<ZmbE<X%o`40qg<?{dHGsaL+Yr(XH8 zr(XH;0`)2}U8FUqm~ITBf9I5k>trubE>Sz9PHH+H)ibDQV1)4<=(!!=fmRq-QY(xr zsTIa`pcTe-pc&&4wS3tlYWcE9)beGIsO8HZQOlP-qLwdvu0LN6iCTqmiQ11Rq;Vo4 zasey0b(}Xj!-^P9taeqPZ1G}H7Ni)IB`F4FQHnuXmVA&WO!>JyX~~z<g!-*lGaAoB zp3(^r26BOgxj?xV=8Os~%o*fcm@}q`#@N7D7}pn87}vs77}vs77}vs77}vsNj3*TN zvS(rPWlv`EWzWLo%btbFmpu!UFMAdyU#{eFoDr%pu7%<DBWaunE-qkM9OqzJNXGrT zXe^6Kgi6PP5I;>MYR_#2EcXn0nO8B!(p_Onj5S_4tw5RPPMC@cR7NUnsqp*|R2KWj zsp{%>nd*kaWQX9+jinuDJPRtOKkQR6{SoL?co%}oV1}SFm?3D%V4jNX!j{U2kBQ`Y zT1xFZJA1C<y$V#EZ3rqO9)ik<hoItYLr`(H(Gd7~g!99_aAU9v<HleW#`QZD#`QZD z#`QaAj30wlnB3=3;R+p(L1kv6p?+RwHUyQK4MDRr`=uqUT&w(BC(oV7<~Q->FXGFO z@#R#J=o{Wtjp%!)REg++|6sTGr|YwH-8I*r&U`=B9s2iAHHZH7k7nA>wTABeznJ;{ z^O@_<(skEzAOq96&MX|z60W-*n7Amq>}3dY<6ed!U(WpA9UJ&mkgUy(RHVz7GJ!JL zaJ5L7LN>-pc=9kKYBnCV3siQI5vuU}ahBoSQZZQ}CR?l!lMPmg$@VJ5WOL<W(zLpl zs|kySrp(0{1BV|?#e{-hzzSU%+le#m#B8Hmo`~)E`OYnsy(J;WP0d#A<Zg%UxT)Ey z9XB;wVO&~JVO&~JVO&~JVO&~JVO&~p#uTa=O<36-5@PZghL{CoSZHe4&Vq3+BsFYj z!8qS780Whs<Lrk0)m*q?{~1&0X(Z2uo`#q#hao19Pl$2NX4PlcY@RWNo<{d7rhe>y zs&;apLrm^-h{=5pF?miyOrBF0lh~j8*opkPmlOAMFDL5f>Of+C?za>1bHAN<pZo1Z z``pWk^|_Z5>2vR$IG=ktQ9k!_Vtnr9MCjbEB|_(3PK3_AoCuwJIeC6pTJZb<pF69; zY4JVs)`cHTcz$w#O9;XR%qIwESU?bJkZUl`AfF&q7?&Va7?&Va7?&Va7}vQ~7}s%C z7?&Va7}s%C7}s%C7}s%~F+M@4FnJ8e8dYIjf>2==jG<2us&*EPvriDJb{34YPY|kh zmW;DY5UO@uf^f$81fjy@@flm83gZ%l3gZ%l3gZ%l3bR1peS&aq$0rCC#w7?9#w7?9 zCii)4sw<335GssI5HiLi2>G%{5b|Y@Amqy)LCBXqf{-tJ1R-Dc2tvN>5rll%BMAAj zM-cL5k09jB9zn>LJ%W%gdjuh0_6S10>=A@~*&_(~vPTf|<(MFxK><OiKqZ+oW)Z9* zW`b}E=f~Fn3@TPB#JE<wYRC1C6~?vN6~^_B6~?vNXH2n5?sFwkaW5xPaW5xPaW5xP z8DD1ocg)_#3AqbcVQ&%a#NH+t<GHawAkLsd-^Mjx6(-ZS5R>~IVlwpzF`0UVPxdlP zXbj3C8iTTo#-J>uF(^xE2r48l1{Dz)Yx{XlPUmxlpe2J@h+N#KB_m#_T-?%<5ieve zZfVhoXV)LMlzo2)@=fP?R!YVvG6gSO(^<9Sn$8O2n$8O2n$9!EH=Pxx=u%{rN_Kx@ z?V@U_=u+5Hnb{CjW;O(snRP*FLDHSD#QI!|l~~`Hd*%mDtk3;+Vtu~UCEDkHJ<&e@ z>)t^mxpUqbB>8gUeeS^I)j-$$<kdj;dSZTl=M(kwuX_$X_ug~p`LgHG^W_<bp15Bq z=RtNT-=kVQ3R^m5hsGjI`Pnu38;6o-P_bYk#tliUcCs}H+sPIz#AI6#VzMcSFvWto z7%xu9kL1M(`LY)$<jY>1@Q-P7%4VqXsWM3TnH}aO-SHz_pxpddh02BMVN33yez>Sl z7bv$+XOv$ZmoZ=3+Wff7`SNd_rTcvOH}T~!;>(ZmWvQt<q~}L0rT^n+z|f7Rd1AxX z1uTzg49mTWL3ySpKp5~*zs9}4K)F+WM)^~nG2T??%idJy%idJy%idJy%idJy%i&a4 z7*~5<P7En0QFqtnc^9}c*D<b4c8n^sJ%PHP=-YU@FHr7uS14CCDvUc`zdZHn6w!|P z#u;R<6rZf&sW5KxqQbZgyu!E)yu!E)yu##%kDjYUg(1dG?Vs;eV#2T;H??22lP5K7 z$4!Cfb`rOBn@HT%y^OX+6YXUc^S!a9li!B%E--l)C|3t6l&b?3#?=8x`hq@Ppxi!H zD7Q})#_bc6v!G8GD7Q~%l<yic#&Zq%vgaD|WzRL_%bsh<mp#{zFNdz7!ni|9D7Rop zFHr7~o>BggW{fwa`LZ{p`LZ{p`LZ{p`LZ{p`Eod<6~-M>g6q+c@@~*;XL|w5V;aH& zUvzHE_eB-P^+grN^+grN^+grN^+gpX59QeEo-w{JsxYoEsxWz^!+W{DsA|XcMHObj zIG5aH*q;UCTr!hkJ4?pdU1qMH%k{At<N4Tp8M`#;2J_{V;2CqkeA#os`LgGN^JUKk z=gY*aQP(Ql5UOg4x+Xx!DeEwvwF_9W4k0WH<U~YOwUs4c0)$mOTP=4Z_ysEG1|}Zz z0+zLMYymG&<ryPbki4qeTGDxUe_+*48PKRl!9?SQ77XYG${)}Rm^+{sD1SiDuwX#X zpt2M^9)}9!4rqn(2ebke2_4@Jub&4r@PucO?+Gi6YoRNQ>j^82YoRNQ>j^82YoX5= z-xF3C*ArG4*ArG4*ArG4*ArG4*JEUi=P~kS&tv4vo=eD=J(rL#doBSIx<G+1P`(0R zz+45sK=}%Mh6M_I2KfqHVO#~SFunp;AYXy;o`aU`HL8C48Ps!$%X#ecs7~xq8)NgJ z&0|jo2u$Rpu9^)B7Os%xz=8QT%bLg7rC&Gcny71_Yp1S(uCclXx)$pi=$fr7U|A7~ zpZXU@!e++s=LQ;kiTaK|TYzDY8;oy8UeZEM-0L4%Lovob<F)R#w+L8czPI3R;L8%h z%<~DE=g>haELf_Mm)KY%E9{&`)=>Y%Hw{vSoYBY{>H50sCPR&^TMRX_28J4014E6h zfuTlLz*r*-Fx1EbiZrrdB8@DVP$LT{(#V2|G_qh~jV!20BMT<d$by;I$Ql`Iq^>U2 z$V+Ujkrj4MBWq}^kri@ABWq-+ku@;X$Ql@GWDN{8vId44Sp)TXGPfY}QUPO)EWl7B z3n<daf{8S;U_y;7phzPNCep})i8ZpIB8@DVNFxhoUL$LyKKpDzqOepWFR`&kR@ga> ztf8?+R>&ERtdXHc*1%9BYhb96H89l38mP~%qSe4Wo70r70>&CyfT2bfP^6Is6KQ0@ zgc?~ukwz9wq>%*^Yh*!18d)%rMi$JxM%Kt!BPBCSHS!W0Yh;C;)5sbcYh;C-(a0JZ zYGe%zHL?bV8d(GN*;TX}s0mvH3^lT9G1kZe3^lTVB8@DVNFxg-)W`ygG_qhKjVzd0 zBMU0h$byM9vS8*lvPQ-lDdAeGk(bz5BP;BjM%K_+BP-;LM%KtsBWqx&ku^}CUHz$n znukTeP$TOWLyfF}u|^hPsF4K}X=K4f8d)%*Mix+{kp&ZJWWmH5Sx}Ki7EGj(1v9Ua zH8R#nNue|{KY^2WQ|dSC?MynfLdHqX8W^fV4b*eF5?%vCRj7fXD%8MG6)Iq?3I!Mm zUcp3yS1^%C6-*>jvR3ocFXKCp(z?bx>Us%aT!)HyzqniiaMyIlP<L_V3VL!A<4S`o zWU>9Tz_P!5GNP!TsBB4^2S(C)(PAW>7eHm0JPo=4x@&gz@ce@{7LQD_`Z4D37j!B) zhPa*N7-CFv4CC!f^>h8%g8qQ_m)7dW1a#Ne1k~hZ>l(c;X$%d8y=rwv*ehf#>=iH; z_8J(O;`-5_hr(XBsL!qp*T7KNYhWns1sDl?!9>DdFp;nqOeE|D6A634M8aM$k+2tx zWH_|KH82!*&GJHFzl4UuUO{Jsy+X#qUIAlauYsYk*Fb%CWw-`vU>5;HVXs>Zg}neH zVK10S*b62S_JWCoy<j3?FPKQ!3nmiwf|(We8W;+@#9^VZUqVA+ub?x+ULj*)uYj?z z*Fb%CMY9HKycPjNVXs>Zg}nxb!d`%puop}u>;)4Ed%;A)UNDic7fdAV1rrH-!ORMK z4Ge|74myL^K8nU%LPKG%pfkc=A!A{$fU&UGKn;T{!!<Az_8J%pdkqYQy#|KDUVxFX z7fdAV1rrH-!9>DdFp;nqOeE|D6A634%nExA428YqP1NFyuwOz$VXvSw!d@X`VXuI( zu-Cv)*lS=Y>@_eH_8J%pdkqYQy#OO&FPKQ!3nmiwf{BE^U?O2Jm`K<QCKC37nHBaL z7z%sI5-kw+OK2$U6?8_}D`YI}6)+a|8W;+D4Ge|728P0314Ci2fuXP$U?l7X6A634 zM8aM$k+2s`B<uwf346gr!d@`5!d?SIVK2$f3t^v5)m=ifu+Kt^WKO54sy0iWa2}W? za~_x_a~_x_a~_x_GX|y^j4{;=&JJP8r%eMj5u>PU2{fF+s?~S~Yhbo5(@$Ol!x^lB z;SAQma0Y8&ID-Wk&0xXI&R`A9IygNoWszWk4qifa2bZN+(0B%GU^s&{Fr2{}7|vh~ z3}>(ghBH`z(F_*M><rexa0Yd8p$=X`!x^lg@eJ0$a0Y8&ID<7XoWU9x&R`7;XRrXH z87!FD8LWZ&>}rel-Hc{%dVSbP*%_Osa2|Ww$v1JJ8V^!88!tQ8NdN56t0rGcn0fr^ zrJ(BZU*-pz2g-RbYEf(i;QVt3hl*Z5j$+qkZDx&FaQCbd3y@hS=8<Iw;{s$6r15cm zSI=I~m|4)~;*k$dAici30;xqKU-tVi=;z`&DtrGIw7Gnavf*0LX0}}O$gmuwR$%|Q z(yMXz&n&$L=E0mM8<nQN$nri9%tJW~49h|4r!M|%-fEVxU;(nI?{twx_28$MEzTp0 zXv`yvXvD}bO?Tpf^v*l2=h-{-w8n7G!>oBeEYW37f|+gT(<KdY@X>5T9N09A`N%Nw zD5j0lGn(q2kXn!9^Cge=YzZhRggR+QPzZIx1cgv1Oi&1Q!X%D0uUf&@>w2L0T-MF! z+bmJ7gVg%_nPlbF_=#7p>;9M6>__LZCnGfNajRBOMra;cjL<wX_D}WQixHY{vlyWm z8Kut3eWSEk!DR7?Z&nG#{FD@-m`2{|@y<dai;k(7OgCIXGgY03s*G?^n|b!8ThxRt z?B^vk>}L%P`&k3Se(K`FeqKVue%8>ipEXdQ-GP@<E$rtdH0);$4f|OG!+wf+E$rtd zH0);$4f|OG!+zEaf9odHqf2Pm&l(!`vj&F!tkc*t{k(*R{j8w=;eD8`y8=w4ZCcd} z=C>xkla%Dt&TkfAzF2^HT!4|;4JV;=T)=P=G?oj6`VtyWLIsT{p#Y;vD41vx3MQI_ zf{7-fV4_JVnAu6Ff#D>G)GVBYOQ`PP+SLjgPeK7klTa|xBos_E2?Y~PLcv6nP%yKT zPy@qBsPn-y=I9a{PC^BZC!qkNNhp|T5(*}ogo24Cp<tp(D45wvsDaTWyj;!!ub|N+ z)X;DePQYLiPMBa4PMBa4PMBa4PMBa4PMEn#xB!Nepo`1Q(aTF{I0+Rro`eF7CZS-W zNhp|T5(*}ogo24Cp<rewp$6)+XT4w6v@|wHSI}@0s#fDkD8OhE3MQI_f{7-fV4_JV zm}n9TW_A*4U^odi=bo8_OK3O=6*QiN0*of1V4_JVm}n9TCYpqTi6)_7W+$NrhLcd& zcAX|+l8f64)7f(6NtlObDm@R({hS8Yocq+z$+*H!^c?kb78(mnxqT!o1rrHN!9>DR zFp;nnOe8D?Gb=1LFcg+*Az-GM)kgC?2{}%lI0Kl@U17y3G2D}9_FX}<49+(jXJIc| zRfcZS?en7ed_S`S%=fYclMb@v4mF=MDsTx6?PUeEap2jfHLw696)2cU1qvoofr5!t zpkN{uD41ClsDYshyu6@q`kE^&m(W-RF0r8sTtZ_NsIW6CP$A1g#I$7Bz)%HhV5|Z) zG7tW=3Z&u=nU(Muf>b4Zwmx~5rk6{u!FlW#fM=>wE*g%@QZArjUCJd=kssnWS#NTQ z%ulrdnFVSAQf`C0Pp=bR-aagRxP&Uhxv*7{oP|)4(uL40feRihu28vnth*vslPf-# z&^!Z6I<R~S;wqKP4lJLoxK8D=)#bAlSE^jL`WmyPwVh=$U`t@jpkcMjMOVXel}lvS zfk{7niOhq#0GTyl0WuHiJTk0Vx#;I<y?C<3;}TlrWC65j^#W*-lLgQsCkvou(Rc=$ zDAUY<2DK~a0Sby&&Y+-r<qV3-SI(%Qe&q~`3Ruplpn~NL3QAbcprD5342p_a&Zwx0 z<&28TSk9=Zj^&IB3R%veppxYb3QAedprDrJ42p_b&L~K9Od>C!g+(qPQl)fZ8cM8F zQc7tP&?GMfCBq@o7o)0RH}w}ge>0gKpvfA%39Zc~IOK3w(1^rcK_eD-1&wIj6||6u zNh5ZJE!1EMwlKLR*wE--_2G5qAvF7!?Vi}&g8rW9+!Aczb4#$VF&8IBx1`-XZ=UK@ za$YFi5@?>aCD1%+OQ3nqmO!(sUIGnW^`#_Ok>5hIaAG$7=sme9Pg4!;sTOVtwn+IB zY?1OM*urj>V9S`zVFT(?jcnpBlYwQ03dl=^%IsxM^aJ`*HJ16yTw?)&sTvCyOod7m zW^ODphneeGCNXoc%wpzXiN?&S)GsWSnsuB%Pq0bqTMft0mcf!|pLi|ZrK)8*<4LXT zaZV1+Gk_XA%K$3y90RDKGYp`H&M<%)s?QiPPsVEKoY$$ba}1!y&M|-*JI4TOY_W}= zDA(9x8y8?_89>$UECZ;q`mA)ql0Lk~T+A|nx(_o9poZpY^GrYuonZhqbcO-c&>03$ zLuVL34K3bm!7R)&fU4bD22f**lrOMN<($LmS1n;Y>voHjFKKs<0o3i5F`H{QW&owd zm;n@2%m4~%h5-~<%m4~%h5-~<%m4~1W&i~hGk}7cVE_d-!vG3wh5-~<%m4~%h5;1V z3<D^z83s^bGYp`>W*C6H=rsdyjdKky2f<J0=F!OtTx`gahF?TGtgo8QY{8>cbr19z zzq16Yky{8Y9%^za<EpcTEiAznwy*?S?C26~VGB#J#f~n(mhAVeEF?vl6@#QGv#_Kn zv#_5on$Dz7u7@eIlya7{51O);v#^x6oQ0*#r3;hBT<fqKj?~~;7GHtqSbPngVevII z>!nA{YiQQXCD5Xm9>1xZEqb{GTl8`Xw&>*&Y|+al*rJyUu(K?_8i!dHUt{xBxT;rU zUt=z2S$y5@42!R!Gc3M_&an6zI>X{?=nRXmp))MLh89M;KoW`vUSbwzS$x%p**sp2 zEmH0==o(w3d<k}r#n<hYF`H{QX7Q!Pn8g=V%;F1bhQ$|H%;F1bhQ$|H%;F0wX7L3T zv-pCVVethv!{Q5UhQ$|H%;F1bhQ$}y42v(Y85Un)Gc3NqW>|bxvv<nlxyHE$&$9Rm zTx`gahUZv(-RumDuc0$6zJ|`Q_!?R~l*e>yY+(yau!Suw!4|f#1Y7Lr5^S-f3$U{+ zzKp{Ri!ZPl7GGd9EWW^E7GF>^EWW^ISbTxau=oO-Vetia#p0j7{PdIKcfa-Rr!Vea PzWVOBpT2th=)3<PIxunb literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.woff b/Ivette/src/dome/doc/template/static/fonts/OpenSans-Regular-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..e231183dce4c7b452afc9e7799586fd285e146f4 GIT binary patch literal 22660 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 ML;wL%uV=LY00kR;TmS$7 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/template/static/scripts/linenumber.js b/Ivette/src/dome/doc/template/static/scripts/linenumber.js new file mode 100644 index 00000000000..8d52f7eafdb --- /dev/null +++ b/Ivette/src/dome/doc/template/static/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(function() { + var source = document.getElementsByClassName('prettyprint source linenums'); + var i = 0; + var lineNumber = 0; + var lineId; + var lines; + var totalLines; + var anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = 'line' + lineNumber; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/Ivette/src/dome/doc/template/static/scripts/prettify/Apache-License-2.0.txt b/Ivette/src/dome/doc/template/static/scripts/prettify/Apache-License-2.0.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/Ivette/src/dome/doc/template/static/scripts/prettify/Apache-License-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Ivette/src/dome/doc/template/static/scripts/prettify/lang-css.js b/Ivette/src/dome/doc/template/static/scripts/prettify/lang-css.js new file mode 100644 index 00000000000..041e1f59067 --- /dev/null +++ b/Ivette/src/dome/doc/template/static/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/Ivette/src/dome/doc/template/static/scripts/prettify/prettify.js b/Ivette/src/dome/doc/template/static/scripts/prettify/prettify.js new file mode 100644 index 00000000000..eef5ad7e6a0 --- /dev/null +++ b/Ivette/src/dome/doc/template/static/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c< +f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&& +(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r= +{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length, +t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b=== +"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value", +m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m= +a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue= +j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m, +250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit", +PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})(); diff --git a/Ivette/src/dome/doc/template/static/styles/jsdoc-default.css b/Ivette/src/dome/doc/template/static/styles/jsdoc-default.css new file mode 100644 index 00000000000..f12f3f6d62c --- /dev/null +++ b/Ivette/src/dome/doc/template/static/styles/jsdoc-default.css @@ -0,0 +1,496 @@ +/* -------------------------------------------------------------------------- */ +/* --- Main Document --- */ +/* -------------------------------------------------------------------------- */ + +@font-face { + font-family: 'Open Sans'; + font-weight: normal; + font-style: normal; + src: url('../fonts/OpenSans-Regular-webfont.eot'); + src: + local('Open Sans'), + local('OpenSans'), + url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Regular-webfont.woff') format('woff'), + url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg'); +} + +@font-face { + font-family: 'Open Sans Light'; + font-weight: normal; + font-style: normal; + src: url('../fonts/OpenSans-Light-webfont.eot'); + src: + local('Open Sans Light'), + local('OpenSans Light'), + url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Light-webfont.woff') format('woff'), + url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg'); +} + +html +{ + background-color: #fff; + font-size: 14px; +} + +body +{ + display: block ; + position: fixed ; + top: 0px ; + bottom: 0px ; + left: 0px ; + right: 0px ; + overflow: hidden ; + margin: 0px ; + padding: 0px ; + font-family: 'Open Sans', sans-serif; + line-height: 1.5; + color: #4d4e53; + background-color: white; +} + +#main { + display: flex ; + flex-flow: row nowrap ; + width: 100% ; + height: 100% ; + overflow: hidden ; +} + +#index { + box-sizing: border-box ; + display: block ; + order: 2 ; + flex: 0 1 auto ; + width: auto ; + min-width: 300px ; + height: 100% ; + overflow: auto ; +} + +#content { + box-sizing: border-box ; + order: 1 ; + flex: 1 1 auto ; + width: 100% ; + height: 100% ; + display: flex ; + overflow: auto ; + justify-content: center ; + align-content: center ; +} + +#page { + margin: 10px ; + flex: 1 1 auto ; + min-width: 600px ; + max-width: 1000px ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Content Styling --- */ +/* -------------------------------------------------------------------------- */ + +h4:target { border-left: thick solid orange ; padding-top: 4px ; padding-left: 2px } + +a, a:visited, a:active, a code { + color: #b63910 ; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +header +{ + display: block; + padding: 0px 4px; +} + +tt, code, kbd, samp { + color: #8a8a61; + font-family: Consolas, Monaco, 'Andale Mono', monospace; +} + +.class-description { + font-size: 130%; + line-height: 140%; + margin-bottom: 1em; + margin-top: 1em; +} + +.class-description:empty { + margin: 0; +} + +article dl { + margin-bottom: 40px; +} + +div.summary { + margin-top: 10px ; + margin-bottom: 10px ; + padding-left: 20px ; + padding-bottom: 10px ; + border-bottom: thin solid #c0c0c0 ; +} + +table.summary { } +table.summary tr { } +table.summary td { padding-left: 20px } +table.summary p { margin: 0 } + +section +{ + display: block; + background-color: #fff; + padding: 12px 24px; + margin-right: 30px; +} + +.variation { + display: none; +} + +.signature-attributes { + font-size: 60%; + color: #aaa; + font-style: italic; + font-weight: lighter; +} + +nav +{ + display: block; + margin: 20px ; + width: content ; +} + +nav ul { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif; + font-size: 100%; + padding: 0; + margin: 0; + list-style-type: none; +} + +nav li { + white-space: nowrap ; +} + +nav ul a, nav ul a:visited, nav ul a:active { + font-family: Consolas, Monaco, 'Andale Mono', monospace; + color: #4D8053; +} + +nav ul a:hover { + text-decoration: none ; + background-color: lightblue ; +} + +nav ul a { + padding-top: 4px ; + padding-bottom: 2px ; + padding-left: 2px ; + padding-right: 2px ; + margin-left: 4px ; +} + +nav h3 { + font-size: 18px; + margin-top: 12px; +} + +footer { + font-size: 8pt; + color: gray; + display: block; + padding: 6px; + margin-top: 12px; + margin-left: 20px; +} + +h1, h2, h3, h4 { + font-weight: 200; + margin: 0; +} + +h1 +{ + font-family: 'Verdana', sans-serif; + font-size: 32px; + letter-spacing: -2px; + margin: 20px 0px 12px ; +} + +h1.page-title { + background: #f50000; + color: white; + padding-left: 20px ; + margin: 0px ; +} + +h2, h3 +{ + font-size: 24px; + font-weight: 700; + letter-spacing: -1px; + margin-bottom: 12px; +} + +h4 +{ + font-size: 18px; + letter-spacing: -0.33px; + margin-bottom: 8px; + padding-bottom: 4px; + border-bottom: thin solid #c0c0c0; + color: #4d4e53; +} + +h5, .container-overview .subsection-title +{ + font-size: 120%; + font-weight: bold; + letter-spacing: -0.01em; + margin: 8px 0 3px 0; +} + +h6 +{ + font-size: 100%; + letter-spacing: -0.01em; + margin: 6px 0 3px 0; + font-style: italic; +} + +.ancestors { color: #999; } +.ancestors a +{ + color: #999 !important; + text-decoration: none; +} + +.clear +{ + clear: both; +} + +.important +{ + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px; +} + +.type-signature { + color: #aaa; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace; +} + +h4.name { position: relative; } +h4.name .anchor { position: absolute; right: 2px; } + +.details { margin-top: 14px; } +.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } +.details dd { margin-left: 70px; } +.details ul { margin: 0; } +.details ul { list-style-type: none; } +.details li { margin-left: 30px; padding-top: 6px; } +.details pre.prettyprint { margin: 0 } +.details .object-value { padding-top: 0; } + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption +{ + font-style: italic; + font-size: 107%; + margin: 0; +} + +.prettyprint +{ + border: 1px solid #ddd; + width: 80%; + overflow: auto; +} + +.prettyprint.source { + width: inherit; +} + +.prettyprint code +{ + font-size: 100%; + line-height: 18px; + display: block; + padding: 4px 12px; + margin: 0; + background-color: #fff; + color: #4D8053; +} + +.prettyprint code span.line +{ + display: inline-block; +} + +.prettyprint.linenums +{ + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol +{ + padding-left: 0; +} + +.prettyprint.linenums li +{ + border-left: 3px #ddd solid; +} + +.prettyprint.linenums li.selected, +.prettyprint.linenums li.selected * +{ + background-color: lightyellow; +} + +.prettyprint.linenums li * +{ + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +table { + border-collapse: collapse; + margin-left: 1em; +} + +thead { + background-color: #ddd; + font-weight: bold; +} + +td, th +{ + border: 1px solid #ddd; + margin: 0px; + text-align: left; + vertical-align: baseline; + padding: 4px 6px; + display: table-cell; +} + +.params, .props, .description table, .description td, .description th, .summary td, .summary th +{ + border-spacing: 0; + border: 0; +} + +.params .name, .props .name, .name code, .params .type, .props .type { + color: #4D8053; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 9pt; + white-space: nowrap; +} + +.params td, .params th, .props td, .props th, .description td, .description th +{ + border: 1px solid #ddd; + margin: 0px; + text-align: left; + vertical-align: baseline; + padding: 4px 6px; + display: table-cell; +} + +.params thead tr, .props thead tr, .description thead tr +{ + background-color: #ddd; + font-weight: bold; +} + +.params .params thead tr, .props .props thead tr +{ + background-color: #fff; + font-weight: bold; +} + +.params th, .props th { border-right: 1px solid #aaa; } +.description th { border: 1px solid #aaa; } +.params thead .last, .props thead .last { border-right: 1px solid #ddd; } + +.params td.description > p:first-child, +.props td.description > p:first-child +{ + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, +.props td.description > p:last-child +{ + margin-bottom: 0; + padding-bottom: 0; +} + +.list-index +{ + margin-top: 2em ; + border-top: 1px solid #ddd ; + border-bottom: 1px solid #ddd ; + margin-bottom: 2em ; +} + +.list-item:hover +{ + background: #ddd ; +} + +.list-title, +.list-descr +{ + border: none; + margin: 0; + padding: 1px 20px 1px 0px ; +} + +.list-separator +{ + border-top: 1px solid #ddd ; +} + +.list-descr p +{ + padding: 0; + margin: 0; +} + +.dimmed +{ + color: #bbb ; +} + +.disabled { + color: #454545; +} diff --git a/Ivette/src/dome/doc/template/static/styles/prettify-jsdoc.css b/Ivette/src/dome/doc/template/static/styles/prettify-jsdoc.css new file mode 100644 index 00000000000..5a2526e3748 --- /dev/null +++ b/Ivette/src/dome/doc/template/static/styles/prettify-jsdoc.css @@ -0,0 +1,111 @@ +/* JSDoc prettify.js theme */ + +/* plain text */ +.pln { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* string content */ +.str { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a keyword */ +.kwd { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a comment */ +.com { + font-weight: normal; + font-style: italic; +} + +/* a type name */ +.typ { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a literal value */ +.lit { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* punctuation */ +.pun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp open bracket */ +.opn { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp close bracket */ +.clo { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a markup tag name */ +.tag { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute name */ +.atn { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute value */ +.atv { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a declaration */ +.dec { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a variable name */ +.var { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a function name */ +.fun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/Ivette/src/dome/doc/template/static/styles/prettify-tomorrow.css b/Ivette/src/dome/doc/template/static/styles/prettify-tomorrow.css new file mode 100644 index 00000000000..b6f92a78db9 --- /dev/null +++ b/Ivette/src/dome/doc/template/static/styles/prettify-tomorrow.css @@ -0,0 +1,132 @@ +/* Tomorrow Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* Pretty printing styles. Used with prettify.js. */ +/* SPAN elements with the classes below are added by prettyprint. */ +/* plain text */ +.pln { + color: #4d4d4c; } + +@media screen { + /* string content */ + .str { + color: #718c00; } + + /* a keyword */ + .kwd { + color: #8959a8; } + + /* a comment */ + .com { + color: #8e908c; } + + /* a type name */ + .typ { + color: #4271ae; } + + /* a literal value */ + .lit { + color: #f5871f; } + + /* punctuation */ + .pun { + color: #4d4d4c; } + + /* lisp open bracket */ + .opn { + color: #4d4d4c; } + + /* lisp close bracket */ + .clo { + color: #4d4d4c; } + + /* a markup tag name */ + .tag { + color: #c82829; } + + /* a markup attribute name */ + .atn { + color: #f5871f; } + + /* a markup attribute value */ + .atv { + color: #3e999f; } + + /* a declaration */ + .dec { + color: #f5871f; } + + /* a variable name */ + .var { + color: #c82829; } + + /* a function name */ + .fun { + color: #4271ae; } } +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { + color: #060; } + + .kwd { + color: #006; + font-weight: bold; } + + .com { + color: #600; + font-style: italic; } + + .typ { + color: #404; + font-weight: bold; } + + .lit { + color: #044; } + + .pun, .opn, .clo { + color: #440; } + + .tag { + color: #006; + font-weight: bold; } + + .atn { + color: #404; } + + .atv { + color: #060; } } +/* Style */ +/* +pre.prettyprint { + background: white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 12px; + line-height: 1.5; + border: 1px solid #ccc; + padding: 10px; } +*/ + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; } + +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + /* */ } + +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + /* */ } diff --git a/Ivette/src/dome/doc/template/tmpl/augments.tmpl b/Ivette/src/dome/doc/template/tmpl/augments.tmpl new file mode 100644 index 00000000000..605c384364b --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/augments.tmpl @@ -0,0 +1,25 @@ +<?js + var data = obj; + var self = this; + const href = /^\[(.+)\]\((.+)\) */; +?> + +<?js if (data.augments && data.augments.length) { ?> + <div class="summary"> + <table class="summary"> + <tbody> + <?js data.augments.forEach(function(a,descr) { + var m = href.exec(a) ; ?> + <tr> + <?js if (m) { ?> + <td><a href="<?js= m[2] ?>"><?js= m[1] ?></a></td> + <?js } else { ?> + <td><?js= a ?></td> + <?js } ?> + <td>Super Class Methods</td> + </tr> + <?js }) ?> + </tbody> + </table> + </div> +<?js } ?> diff --git a/Ivette/src/dome/doc/template/tmpl/container.tmpl b/Ivette/src/dome/doc/template/tmpl/container.tmpl new file mode 100644 index 00000000000..6d77d043120 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/container.tmpl @@ -0,0 +1,261 @@ +<?js + var self = this; + var isGlobalPage; + + docs.forEach(function(doc, i) { +?> + +<?js + // we only need to check this once + if (typeof isGlobalPage === 'undefined') { + isGlobalPage = (doc.kind === 'globalobj'); + } +?> +<?js if (doc.kind === 'mainpage' || (doc.kind === 'package')) { ?> + <?js= self.partial('mainpage.tmpl', doc) ?> +<?js } else if (doc.kind === 'source') { ?> + <?js= self.partial('source.tmpl', doc) ?> +<?js } else { ?> + +<section> + +<header> + <?js if (!doc.longname || doc.kind !== 'module') { ?> + <h2><?js if (doc.ancestors && doc.ancestors.length) { ?> + <span class="ancestors"><?js= doc.ancestors.join('') ?></span><?js + } + ?><?js= (doc.name && doc.name.startsWith('module:')) ? doc.name.substring(7): doc.name ?><?js + if (doc.variation) { ?> + <sup class="variation"><?js= doc.variation ?></sup> + <?js } ?></h2> + <?js if (doc.classdesc) { ?> + <div class="class-description"><?js= doc.classdesc ?></div> + <?js } ?> + <?js } else if (doc.kind === 'module' && doc.modules) { ?> + <?js doc.modules.forEach(function(module) { ?> + <?js if (module.classdesc) { ?> + <div class="class-description"><?js= module.classdesc ?></div> + <?js } ?> + <?js }) ?> + <?js } ?> +</header> + +<article> + <div class="container-overview"> + <?js if (doc.kind === 'module' && doc.modules) { ?> + <?js if (doc.description) { ?> + <div class="description"><?js= doc.description ?></div> + <?js } ?> + + <?js doc.modules.forEach(function(module) { ?> + <?js= self.partial('method.tmpl', module) ?> + <?js }) ?> + <?js } else if (doc.kind === 'class') { ?> + <?js= self.partial('method.tmpl', doc) ?> + <?js } else { ?> + <?js if (doc.description) { ?> + <div class="description"><?js= doc.description ?></div> + <?js } ?> + + <?js= self.partial('details.tmpl', doc) ?> + + <?js if (doc.examples && doc.examples.length) { ?> + <h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3> + <?js= self.partial('examples.tmpl', doc.examples) ?> + <?js } ?> + <?js } ?> + </div> + + <?js if (doc.augments && doc.augments.length) { ?> + <h3 class="subsection-title">Extends</h3> + + <?js= self.partial('augments.tmpl', doc) ?> + <?js } ?> + + <?js if (doc.requires && doc.requires.length) { ?> + <h3 class="subsection-title">Requires</h3> + + <ul><?js doc.requires.forEach(function(r) { ?> + <li><?js= self.linkto(r, r) ?></li> + <?js }); ?></ul> + <?js } ?> + + <?js + var classes = self.find({kind: 'class', memberof: doc.longname}); + if (!isGlobalPage && classes && classes.length) { + ?> + <h3 class="subsection-title">Classes</h3> + <div class="summary"> + <table class="summary"> + <?js classes.forEach(function(c) { ?> + <tr> + <td><?js= self.linkto(c.longname, c.name) ?></td> + <td><?js if (c.summary) { ?><?js= c.summary ?><?js } ?></td> + </tr> + <?js }); ?> + </table> + </div> + <?js } ?> + + <?js + var mixins = self.find({kind: 'mixin', memberof: doc.longname}); + if (!isGlobalPage && mixins && mixins.length) { + ?> + <h3 class="subsection-title">Mixins</h3> + + <dl><?js mixins.forEach(function(m) { ?> + <dt><?js= self.linkto(m.longname, m.name) ?></dt> + <dd><?js if (m.summary) { ?><?js= m.summary ?><?js } ?></dd> + <?js }); ?></dl> + <?js } ?> + + <?js + var namespaces = self.find({kind: 'namespace', memberof: doc.longname}); + if (!isGlobalPage && namespaces && namespaces.length) { + ?> + <h3 class="subsection-title">Namespaces</h3> + + <dl><?js namespaces.forEach(function(n) { ?> + <dt><?js= self.linkto(n.longname, n.name) ?></dt> + <dd><?js if (n.summary) { ?><?js= n.summary ?><?js } ?></dd> + <?js }); ?></dl> + <?js } ?> + + <?js + var members = self.find({kind: 'member', memberof: isGlobalPage ? {isUndefined: true} : doc.longname}); + var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname}); + + var hasMembers = members && members.length && members.forEach ; + var hasMethods = methods && methods.length && methods.forEach ; + + // symbols that are assigned to module.exports are not globals, even though they're not a memberof anything + if (isGlobalPage && hasMembers) { + members = members.filter(function(m) { + return m.longname && m.longname.indexOf('module:') !== 0; + }); + hasMembers = members && members.length && members.forEach ; + } + + var makeWarning = ( m , msg ) => { + let ident = m.longname + ':' ; + if (m.meta) { + let { path, filename, lineno } = m.meta ; + let root = process.env['DOME_PWD']; + let dir = root && path.startsWith(root) ? path.substring(root.length+1) : path ; + ident = dir + '/' + filename + ':' + lineno + ': (' + m.name + ')' ; + } + console.warn( ident, msg); + }; + + var makeSummary = (m) => { + if (m.summary) { + let s = m.summary.trim() ; + if ( s.startsWith('<p>') && s[3].toUpperCase() !== s[3] ) + makeWarning( m , "Not capitalized @summary" ); + if ( s.startsWith('<p>') && ! s.endsWith('.</p>') ) + makeWarning( m , "Missing @summary final '.'" ); + return s; + } + let descr = m.description ; + if (descr && typeof(descr)=='string' && descr.startsWith("<p>")) { + let pos = descr.indexOf("</p>"); + if (0 <= pos && pos < 60) return descr.substring(0,pos)+"</p>"; + } + makeWarning( m , "Missing @summary" ); + return '<span class="dimmed">(details below)</span>' ; + }; + + if ( hasMembers || hasMethods ) { + ?> + + <h3 class="subsection-title">Summary</h3> + <table class="list-index"> + <?js hasMembers && members.forEach(function(m) { ?> + <tr class="list-item"> + <td class="list-title"> + <a href="#<?js= m.id ?>"><code><?js= m.name ?></code></a> + </td> + <td class="list-descr"> + <?js= makeSummary(m) ?> + </tr> + <?js }); ?> + + <?js if (hasMethods && hasMembers) { ?> + <tr class="list-separator"> + <td class="list-title"/> + <td class="list-descr"/> + </tr> + <?js } ?> + + <?js hasMethods && methods.forEach(function(m) { ?> + <tr class="list-item"> + <td class="list-title"> + <a href="#<?js= m.id ?>"><code><?js= m.name ?>()</code></a> + </td> + <td class="list-descr"> + <?js= makeSummary(m) ?> + </td> + </tr> + <?js }); ?> + </table> + + <?js } ?> + + <?js + if (hasMembers) { + ?> + <h3 class="subsection-title">Members</h3> + + <?js members.forEach(function(p) { ?> + <?js= self.partial('members.tmpl', p) ?> + <?js }); ?> + <?js } ?> + + <?js + + if (hasMethods) { + ?> + + <h3 class="subsection-title">Methods</h3> + + <?js methods.forEach(function(m) { ?> + <?js= self.partial('method.tmpl', m) ?> + <?js }); ?> + <?js } ?> + + <?js + var typedefs = self.find({kind: 'typedef', memberof: isGlobalPage ? {isUndefined: true} : doc.longname}); + if (typedefs && typedefs.length && typedefs.forEach) { + ?> + <h3 class="subsection-title">Type Definitions</h3> + + <?js typedefs.forEach(function(e) { + if (e.signature) { + ?> + <?js= self.partial('method.tmpl', e) ?> + <?js + } + else { + ?> + <?js= self.partial('members.tmpl', e) ?> + <?js + } + }); ?> + <?js } ?> + + <?js + var events = self.find({kind: 'event', memberof: isGlobalPage ? {isUndefined: true} : doc.longname}); + if (events && events.length && events.forEach) { + ?> + <h3 class="subsection-title">Events</h3> + + <?js events.forEach(function(e) { ?> + <?js= self.partial('method.tmpl', e) ?> + <?js }); ?> + <?js } ?> +</article> + +</section> +<?js } ?> + +<?js }); ?> diff --git a/Ivette/src/dome/doc/template/tmpl/details.tmpl b/Ivette/src/dome/doc/template/tmpl/details.tmpl new file mode 100644 index 00000000000..3b1ee84c132 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/details.tmpl @@ -0,0 +1,143 @@ +<?js +var data = obj; +var self = this; +var defaultObjectClass = ''; + +// Check if the default value is an object or array; if so, apply code highlighting +if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvaluetype === 'array')) { + data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>"; + defaultObjectClass = ' class="object-value"'; +} +?> +<?js + var properties = data.properties; + if (properties && properties.length && properties.forEach) { +?> + + <h5 class="subsection-title">Properties</h5> + + <?js= this.partial('properties.tmpl', data) ?> + +<?js } ?> + +<dl class="details"> + + <?js if (data.version) {?> + <dt class="tag-version">Version:</dt> + <dd class="tag-version"><ul class="dummy"><li><?js= version ?></li></ul></dd> + <?js } ?> + + <?js if (data.since) {?> + <dt class="tag-since">Since:</dt> + <dd class="tag-since"><ul class="dummy"><li><?js= since ?></li></ul></dd> + <?js } ?> + + <?js if (data.inherited && data.inherits && !data.overrides) { ?> + <dt class="inherited-from">Inherited From:</dt> + <dd class="inherited-from"><ul class="dummy"><li> + <?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?> + </li></ul></dd> + <?js } ?> + + <?js if (data.overrides) { ?> + <dt class="tag-overrides">Overrides:</dt> + <dd class="tag-overrides"><ul class="dummy"><li> + <?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?> + </li></ul></dd> + <?js } ?> + + <?js if (data.implementations && data.implementations.length) { ?> + <dt class="implementations">Implementations:</dt> + <dd class="implementations"><ul> + <?js data.implementations.forEach(function(impl) { ?> + <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li> + <?js }); ?> + </ul></dd> + <?js } ?> + + <?js if (data.implements && data.implements.length) { ?> + <dt class="implements">Implements:</dt> + <dd class="implements"><ul> + <?js data.implements.forEach(function(impl) { ?> + <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li> + <?js }); ?> + </ul></dd> + <?js } ?> + + <?js if (data.mixes && data.mixes.length) { ?> + <dt class="mixes">Mixes In:</dt> + + <dd class="mixes"><ul> + <?js data.mixes.forEach(function(a) { ?> + <li><?js= self.linkto(a, a) ?></li> + <?js }); ?> + </ul></dd> + <?js } ?> + + <?js if (data.deprecated) { ?> + <dt class="important tag-deprecated">Deprecated:</dt><?js + if (data.deprecated === true) { ?><dd class="yes-def tag-deprecated"><ul class="dummy"><li>Yes</li></ul></dd><?js } + else { ?><dd><ul class="dummy"><li><?js= data.deprecated ?></li></ul></dd><?js } + ?> + <?js } ?> + + <?js if (data.author && author.length) {?> + <dt class="tag-author">Author:</dt> + <dd class="tag-author"> + <ul><?js author.forEach(function(a) { ?> + <li><?js= self.resolveAuthorLinks(a) ?></li> + <?js }); ?></ul> + </dd> + <?js } ?> + + <?js if (data.copyright) {?> + <dt class="tag-copyright">Copyright:</dt> + <dd class="tag-copyright"><ul class="dummy"><li><?js= copyright ?></li></ul></dd> + <?js } ?> + + <?js if (data.license) {?> + <dt class="tag-license">License:</dt> + <dd class="tag-license"><ul class="dummy"><li><?js= license ?></li></ul></dd> + <?js } ?> + + <?js if (data.defaultvalue) {?> + <dt class="tag-default">Default Value:</dt> + <dd class="tag-default"><ul class="dummy"> + <li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li> + </ul></dd> + <?js } ?> + + <?js if (data.meta && self.outputSourceFiles) {?> + <dt class="tag-source">Source:</dt> + <dd class="tag-source"><ul class="dummy"><li> + <?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?> + </li></ul></dd> + <?js } ?> + + <?js if (data.tutorials && data.tutorials.length) {?> + <dt class="tag-tutorial">Tutorial<?js= data.tutorials.length > 1 ? 's' : '' ?>:</dt> + <dd class="tag-tutorial"> + <ul><?js tutorials.forEach(function(t) { ?> + <li><?js= self.tutoriallink(t) ?></li> + <?js }); ?></ul> + </dd> + <?js } ?> + + <?js if (data.see && data.see.length) {?> + <dt class="tag-see">See:</dt> + <dd class="tag-see"> + <ul><?js see.forEach(function(s) { ?> + <li><?js= self.linkto(s) ?></li> + <?js }); ?></ul> + </dd> + <?js } ?> + + <?js if (data.todo && data.todo.length) {?> + <dt class="tag-todo">To Do:</dt> + <dd class="tag-todo"> + <ul><?js todo.forEach(function(t) { ?> + <li><?js= t ?></li> + <?js }); ?></ul> + </dd> + <?js } ?> +</dl> diff --git a/Ivette/src/dome/doc/template/tmpl/example.tmpl b/Ivette/src/dome/doc/template/tmpl/example.tmpl new file mode 100644 index 00000000000..e87caa5b72c --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/example.tmpl @@ -0,0 +1,2 @@ +<?js var data = obj; ?> +<pre><code><?js= data ?></code></pre> diff --git a/Ivette/src/dome/doc/template/tmpl/examples.tmpl b/Ivette/src/dome/doc/template/tmpl/examples.tmpl new file mode 100644 index 00000000000..04d975e96dc --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/examples.tmpl @@ -0,0 +1,13 @@ +<?js + var data = obj; + var self = this; + + data.forEach(function(example) { + if (example.caption) { + ?> + <p class="code-caption"><?js= example.caption ?></p> + <?js } ?> + <pre class="prettyprint"><code><?js= self.htmlsafe(example.code) ?></code></pre> +<?js + }); +?> \ No newline at end of file diff --git a/Ivette/src/dome/doc/template/tmpl/exceptions.tmpl b/Ivette/src/dome/doc/template/tmpl/exceptions.tmpl new file mode 100644 index 00000000000..9cef6c7d951 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/exceptions.tmpl @@ -0,0 +1,32 @@ +<?js + var data = obj; +?> +<?js if (data.description && data.type && data.type.names) { ?> +<dl> + <dt> + <div class="param-desc"> + <?js= data.description ?> + </div> + </dt> + <dd></dd> + <dt> + <dl> + <dt> + Type + </dt> + <dd> + <?js= this.partial('type.tmpl', data.type.names) ?> + </dd> + </dl> + </dt> + <dd></dd> +</dl> +<?js } else { ?> + <div class="param-desc"> + <?js if (data.description) { ?> + <?js= data.description ?> + <?js } else if (data.type && data.type.names) { ?> + <?js= this.partial('type.tmpl', data.type.names) ?> + <?js } ?> + </div> +<?js } ?> diff --git a/Ivette/src/dome/doc/template/tmpl/layout.tmpl b/Ivette/src/dome/doc/template/tmpl/layout.tmpl new file mode 100644 index 00000000000..39dbc7889cb --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/layout.tmpl @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title><?js= title ?></title> + + <script src="scripts/prettify/prettify.js"> </script> + <script src="scripts/prettify/lang-css.js"> </script> + <!--[if lt IE 9]> + <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> + <![endif]--> + <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> + <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> +</head> + +<body> + <div id="main"> + <div id="content"> + <div id="page"> + <h1 class="page-title"> + <?js=( + title.startsWith('Class: module:') ? 'Class ' + title.substring(14) : + title.startsWith('Class: ') ? 'Class ' + title.substring(7) : + title.startsWith('Event: ') ? 'Event ' + title.substring(7) : + title.startsWith('Module: ') ? 'Module ' + title.substring(8) : + title.startsWith('Tutorial: ') ? title.substring(10) + ' (tutorial)' : + title + )?> + </h1> + <?js= content ?> + <br class="clear"> + <footer> + Copyright (©) <?js= process.env.COPYRIGHT ?> <?js= (new Date()).getFullYear() ?> + </footer> + </div> + </div> + + <div id="index"> + <nav> + <?js= this.nav ?> + </nav> + </div> + + </div> +<script> prettyPrint(); </script> +<script src="scripts/linenumber.js"> </script> +</body> +</html> diff --git a/Ivette/src/dome/doc/template/tmpl/mainpage.tmpl b/Ivette/src/dome/doc/template/tmpl/mainpage.tmpl new file mode 100644 index 00000000000..64e9e5943a1 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/mainpage.tmpl @@ -0,0 +1,14 @@ +<?js +var data = obj; +var self = this; +?> + +<?js if (data.kind === 'package') { ?> + <h3><?js= data.name ?> <?js= data.version ?></h3> +<?js } ?> + +<?js if (data.readme) { ?> + <section> + <article><?js= data.readme ?></article> + </section> +<?js } ?> diff --git a/Ivette/src/dome/doc/template/tmpl/members.tmpl b/Ivette/src/dome/doc/template/tmpl/members.tmpl new file mode 100644 index 00000000000..66a2799d173 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/members.tmpl @@ -0,0 +1,40 @@ +<?js +var data = obj; +var self = this; +?> +<h4 class="name" id="<?js= id ?>"><?js= data.attribs + name + (data.signature ? data.signature : '') ?> +<a class="anchor" href="#<?js= id ?>">♯</a> +</h4> + +<?js if (data.summary) { ?> +<p class="summary"><?js= data.summary ?></p> +<?js } ?> + +<?js if (data.description) { ?> +<div class="description"> + <?js= data.description ?> +</div> +<?js } ?> + +<?js if (data.type && data.type.names) {?> + <h5>Type</h5> + <ul> + <li> + <?js= self.partial('type.tmpl', data.type.names) ?> + </li> + </ul> +<?js } ?> + +<?js= this.partial('details.tmpl', data) ?> + +<?js if (data.fires && fires.length) { ?> + <h5>Fires</h5> + <ul><?js fires.forEach(function(f) { ?> + <li><?js= self.linkto(f) ?></li> + <?js }); ?></ul> +<?js } ?> + +<?js if (data.examples && examples.length) { ?> + <h5>Example<?js= examples.length > 1? 's':'' ?></h5> + <?js= this.partial('examples.tmpl', examples) ?> +<?js } ?> diff --git a/Ivette/src/dome/doc/template/tmpl/method.tmpl b/Ivette/src/dome/doc/template/tmpl/method.tmpl new file mode 100644 index 00000000000..c29c67b7ccd --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/method.tmpl @@ -0,0 +1,103 @@ +<?js +var data = obj; +var self = this; +?> + +<?js if (data.kind !== 'module') { ?> + <?js if (data.kind === 'class' && data.classdesc) { ?> + <h2>Constructor</h2> + <?js } ?> + + <?js if (data.kind !== 'class') { ?> + <h4 class="name" id="<?js= id ?>"><?js= data.attribs + name + (data.signature || '') ?> + <a class="anchor" href="#<?js= id ?>">♯</a> + </h4> + <?js } ?> + + <?js if (data.summary) { if (data.kind === 'class') { ?> + <div class="summary"><p><?js= data.summary ?></p></div> + <?js } else { ?> + <p class="summary"><?js= data.summary ?></p> + <?js }} ?> +<?js } ?> + +<?js if (data.kind !== 'module' && data.description) { ?> +<div class="description"> + <?js= data.description ?> +</div> +<?js } ?> + +<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?> + <h5>Extends</h5> + <?js= self.partial('augments.tmpl', data) ?> +<?js } ?> + +<?js if (kind === 'event' && data.type && data.type.names) {?> + <h5>Type</h5> + <ul> + <li> + <?js= self.partial('type.tmpl', data.type.names) ?> + </li> + </ul> +<?js } ?> + +<?js if (data['this']) { ?> + <h5>This</h5> + <ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul> +<?js } ?> + +<?js if (data.params && params.length) { ?> + <h5>Parameters</h5> + <?js= this.partial('params.tmpl', params) ?> +<?js } ?> + +<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?> +<h5>Requires</h5> +<ul><?js data.requires.forEach(function(r) { ?> + <li><?js= self.linkto(r) ?></li> +<?js }); ?></ul> +<?js } ?> + +<?js if (data.fires && fires.length) { ?> +<h5>Fires</h5> +<ul><?js fires.forEach(function(f) { ?> + <li><?js= self.linkto(f) ?></li> +<?js }); ?></ul> +<?js } ?> + +<?js if (data.listens && listens.length) { ?> +<h5>Events</h5> +<ul><?js listens.forEach(function(f) { ?> + <li><?js= self.linkto(f) ?></li> +<?js }); ?></ul> +<?js } ?> + +<?js if (data.listeners && listeners.length) { ?> +<h5>Listeners</h5> +<ul><?js listeners.forEach(function(f) { ?> + <li><?js= self.linkto(f) ?></li> +<?js }); ?></ul> +<?js } ?> + +<?js if (data.exceptions && exceptions.length) { ?> +<h5>Throws</h5> +<?js if (exceptions.length > 1) { ?><ul><?js + exceptions.forEach(function(r) { ?> + <li><?js= self.partial('exceptions.tmpl', r) ?></li> + <?js }); +?></ul><?js } else { + exceptions.forEach(function(r) { ?> + <?js= self.partial('exceptions.tmpl', r) ?> + <?js }); +} } ?> + +<?js if (data.returns && returns.length) { ?> + <h5>Returns</h5> + <?js= this.partial('returns.tmpl',returns) ?><?js } ?> + +<?js if (data.examples && examples.length) { ?> + <h5>Example<?js= examples.length > 1? 's':'' ?></h5> + <?js= this.partial('examples.tmpl', examples) ?> +<?js } ?> + +<?js= this.partial('details.tmpl', data) ?> diff --git a/Ivette/src/dome/doc/template/tmpl/params.tmpl b/Ivette/src/dome/doc/template/tmpl/params.tmpl new file mode 100644 index 00000000000..000e36fb480 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/params.tmpl @@ -0,0 +1,76 @@ +<?js + var params = obj; + + /* sort subparams under their parent params (like opts.classname) */ + var parentParam = null; + params.forEach(function(param, i) { + var paramRegExp; + + if (!param) { + return; + } + + if (parentParam && parentParam.name && param.name) { + paramRegExp = new RegExp('^(?:' + parentParam.name + '(?:\\[\\])*)\\.(.+)$'); + + if ( paramRegExp.test(param.name) ) { + param.name = RegExp.$1; + parentParam.subparams = parentParam.subparams || []; + parentParam.subparams.push(param); + params[i] = null; + } + else { + parentParam = param; + } + } + else { + parentParam = param; + } + }); + +?> + +<table class="params"> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th class="last">Description</th> + </tr> + </thead> + + <tbody> + <?js + var self = this; + const displayParam = (param,indent=0) => { + if (!param) { return; } + ?> + + <tr> + <td class="name"> + <code> + <?js for( var k = 0; k < indent; k++) { ?> + + <?js } ?> + <?js= (indent ? '.' : '') + param.name + (param.variable ? '...' : '') ?> + </code> + </td> + <td class="type"> + <?js if (param.type && param.type.names) {?> + <?js= self.partial('type.tmpl', param.type.names) ?> + <?js if (param.optional) { ?> + (opt.) + <?js } ?> + <?js } ?> + </td> + <td class="description last"> + <?js= param.description ?> + </td> + </tr> + <?js if (param.subparams) param.subparams.forEach((p) => displayParam(p,indent+1)); ?> + <?js + }; + params.forEach( (p) => displayParam(p) ); + ?> + </tbody> +</table> diff --git a/Ivette/src/dome/doc/template/tmpl/properties.tmpl b/Ivette/src/dome/doc/template/tmpl/properties.tmpl new file mode 100644 index 00000000000..4c73e65805e --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/properties.tmpl @@ -0,0 +1,75 @@ +<?js + var data = obj; + var props = data.subprops || data.properties; + + /* sort subprops under their parent props (like opts.classname) */ + var parentProp = null; + props.forEach(function(prop, i) { + if (!prop) { return; } + if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) { + prop.name = prop.name.substr(parentProp.name.length+1); + parentProp.subprops = parentProp.subprops || []; + parentProp.subprops.push(prop); + props[i] = null; + } + else { + parentProp = prop; + } + }); +?> + +<table class="props"> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th class="last">Description</th> + </tr> + </thead> + + <tbody> + <?js + var self = this; + const displayProp = (prop,indent=0) => { + if (!prop) { return; } + ?> + + <tr> + <td class="name"> + <code> + <?js for( var k = 0; k < indent; k++) { ?> + + <?js } ?> + <?js= (indent ? '.' : '') + prop.name ?> + </code> + </td> + <td class="type"> + <?js if (prop.type && prop.type.names) {?> + <?js= self.partial('type.tmpl', prop.type.names) ?> + <?js if (prop.optional) { ?> + (opt.) + <?js } ?> + <?js } ?> + </td> + <td class="description last"> + <?js= prop.description ?> + </td> + </tr> + <?js if (prop.subprops) prop.subprops.forEach((p) => displayProp(p,indent+1)); ?> + + <?js + }; + props.forEach( (p) => displayProp(p) ); + ?> + <?js if (data.augments && data.augments.length) data.augments.forEach((a) => { + const href = /^\[(.+)\]\((.+)\) */; + const m = href.exec(a); + if (m) { ?> + <tr> + <td><tt>...</tt></td> + <td><a href="<?js= m[2] ?>"><?js= m[1] ?></a></td> + <td>Super Class Properties</td> + </tr> + <?js }})?> + </tbody> +</table> diff --git a/Ivette/src/dome/doc/template/tmpl/returns.tmpl b/Ivette/src/dome/doc/template/tmpl/returns.tmpl new file mode 100644 index 00000000000..0f24cbdb24a --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/returns.tmpl @@ -0,0 +1,25 @@ +<?js var returns = obj; const self = this; ?> + +<table class="params"> + <thead> + <tr> + <th>Type</th> + <th class="last">Description</th> + </tr> + </thead> + <tbody> +<?js returns.forEach(function (r) { ?> + + <tr> + <td class="type"> + <?js if (r.type && r.type.names) { ?> + <?js= self.partial('type.tmpl', r.type.names) ?> + <?js } ?> + </td> + <td class="description last"> + <?js= r.description ?> + </td> + +<?js }); ?> + </tbody> +</table> diff --git a/Ivette/src/dome/doc/template/tmpl/source.tmpl b/Ivette/src/dome/doc/template/tmpl/source.tmpl new file mode 100644 index 00000000000..e559b5d1038 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/source.tmpl @@ -0,0 +1,8 @@ +<?js + var data = obj; +?> + <section> + <article> + <pre class="prettyprint source linenums"><code><?js= data.code ?></code></pre> + </article> + </section> \ No newline at end of file diff --git a/Ivette/src/dome/doc/template/tmpl/tutorial.tmpl b/Ivette/src/dome/doc/template/tmpl/tutorial.tmpl new file mode 100644 index 00000000000..88a0ad52aa2 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/tutorial.tmpl @@ -0,0 +1,19 @@ +<section> + +<header> + <?js if (children.length > 0) { ?> + <ul><?js + var self = this; + children.forEach(function(t) { ?> + <li><?js= self.tutoriallink(t.name) ?></li> + <?js }); ?></ul> + <?js } ?> + + <h2><?js= header ?></h2> +</header> + +<article> + <?js= content ?> +</article> + +</section> diff --git a/Ivette/src/dome/doc/template/tmpl/type.tmpl b/Ivette/src/dome/doc/template/tmpl/type.tmpl new file mode 100644 index 00000000000..ec2c6c0df72 --- /dev/null +++ b/Ivette/src/dome/doc/template/tmpl/type.tmpl @@ -0,0 +1,7 @@ +<?js + var data = obj; + var self = this; + data.forEach(function(name, i) { ?> +<span class="param-type"><?js= self.linkto(name, self.htmlsafe(name)) ?></span> +<?js if (i < data.length-1) { ?>|<?js } ?> +<?js }); ?> \ No newline at end of file diff --git a/Ivette/src/dome/doc/tutorials/application.md b/Ivette/src/dome/doc/tutorials/application.md new file mode 100644 index 00000000000..ec13570b915 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/application.md @@ -0,0 +1,119 @@ +<!-- Application Design --> + +This tutorial introduces how to design a **Dome** application within the +**Electron** & **React** frameworks. You shall be reasonably familiar with +**React** concepts, but no knowledge of **Electron** is required. + +A desktop **Dome** application looks like a native application, but is actually +a static web page rendered in a **Chrome** web browser. This is what provides +the **Electron** framework by default. **Dome** is simply a library of **React** +components and development templates tuned together to enable professional +application development. + +This tutorial provides an overview of this environment and how to design a typical +**Dome** application. + +## System Architecture + +Following the **Electron** framework design, your application will consists of +two different processes interacting with each others. +One is responsible for the management of the main GUI resources +(windows, menu-bar, desktop interaction, user settings, etc.) +and is named the `Main` process. +The second one will be responsible for running the +web page holding the main application window, and is named the `Renderer` process. +Both kind of process communicates through the message-passing API provided by +the **Electron** framework. + +When several instances of your application are running simultaneously, each invokation +have its own window, running its owan, separate `Renderer` process. However, the +**Dome** framework automatically makes them sharing the same `Main` process. + +Hence, each application instance has its own working directory and command-line arguments, +depending on how its has been launched by the user. The **Dome** framework build +both command-line and desktop entry points, depending on each target platform. + +## Event Driven Design + +On the renderer process side, the **React** framework induces a natural design where +_Application State_ is separated from _Application Rendering_. Moreover, +following a popular design introduced with **Redux**, application rendering tend +to be written like a pure function (or _view_) on the state, where user +actions are just state updater callbacks. Each time the state is modified, the +entire application rendering is recomputed, and **React** computes a minimal +diff to apply on the web page displayed in the main application window. + +Putting everything together, its is recommended to design **Dome** application +into two different parts, both running in the `Renderer` process of each +application instance: + +- **Application Internals (State)** +holding your application state and data and updating it in response to user or +system events; + +- **Application Components (View)** +responsible for rendering the application main window and +binding callbacks to application services. + +<img src="dataflow.png" style="float: right; width: 30em"/> + +Such an architecture is typical of a _Model-View-Controller_ design, but +revisited to scale. In particular, data flow between those three different +layers shall follow a unique-direction pattern in order to avoid the +combinatorial explosion of interactions between components that is generally +observed in most Model-View-Controller designs. + +Hence, data-flow shall follow one of the following routes between these +three layers, illustrated above: + +- from `State` to `View` : your rendering components shall only access the +current application state and data; +- from `View` to `State` or `System` : user action callbacks shall only trigger +state update or system operation, not any other view direct modification. +- from `System` to `State` : upon completion, system services shall trigger state +updates that would in turn trigger new requests and view re-rendering. + +## Data Management + +To implement the recommended data-flow described above, you may use a full +featured [Redux](https://redux.js.org) platform or any other framework of your +choice. However, **Dome** provides you with many facilities for implementing +your data flow. + +- **Global States** are necessary to implement the unidirectional data-flow. These + data are stored in the renderer process, but outside of the view hierarchy of + **React** components actually mounted in the DOM. Hence, it remains consistent whatever + the evolution of the view. See `Dome.State` class and the associated custom **React** hooks + to implement global states. You may also use global JavaScript variables and emit events + on your own. + +- **Local States** are necessary to maintain local states associated + to views. We strongly encourage the use of the `Dome.useState()` hook for this + purpose, since it generalizes `React.useState()` with persistent window settings + (see below). + +- **View Updates** to make your views listening for updates of the various data + sources, we encourage to use the **React** hooks we provide, since they + transparently make your components to re-render when required. However, + sometimes you will need to respond to special events by hand. For this purpose, + you can use **Dome** as a central event emitter, by using `Dome.emit()`, + `Dome.on()` and `Dome.off()` functions. Moreover, the `Dome.useUpdate()` and + `Dome.useEvent()` hooks can be used to make your components being notified by + events. + +- **Window Settings** are stored in the user's home directory but remain + generally unnoticed by most users, although they are responsible for a good user + experience. They typically include the window's position and dimension, + resizable items position, fold/unfold states, presentation options, etc. Most + **Dome** components with presentation options can be assigned a `settings` key + to make their state persistent. Contrary to Global Settings, however, they are + not shared across several windows. You may also access these data by using + `Dome.setWindowSetting()` and `Dome.getWindowSetting()`, or the **React** hook + `Dome.useWindowSetting()`. + +- **Global Settings** are stored in the user's home directory and automatically + saved and load with your application; they are typically modified _via_ the + Settings Window, which is accessible from the application menubar. In **Dome**, + you access these data by using `Dome.setGlobalSetting()` and + `Dome.getGlobalSetting()`, or the **React** hook `Dome.useGlobalSetting()`. + Settings must be JSON serializable JavaScript values. diff --git a/Ivette/src/dome/doc/tutorials/dataflow.png b/Ivette/src/dome/doc/tutorials/dataflow.png new file mode 100644 index 0000000000000000000000000000000000000000..648a290cadfa3d89ffe5861b76076ab18edfeac1 GIT binary patch literal 48365 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묮L5NAiGO+wMGSWRK3|tbz*mQL-(a&_1 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 literal 0 HcmV?d00001 diff --git a/Ivette/src/dome/doc/tutorials/development.md b/Ivette/src/dome/doc/tutorials/development.md new file mode 100644 index 00000000000..7a10355c137 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/development.md @@ -0,0 +1,204 @@ +<!-- Application Development --> + +The [Quick Start](tutorial-quickstart.html) tutorial introduces how to setup a new application project, +and [Application Design](tutorial-application.html) draw a high-level view of how it works. +This tutorial goes into more details about the development environment provided by the **Dome** +framework. + + +## HTML & JavaScript Environment + +The Web environment for designing your application is based on the following +framework: + +- **Electron** [v5.0+](https://electronjs.org) runtime environment (packaging Chrome and Node) +- **Node** [v12.0+](https://nodejs.org/dist/latest-v12.x/docs/api) provided by Electron +- **Chromium** [v73.0+](https://www.chromium.org/Home) HTML rendering engine provided by Electron + +You will write your application in a an environment setup with the following +JavaScript features: + +- **Webpack** for packaging the application from sources +- **Babel** to parse language extensions +- **Babel Presets Env** to use ECMA modules and JavaScript strict mode +- **Babel Presets React** to use JSX react notation in all your `*.js` files +- **Babel Object Rest Spread** to use object spread syntax `{ ...props }` +- **React v16** with its latest features (including Hooks) +- **React Hot Loader** for [live-editing](tutorial-hotreload.html) your application +- **CSS Loader** to load and install `*.css` files + +## Available Packages + +The implementation and internals of the **Dome** framework rely on +high-quality and mature popular packages. They are automatically packed +into your dependencies by the provided template makefile. We list them here +since you may re-use them for your own purpose: + +- [**Lodash**](https://lodash.com) convenient JavaScript utilities +- [**React-Virtualized**](http://bvaughn.github.io/react-virtualized) +for layout of large data set in list, tables and grids +- [**React-Draggable**](https://github.com/mzabriskie/react-draggable) +for straightforward drag-and-drop features +- [**CodeMirror**](https://codemirror.net) for rich text capabilities and edition +that scales on large document +- [**ZeroMQ**](http://zeromq.org) for inter-process and distant communications +(see also [System Services](tutorial-services.html)). + + +## Project Files Organization + +The main directory holding your application project with **Dome** consists of +several files and directories. Each is created and/or managed by various +entities : yourself the **Developer**, the **Dome** template makefile, the +**Yarn** JavaScript package manager and the **Electron** suite of +utilities. Parts of those files are generated and updated on demand and shall or +shall _not_ be tracked in your source version control system, be it based on `git`, +`svn` or anything else. + +Most files are actually created and used by **Dome**, **Electron** and **Yarn**. +However, that are _in fine_ under the responsibility of the **Developer** +since you can edit and extend them to fit your needs. +Those generated files generally contains comments to indicate how you +can extend them. You shall put those files under version control only if you edit them. + +As depicted in the [Quick Start](tutorial-quickstart.html) tutorial, the only file you +need to create by yourself is the main `Makefile`, with a minimal content +limited to: + +```makefile +DOME="..." ;; path to your dome installation +include $(DOME)/template/makefile +``` + +The following table lists the main files and directories of your project, with +the associated entity responsible for it, and whether they should be tracked by +your source version control system (VCS). + +Optional files are tagged with « (Opt.) » in the corresponding `Entity` column, +and are _not_ generated by default. Similarly, files mainly used by the system +but that can still be configured by the developer are tagged with « (+Dev) ». +Files are tagged with « ✓(*) » in the `VCS` column shall be tracked only if you +actually modified them. + +| File or Directory | Description | Entity | VCS | +|:------------------|:------------|:-------:|:---:| +| `./Makefile` | Drives the build system | **Developer** | ✓ | +| `./src/main/` | Sources for the main process | **Developer** | ✓ | +| `./src/main/index.js` | Main process entry point | **Electron** (+Dev) | ✓ | +| `./src/renderer/` | Sources for the renderer process | **Developer** | ✓ | +| `./src/renderer/index.js` | Renderer process entry point | **Electron** (+Dev) | ✓ | +| `./src/renderer/Application.js` | Top React component of the main application window | **Developer** | ✓ | +| `./src/renderer/Preferences.js` | Top React component of the user preferences window | **Developer** | ✓ | +| `./src/common/` | Sources for _both_ processes | **Developer** (Opt.) | ✓ | +| `./static/` | Static resources | **Developer** (Opt.) | ✓ | +| `./package.json` | JavaScript packages configuration | **Yarn** (+Dev) | ✓ | +| `./node_modules` | Downloaded packages | **Yarn** | ð„‚ | +| `./yarn.lock` | Packages versions stamps | **Yarn** | ✓ | +| `./electron-webpack.json` | Electron configuration | **Electron** (+Dev) | ✓(*) | +| `./babelrc` | Babel configuration | **Electron** (+Dev) | ✓(*) | +| `./webpack.main.json` | Webpack main process config. | **Electron** (+Dev) | ✓(*) | +| `./webpack.renderer.json` | Webpack renderer process config. | **Electron** (+Dev) | ✓(*) | +| `./.dome-*` | Dome makefile stamps | **Dome** | ð„‚ | +| `$(DOME)/*` | Dome framework clone | **Dome** | (var.) | +| `./dist/` | Packaged application | **Dome** | ð„‚ | +| `./bin/` | Local command-lines | **Dome** | ð„‚ | + +The main entry points of the two **Electron** processes running your application, +`src/main/index.js` and `src/renderer/index.js` shall be modified with extreme care, +since they are in charge with the correct bootstrap of your application. +The generated files from **Dome** templates contains explicit comments and guidelines. + +You may want to modify the name of your application top-level **React** components, +namely `src/renderer/Application.js` and `src/render/Preferences.js` by default. +To do this, you shall hook into the +`src/renderer/index.js` file and follow the provided comments and guidelines, +and set the `DOME_CUSTOM_ENTRIES` variable into your own `./Makefile` to make +**Dome** aware about this. + +If you need static resource files to be packed with your application, put them in the `static` directory. +You can then access to their actual path from your code by using the `System.getStatic(<path>)` utility function. + +The location of the **Dome** resources actually depends on the developer +profile, as explained in more detailed in the [Live Editing](tutorial-hotreload.html) tutorial. +To summarize: +- for normal developers, it can be a local copy of the dome framework, for instance in your `/usr/local/lib/dome` directory; +- for developers working with a specific or modified version of the dome framework, it can be in the local +`./dome/` directory of your project, with or without versioning control; +- for **Dome** developers, it is also possible to clone the Git repository inside the `./src/dome/` sub-directory of your +project, hence also enabling live-editing of **Dome** itself; +- for **Dome** maintainers, it is even possible to use the root of the **Dome** development repository as an application project +in itself, for demos, examples or testing purposes. + +Most of the **Electron** configuration files depends on the definition of the +`DOME` environment variable to find the necessary resources for your application +during development. Commands initiated by **Dome** from `$(DOME)/template/makefile` +will explicitly copy the `$(DOME)` makefile variable into the `$DOME` shell environment +variable when calling the **Electron** builder utilities, and might use it to generate static +files from templates, if necessary. + +If you ever _move_ the place where **Dome** is installed, you +probably have to inspect the generated files that you have modified to check +if they still behave as expected. + +Notice, however, that distributed versions of +the application (those accessible from the `./dist/` directory) are +self-contained: they are _not_ tied to your local installation of **Dome**. + +The command-line version of the application is accessible to the developer from the `./bin` directory. + +# Common Development Tasks + +Most development tasks shall be accessible from your `./Makefile`, and simply delegate to the +predefined **Dome** targets in `$(DOME)/template/makefile` ; however, for very specific needs, +you can borrow the content of the template makefile into your own one and modify it at your +convenience. The **Dome** environment will not target this template makefile explicitly. + +The top target of the **Dome** template makefile is `make dome-help`, +which is thus activated by default unless you put your own targets _before_ +its inclusion. The `dome-help` target simply echoes a short list of all the +`dome-xxx` predefined targets in the template. It also reports on +actual values of makefile variables used by the template. + +``` +$ make dome-help + +[Dome] Builtin Targets: + make dome-help This help + make dome-dev Run application in development mode + make dome-app Compile application + make dome-dist Package application for production + make dome-doc Generate Dome documentation + make dome-api Generate Application documentation + make dome-pkg Install development packages + make dome-templ Update templates + make dome-reboot Rebuild templates from scratch + make dome-clean Remove dome temporary files + make dome-plugins Package plugins for distribution + +[Dome] Development Variables: + Dome framework DOME = '…' + Arguments (dev) DOME_ARGS = '' + Export modules DOME_EXPORTS = '…' + Plugin modules DOME_PLUGINS = '…' + Local (./bin/) DOME_APP_CLI = '…' + +[Dome] Documentation Variables: + Application APP = '…' + Copyright COPYRIGHT = '…' + Dome framework DOME_DOC = '…' + App. framework DOME_APP_DOC = '…' + App. Sources DOME_APP_SRC = '…' + +``` + +As depicted above, the **Dome** template also provides two extensible targets `help::` and `clean::`. +By default, the `make clean` would only remove the **Dome** stamp files, not the actually generated files, +since they can have been modified when developing the application. This can cause, however, an _update_ of +configuration files that can be managed incrementally, typically for the `package.json` and the installed +JavaScript packages. + +The **Dome** framework can generate its own documentation locally, hence you may consult it offline. It +is also capable of generating internal **JSDoc** documentation of the application itself. The application +documentation does _not_ contain the framework documentation, though. + +The environment variable can be redefined _via_ your own Makefile before the **Dome** template inclusion. diff --git a/Ivette/src/dome/doc/tutorials/glossary.md b/Ivette/src/dome/doc/tutorials/glossary.md new file mode 100644 index 00000000000..b8f8e0e09a6 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/glossary.md @@ -0,0 +1,30 @@ +<!-- Glossary --> + +## Basic Concepts + +- **Component** a React Component definition (class of function) +- **Element** a React Component instance of a Component, typically `<Component ...>` +- **Elements** a fragment of any number of elements, typically the `children` properties of elements +- **Render Prop** a function returning element(s), typically used instead of children elements + +## Component Properties + +- `id` an element identifier +- `icon` an icon identifier, as listed in the [gallery](gallery-icons.html) +- `label` a short text used as the displayed title of a component +- `text` textual content to be printed on screen +- `title` a description for a component, usually provided in a tooltip box +- `settings` a key for making local state(s) persistent in user's settings +- `value` the value associated to some basic control (see `onChange`) +- `state` an object holding some current state (see `onUpdate`) +- `default` identifies the element selected by default in a list +- `selected` whether an element is selected or not (never by default) +- `disabled` whether an element will not responds to user actions (never by default) +- `selection` the identifier or value of current selection, or `undefined` (see `onSelect`) +- `children` the children elements of a component instance +- `onClick` a callback function in response to a click event +- `onClose` a callback function in response to closing action +- `onChange` a callback function in response to value changes (see `value`) +- `onUpdate` a callback function in response to (partial) state updates (see `state`) +- `onSelection` a callback function in response to user selection (see `selection`) +- `style` an inlined CSS style object to inject in a DOM element diff --git a/Ivette/src/dome/doc/tutorials/hooks.md b/Ivette/src/dome/doc/tutorials/hooks.md new file mode 100644 index 00000000000..bf65a102d52 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/hooks.md @@ -0,0 +1,18 @@ +<!-- Dome React Hooks ---> + +The **Dome** framework provides several [React Hooks](https://reactjs.org/docs/hooks-intro.html) +to ease your developpement process. Here is a summary of them. + +- [`useUpdate(evt)`](dome_.html#.useUpdate) to trigger re-rendering on **Dome** events; +- [`useEvent(emitter,event,callback)`](dome_.html#.useEvent) to trigger callbacks on events; +- [`useForceUpdate()`](dome_.html#.useForceUpdate) to trigger re-rendering on demand; +- [`useState(settings,defaultValue)`](dome_.html#.useState) + similar to `React.useState()` with optional persistent _window_ settings; +- [`useSwitch(settings,defaultValue)`](dome_.html#.useSwitch) + similar to `React.useState()` for boolean values with _window_ settings; +- [`useGlobalSetting(settings,defaultValue)`](dome_.html#.useGlobalSetting) + similar to `React.useState()` with optional persistent _global_ settings; +- [`useClock(period,initStart)`](dome_.html#.useClock) +returns start/stop clocks synchronized on period. +- [`useCommand()`](dome_.html#.useCommand) for working with different application instances. +- See also the [`Dome.State`](dome(renderer).State.html) and the associated hooks. diff --git a/Ivette/src/dome/doc/tutorials/hotreload.md b/Ivette/src/dome/doc/tutorials/hotreload.md new file mode 100644 index 00000000000..283ae63281c --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/hotreload.md @@ -0,0 +1,45 @@ +<!-- Live Code Editing --> + +The **Dome** framework comes with live-editing facilities, provided by a +combination of +[Webpack Hot Module Reloading](https://webpack.js.org/concepts/hot-module-replacement) +and [React Hot Loader](http://gaearon.github.io/react-hot-loader). +This allows you to live edit your code and style sheets in real time while application +is running. This feature is only enabled in development mode, not in production mode +used when packaging the application for some platform. + +Hot reloading for **React** components is known to be a fragile feature and to +suffer from certain limitations. Typically, files that can trigger live updates +must be reachable from the `./src` directory, without traversing symbolic links. +Style sheets in `*.css` files can be live edited, and **React** components in +`*.js` files as well. Most **React** components can be live-edited, provided +they are defined in top-level variables or exported by modules. Generally, the +component states are preserved during live-editing. + +For live-editing to work properly, your source code must follow strict +configuration settings. These rules are enforced when using configuration files +and application entry points generated from **Dome** templates. Pay attention to +the provided comments in generated files when modifying them. + +By default, we suggest to install the **Dome** framework in the sub-directory `./dome` +of your project. Being outside `./src`, this normally prevents **Dome** files to +be live-edited. If you want to also live-edit the framework, you shall move the +`$(DOME)` directory inside your own `./src`. +In particular, you might install the framework with `DOME=src/dome` for instance. + +**State Management:** hot-reloading on **React** components preserves application +states _only_ when they are stored outside the reloaded module. This is the case +for local states maintained in **React** components, as they live in the virtual DOM. +However, for global application state stored in global variables of modules, +they simply vanish when a module is hot-reloaded. Worst, the virtual DOM will +be still bound to the _old_ versions of the modules. However, you usually don't +want to live-edit the global state of your application and mix new data with +old ones. A good practice is to separate files holding global state from files +implementing views. Hence, live-editing the views will not cause the global state +modules to reload, and views will stay in sync with your data. If you ever modify +the global state, you will have to reload the application window (`CmdOrCtrl-R`). + +**Versioning Note:** the framework currently sticks on `webpack` version 3 and +`react-hot-loader` version 3, because of limitations and issues when using +`electron-webpack` with most recent versions of those libraries. However, we +hope to be able to migrate to newer versions as soon as possible. diff --git a/Ivette/src/dome/doc/tutorials/index.json b/Ivette/src/dome/doc/tutorials/index.json new file mode 100644 index 00000000000..991424831e0 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/index.json @@ -0,0 +1,9 @@ +{ + "quickstart": { "order": 1, "title": "Quick Start" }, + "application": { "order": 2, "title": "Application Design" }, + "development": { "order": 3, "title": "Application Development" }, + "hooks": { "order": 4, "title": "Custom React Hooks" }, + "hotreload": { "order": 5, "title": "Live Editing" }, + "styling": { "order": 7, "title": "Styling Components" }, + "glossary": { "order": 8, "title": "Glossary" } +} diff --git a/Ivette/src/dome/doc/tutorials/quickstart.md b/Ivette/src/dome/doc/tutorials/quickstart.md new file mode 100644 index 00000000000..44d9925fdd1 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/quickstart.md @@ -0,0 +1,26 @@ +<!-- -------------------------------------------------------------------------- --> +<!-- --- Quick Start --- --> +<!-- -------------------------------------------------------------------------- --> + +We strongly recommand to use [**Yarn**](https://reactjs.org) +for installing the necessary Node packages and their dependencies. + +Then, prepare a directory for developing your application, and download +the Dome Application Framework into sub-directory `dome`. +You shall now setup a makefile for your application as follows: + +<pre> + # Makefile + include dome/template/makefile + all: dome-dev +</pre> + +Now, simply type `make` and all the necessary packages will be automatically +installed and configured. This can take a while for the very first installation. +You will be prompted for generating a default `package.json` file +if you do not have some already. + +Eventually, your application will start with +a « _Hello World_ » window. +Now, you can _live edit_ the generated `src/renderer/Application.js` which is the main entry point +of your application and see what happens into the main window. diff --git a/Ivette/src/dome/doc/tutorials/styling.md b/Ivette/src/dome/doc/tutorials/styling.md new file mode 100644 index 00000000000..9074a9373f0 --- /dev/null +++ b/Ivette/src/dome/doc/tutorials/styling.md @@ -0,0 +1,63 @@ +<!-- Styling Components --> + +This tutorial explains how **Dome** style sheets are organized and how +to reuse them for styling your own components. Although modern styling +usually rely on _style preprocessors_ to leverage the complexity of +CSS style sheets development, the approach used here is based on separation +of concerns and multi-class styling. The advantage is that you can +develop your _own_ style sheets, while still being able +to re-use the existing classes provided by the framework. + +All CSS classes provided by **Dome** start with prefix `dome-` ; you shall not +use such a prefix when designing your own classes. Many class names are provided +with optional or mandatory variants. Typically: + +- `dome-<base>[-<a>,<b>,...]` describes class `dome-<base>` and its variants +`dome-<base>-<a>`, `dome-<base>-<b>` _etc_. + +- `dome-<name>-[<a>,<b>,...]` describes classes `dome-<name>-<a>`, `dome-<name>-<b>` _etc_. + +## Platform Context + +These classes can be used when writing selectors in order to style things +with respect to the target platform. The main window container is attributed +with one of the following class: + +- `dome-platform-[darwin,linux,windows]` derived from the `process.darwin` +global variable (**Node.js** environment). + +- `dome-window-[active|inactive]` depending on whether the main application window +has focus or not. + +## Color Palettes + +Attributing colors to graphical elements is often an issue, since a precise +hex variants shall be tuned depending on the surrounding context. However, +base colors are provided in public classes for several usages: + +- `dome-color-frame` background, foreground and borders for +window frames, which includes tool-bars, status-bars, tabs and such. +Those colors actually depend on the focus state of the main application window. + +- `dome-color-[dragzone|dragging]` for painting the background of a dragging +zone, typically a splitting rule. The `dragzone` variant is completely +transparent with a very transparent light gray when hovered. +The `dragging` variant is semi-transparent blended blue with light gray. +All these drag background effects are smoothly transitioned. + +## Text Properties + +- `dome-text-[label|title|descr]` for labels (_eg._ buttons, tabs, menu +entries), titles (larger labels) and descriptions (_eg._ tooltips). +Uses a sans-serif font, is non-selectable and truncated with an ellipsis. + +- `dome-text-[data|code]` for selectable text, typically input fields. +Uses a sans-serif font (for `data`) or monospace font (for `code`), +never wraps and is clipped when overflow. + +## Component Layout + +The entire application uses the `box-model` box-sizing property by default, +since it is usually much more consistent with nested `<div>` components. +Similarly, default margins and paddings are set to `0px` to avoid unwanted +messy background issues. diff --git a/Ivette/src/dome/src/main/dome.js b/Ivette/src/dome/src/main/dome.js new file mode 100644 index 00000000000..872f371a2c6 --- /dev/null +++ b/Ivette/src/dome/src/main/dome.js @@ -0,0 +1,506 @@ +/** + @module dome(main) + @description + + ## Dome Application (Main Process) + + This module manages the electron main-process of the application. + Your application will launch on `Dome.start()`: + + @example + // src/main/index.js: + import Dome from 'dome' ; + Dome.start(); +*/ + +import { + app, + ipcMain, + BrowserWindow +} from 'electron' ; + +import _ from 'lodash' ; +import fs from 'fs' ; +import path from 'path' ; +import Menubar from './menubar.js' ; +import System from 'dome/system' ; +import installExtension , { REACT_DEVELOPER_TOOLS } from 'dome/devtools' ; + +// -------------------------------------------------------------------------- +// --- System Helpers +// -------------------------------------------------------------------------- + +function fstat(path) { + try { + return fs.statSync(path); + } catch(_error) { + return undefined; + } +} + +// -------------------------------------------------------------------------- +// --- Helpers +// -------------------------------------------------------------------------- + +const LOCAL = process.env.DOME_LOCAL ; + +/** Development mode flag */ +export const DEVEL = System.DEVEL ; + +/** System platform */ +export const platform = System.platform ; + +// -------------------------------------------------------------------------- +// --- Settings +// -------------------------------------------------------------------------- + +const APP_DIR = app.getPath('userData'); +const APP_SETTINGS = path.join( APP_DIR , 'Settings.json' ); + +var s_frames = {} ; +var s_globals = {} ; +var s_application = {} ; +var s_preferences = {} ; + +function loadSettings() { + try { + if (!fstat( APP_SETTINGS )) return; + const content = fs.readFileSync( APP_SETTINGS, { encoding: 'utf8' } ); + const loaded = JSON.parse( content ); + const MERGE = (store,field) => _.merge( store , _.get( loaded , field )); + s_frames = MERGE( s_frames , 'frames' ); + s_globals = MERGE( s_globals, 'globals' ); + s_application = MERGE( s_application, 'application' ); + s_preferences = MERGE( s_application, 'preferences' ); + } catch(err) { + console.error("[Dome] Can not load application settings\n" + err); + } +} + +function saveSettings() { + try { + if (!fstat( APP_DIR )) fs.mkdirSync( APP_DIR ); + const saved = { + globals: s_globals, + application: s_application, + preferences: s_preferences, + frames: s_frames + }; + const content = JSON.stringify( saved, undefined, DEVEL ? 2 : 0 ); + fs.writeFileSync( APP_SETTINGS, content, { encoding: 'utf8' }, errorSettings ); + } catch(err) { + errorSettings(err); + } +} + +const fireSaveSettings = _.debounce( saveSettings , 50 ); + +function errorSettings(err) { + if (err) console.error("[Dome] Can not save application settings\n" + err); +} + +function remoteSyncSettings(event) +{ + const isSetting = windowSettings && windowSettings.id === event.frameId ; + event.returnValue = { + globals: s_globals, + settings: isSetting ? s_preferences : s_application + }; +} + +function remoteSaveWindowSettings(event,patches) +{ + const isSetting = windowSettings && windowSettings.id === event.frameId ; + _.merge( isSetting ? s_preferences : s_application , patches ); + saveSettings(); +} + +function remoteSaveGlobalSettings(event,patches) +{ + _.merge( s_globals , patches ); + saveSettings(); + BrowserWindow.getAllWindows().forEach((win) => { + if (win.id !== event.frameId) + win.send('dome.ipc.settings.update',patches); + }); +} + +ipcMain.on('dome.ipc.settings.sync', remoteSyncSettings ); +ipcMain.on('dome.ipc.settings.window', remoteSaveWindowSettings ); +ipcMain.on('dome.ipc.settings.global', remoteSaveGlobalSettings ); + +// -------------------------------------------------------------------------- +// --- Active Windows +// -------------------------------------------------------------------------- + +var appName = 'Dome' ; +const MODIFIED = '(*) ' ; + +/** + Sets application window name + @param {string} title - application name + */ +export function setName(title) { + appName = title; +} + +function setTitle(event,title) { + let w = BrowserWindow.fromId( event.frameId ); + w.setTitle( title || appName ); +} + +function setModified(event,modified) { + let w = BrowserWindow.frameId( event.frameId ); + if (platform == 'macos') + w.setDocumentEdited( modified ); + else { + let title = w.getTitle(); + if (title.startsWith(MODIFIED)) + title = title.substring(MODIFIED.length); + if (modified) + title = MODIFIED + title ; + w.setTitle(title); + } +} + +ipcMain.on('dome.ipc.window.title',setTitle); +ipcMain.on('dome.ipc.window.modified',setModified); + +// -------------------------------------------------------------------------- +// --- Main Window Web Navigation +// -------------------------------------------------------------------------- + +import { shell } from 'electron' ; +import { URL } from 'url' ; + +function getURL() +{ + if (DEVEL) + return `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` ; + if (LOCAL) + return 'file://' + path.join(__dirname,'../renderer/index.html') ; + return 'file://' + __dirname + '/index.html' ; +} + +function navigateURL( event , url ) { + event.preventDefault(); + const href = new URL( url ); + const main = new URL( getURL() ); + if (href.origin == main.origin) + { + const query = href.pathname.substring(1) + href.query + href.hash ; + event.sender.send('dome.ipc.href', query); + } else { + shell.openExternal( url ); + } +} + +// -------------------------------------------------------------------------- +// --- Browser Window SetUp +// -------------------------------------------------------------------------- + +const windowsHandle = {} ; // Prevent live windows to be garbage collected + +function createBrowserWindow( config, isMain=true ) +{ + + const argv = isMain + ? System.WINDOW_APPLICATION_ARGV + : System.WINDOW_PREFERENCES_ARGV ; + + const options = _.merge( + { + show: false, + backgroundColor: '#f0f0f0', + webPreferences: { + nodeIntegration:true, + additionalArguments: [ argv ] + } + } + , config ); + + const frameId = isMain ? 'application' : 'preferences' ; + const frame = _.get( s_frames, frameId ); + const getInt = (v) => v && _.toSafeInteger(v); + if (frame) { + options.x = getInt(frame.x); + options.y = getInt(frame.y); + options.width = getInt(frame.width); + options.height = getInt(frame.height); + } + + const theWindow = new BrowserWindow( options ); + + // Load the index.html of the app. + if (DEVEL || LOCAL) + process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; + + theWindow.loadURL(getURL()); + + // Load Finished + theWindow.once('ready-to-show' , () => { + if (DEVEL || LOCAL) + process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'false'; + if (DEVEL) + theWindow.openDevTools(); + theWindow.show(); + }); + + // Focus Management + theWindow.on('focus', () => theWindow.send('dome.ipc.focus',true)); + theWindow.on('blur', () => theWindow.send('dome.ipc.focus',false)); + + // URL Navigation + theWindow.webContents.on('will-navigate', navigateURL ); + theWindow.webContents.on('did-navigate-in-page', navigateURL ); + theWindow.webContents.on('did-finish-load', () => broadcast('dome.ipc.reload')); + + // Emitted when the window want's to close. + theWindow.on('close', (evt) => { + theWindow.send('dome.ipc.closing'); + const frame = theWindow.getBounds(); + _.set( s_frames, frameId , frame ); + }); + + // Keep track of frame positions (in DEVEL) + if (DEVEL) { + const reframe = _.debounce( (evt) => { + const frame = theWindow.getBounds(); + _.set( s_frames, frameId , frame ); + saveSettings(); + } , 300); + theWindow.on('resize',reframe); + theWindow.on('moved',reframe); + } + + // Keep the window reference to prevent destruction + const wid = theWindow.id ; + windowsHandle[ wid ] = theWindow ; + + // Emitted when the window is closed. + theWindow.on('closed', () => { + // Dereference the window object to actually destroy it + delete windowsHandle[ wid ] ; + }); + + return theWindow ; +} + +// -------------------------------------------------------------------------- +// --- Application Window(s) +// -------------------------------------------------------------------------- + +function filterArgv( argv ) { + return argv.slice( DEVEL ? 3 : (LOCAL ? 2 : 1) ).filter((p) => p); +} + +function sendCommand( win, argv, wdir ) { + win.webContents.on('did-finish-load', () => { + win.webContents.send('dome.ipc.command',argv,wdir); + }); +} + +function createPrimaryWindow() +{ + // Initialize Menubar + Menubar.install(); + + // Initialize Settings + loadSettings(); + + // React Developper Tools + if (DEVEL) + installExtension(REACT_DEVELOPER_TOOLS,true); + + const primary = createBrowserWindow({ title: appName } , true); + const wdir = process.cwd() === '/' ? app.getPath('home') : process.cwd() ; + sendCommand( primary , filterArgv(process.argv) , wdir ); +} + +var appCount = 1; + +function createSecondaryWindow(_event,argv,wdir) +{ + const secondary = createBrowserWindow({ title: `${appName} #${++appCount}` }, true); + sendCommand( secondary, filterArgv(argv), wdir ); +} + +function createDesktopWindow() +{ + const instance = appCount++ ; + const secondary = createBrowserWindow({ title: `${appName} #${++appCount}` }, true); + sendCommand( secondary , [] , app.getPath('home') ); +} + +// -------------------------------------------------------------------------- +// --- Activate Windows (macOS) +// -------------------------------------------------------------------------- + +function activateWindows() { + var isFocused = false ; + var toFocus = undefined ; + BrowserWindow.getAllWindows().forEach((w) => { + w.show(); + if (w.isFocused()) isFocused = true ; + else if (!toFocus) toFocus = w; + }); + if (!isFocused) { + if (toFocus) toFocus.focus(); + else { + // No focusable nor focused window + createDesktopWindow(); + } + } +} + +// -------------------------------------------------------------------------- +// --- Settings Window +// -------------------------------------------------------------------------- + +var windowSettings = undefined ; // Preference Window + +function showSettingsWindow() +{ + if (!windowSettings) + windowSettings = createBrowserWindow({ + title: appName + ' Settings', + width: 256, + height: 248, + fullscreen: false, + maximizable: false, + minimizable: false + }, false); + windowSettings.show(); + windowSettings.on('closed',() => windowSettings = undefined); +} + +function restoreDefaultSettings() +{ + s_globals = {} ; + s_preferences = {} ; + s_application = {} ; + s_frames = {} ; + fireSaveSettings(); + fireSaveSettings.flush(); + broadcast( 'dome.ipc.settings.defaults' ); +} + +// -------------------------------------------------------------------------- +// --- Main Application Starter +// -------------------------------------------------------------------------- + +/** Starts the main process. */ +export function start() { + + // Ensures second instance triggers the main one + if (!app.requestSingleInstanceLock()) app.quit(); + + // Change default locale + app.commandLine.appendSwitch('lang','en'); + + // Listen to window events + app.on( 'ready', createPrimaryWindow ); // Wait for Electron init + app.on( 'activate', activateWindows ); // Mac OSX response to dock + app.on( 'second-instance', createSecondaryWindow ); + app.on( 'dome.menu.settings', showSettingsWindow ); + app.on( 'dome.menu.defaults', restoreDefaultSettings ); + + // Performing on-exit callbacks + app.on( 'will-quit' , () => { + System.doExit() ; + fireSaveSettings(); + fireSaveSettings.flush(); + }); + + // On OS X menu bar stay active until the user quits explicitly from menu. + // On other systems, quit when all windows are closed. + // Warning: when no event handler is registered, the app automatically + // quit when all windows are closed. + app.on( 'window-all-closed', () => { + if (System.platform !== 'macos') app.quit(); + }); + +} + +// -------------------------------------------------------------------------- +// --- Renderer-Process Communication +// -------------------------------------------------------------------------- + +function broadcast( event, ...args ) +{ + BrowserWindow.getAllWindows().forEach((w) => { + w.send( event, ...args ); + }); +} + +// -------------------------------------------------------------------------- +// --- MenuBar Management +// -------------------------------------------------------------------------- + +const MENU_CLICK = (id,callback) => (_item,win,_event) => { + callback && callback(); + app.emit('dome.menu.clicked', id ); + win.send('dome.ipc.menu.clicked', id ); +}; + +/** + @summary Define a custom main window menu. + @description + Cf. [addMenu](dome_.html#.addMenu) in the renderer process. +*/ +export function addMenu( label ) { Menubar.addMenu( label ); } + +/** + @summary Define a custom menu item. + @description + Cf. [addMenuItem](dome_.html#.addMenuItem) in the renderer process. +*/ +export function addMenuItem( spec ) +{ + if ( spec.type === 'separator' ) { + Menubar.addMenuItem( spec ); + } else { + const id = spec.id ; + if (!id) { + console.error('[Dome] Missing menu-item identifier:',spec); + return; + } + const { callback , ...options } = spec ; + options.click = MENU_CLICK( id, callback ); + Menubar.addMenuItem( options ); + } +} + +/** + @summary Update a menu item. + @description + Cf. [setMenuItem](dome_.html#.setMenuItem) in the renderer process. +*/ +export function setMenuItem( options ) { + const { callback , ...updates } = options ; + if (callback !== undefined) { + const id = updates.id ; + updates.click = MENU_CLICK( id, callback ); + } + Menubar.setMenuItem( updates ); +} + +ipcMain.on( 'dome.ipc.menu.addmenu' , addMenu ); +ipcMain.on( 'dome.ipc.menu.addmenuitem' , addMenuItem ); +ipcMain.on( 'dome.ipc.menu.setmenuitem' , setMenuItem ); + +// -------------------------------------------------------------------------- +// --- Export Default +// -------------------------------------------------------------------------- + +export default { + platform, + DEVEL, + setName, + start, + addMenu, + addMenuItem, + setMenuItem +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/main/menubar.js b/Ivette/src/dome/src/main/menubar.js new file mode 100644 index 00000000000..9660a2b968e --- /dev/null +++ b/Ivette/src/dome/src/main/menubar.js @@ -0,0 +1,415 @@ +// -------------------------------------------------------------------------- +// --- Menus & MenuBar Management +// -------------------------------------------------------------------------- + +import { app, BrowserWindow, Menu, MenuItem, shell } from 'electron' ; +import System from 'dome/system' ; + +// -------------------------------------------------------------------------- +// --- Special Callbacks +// -------------------------------------------------------------------------- + +function reloadWindow(item, focusedWindow) +{ + if (focusedWindow) { + // on reload, start fresh and close any old + // open secondary windows + if (focusedWindow.id === 1) + BrowserWindow.getAllWindows().forEach(function (win) { + if (win.id > 1) win.close(); + }); + reset(); // declared below + focusedWindow.reload(); + } +} + +function toggleFullScreen(item, focusedWindow) +{ + if (focusedWindow) + focusedWindow.setFullScreen(!focusedWindow.isFullScreen()); +} + +function toggleDevTools(item, focusedWindow) +{ + if (focusedWindow) + focusedWindow.toggleDevTools(); +} + +// -------------------------------------------------------------------------- +// --- Menu Utilities +// -------------------------------------------------------------------------- + +const separator = { type: 'separator' } ; + +function concatSep( ...menus ) { + var submenu = [] ; + var needsep = false ; + menus.forEach((items) => { + const n = items.length ; + if (n > 0) { + if (needsep) + submenu.push( separator ); + submenu = submenu.concat(items); + needsep = (items[n-1].type !== 'separator') ; + } + }); + return submenu ; +} + +// -------------------------------------------------------------------------- +// --- MacOS Menu Items +// -------------------------------------------------------------------------- + +const macosAppMenuItems = (name) => [ + { + label: `About ${name}`, + role: 'about' + }, + separator, + { + label: `Preferences…`, + accelerator: 'Command+,', + click: () => app.emit('dome.menu.settings') + }, + { + label: `Restore Defaults`, + click: () => app.emit('dome.menu.defaults') + }, + separator, + { + label: `Services`, + submenu: [], + role: 'services' + }, + separator, + { + label: `Hide ${name}`, + accelerator: 'Command+H', + role: 'hide' + }, { + label: 'Hide Others', + accelerator: 'Command+Alt+H', + role: 'hideothers' + }, { + label: 'Show All', + role: 'unhide' + }, + separator, + { + label: 'Quit', + accelerator: 'Command+Q', + role: 'quit' + } +]; + +// -------------------------------------------------------------------------- +// --- File Menu Items (platform dependant) +// -------------------------------------------------------------------------- + +var fileMenuItems_custom = []; + +const fileMenuItems_linux = [ + { + label: `Preferences…`, + click: () => app.emit('dome.menu.settings') + }, + { + label: `Restore Defaults`, + click: () => app.emit('dome.menu.defaults') + }, + separator, + { + label: 'Exit', + accelerator: 'Ctrl+Q', + role: 'quit' + } +]; + +// -------------------------------------------------------------------------- +// --- Edit Menu Items +// -------------------------------------------------------------------------- + +const editMenuItems = [ + { label: 'Undo', + accelerator: 'CmdOrCtrl+Z', + role: 'undo' + }, { + label: 'Redo', + accelerator: 'Shift+CmdOrCtrl+Z', + role: 'redo' + }, + separator, + { + label: 'Cut', + accelerator: 'CmdOrCtrl+X', + role: 'cut' + }, { + label: 'Copy', + accelerator: 'CmdOrCtrl+C', + role: 'copy' + }, { + label: 'Paste', + accelerator: 'CmdOrCtrl+V', + role: 'paste' + }, { + label: 'Select All', + accelerator: 'CmdOrCtrl+A', + role: 'selectall' + } +]; + +var editMenuItems_custom = [] ; + +// -------------------------------------------------------------------------- +// --- View Menu Items +// -------------------------------------------------------------------------- + +var viewMenuItems_custom = [] ; + +const viewMenuItems = (osx) => [ + { + label: 'Reload', + accelerator: 'CmdOrCtrl+R', + click: reloadWindow + }, { + label: 'Toggle Full Screen', + accelerator: (osx ? 'Ctrl+Command+F' : 'F11'), + click: toggleFullScreen + }, { + label: 'Toggle Developer Tools', + accelerator: (osx ? 'Alt+Command+I' : 'Ctrl+Shift+I'), + click: toggleDevTools + } +]; + +// -------------------------------------------------------------------------- +// --- Window Menu Items +// -------------------------------------------------------------------------- + +const windowMenuItems_linux = [ + { + label: 'Minimize', + accelerator: 'CmdOrCtrl+M', + role: 'minimize' + }, { + label: 'Close', + accelerator: 'CmdOrCtrl+W', + role: 'close' + }, + separator, + { + label: 'Reopen Window', + accelerator: 'CmdOrCtrl+Shift+T', + enabled: false, /*?*/ + key: 'reopenMenuItem', /*?*/ + click: () => { app.emit('activate'); } + } +]; + +const windowMenuItems_macos = windowMenuItems_linux.concat([ + { + label: 'Bring All to Front', + role: 'front' + } +]); + +// -------------------------------------------------------------------------- +// --- Help Menu Items +// -------------------------------------------------------------------------- + +const helpMenuItems = [ + { + label: 'Learn More', + click: function () { + shell.openExternal('http://electron.atom.io'); + } + } +]; + +// -------------------------------------------------------------------------- +// --- Update MenuBar (async) +// -------------------------------------------------------------------------- + +var updateRequired = false ; +var updateTriggered = false ; + +function requestUpdate() { + if (updateRequired && !updateTriggered) { + updateTriggered = true ; + setImmediate( install ); + } +} + +// -------------------------------------------------------------------------- +// --- CustomMenus +// -------------------------------------------------------------------------- + +var customMenus = [] ; +var customItems = {} ; + +function findMenu( label ) { + switch( label ) { + case 'File': return fileMenuItems_custom; + case 'Edit': return editMenuItems_custom; + case 'View': return viewMenuItems_custom; + default: + var theMenu = customMenus.find((m) => m.label === label); + return theMenu && theMenu.submenu ; + } +} + +export function addMenu( label ) +{ + if (findMenu(label)) { + console.warn(`Already defined menu '${menu}'`); + } else { + customMenus.push( { label , submenu:[] } ); + } + requestUpdate(); +} + +function updateItem( entry, options ) +{ +} + +export function addMenuItem( { menu , key, ...spec } ) +{ + var submenu = findMenu( menu ); + if (!submenu) { + console.error(`[Dome] Unknown menu '${menu}' (menu item #${spec.id || spec.label} undefined)`); + return; + } + if (!spec || spec.type === 'separator') { + submenu.push( separator ); + } else { + const id = spec.id ; + if (!id) { + console.error('[Dome] Invalid menu item:',spec); + return; + } + if (key) { + switch(System.platform) { + case 'macos': + if (key.startsWith('Cmd+')) spec.accelerator = "Cmd+" + key.substring(4) ; + if (key.startsWith('Alt+')) spec.accelerator = "Cmd+Alt+" + key.substring(4) ; + if (key.startsWith('Meta+')) spec.acceperator = "Cmd+Shift+" + key.substring(5) ; + break; + case 'windows': + case 'linux': + default: + if (key.startsWith('Cmd+')) spec.accelerator = "Ctrl+" + key.substring(4) ; + if (key.startsWith('Alt+')) spec.accelerator = "Alt+" + key.substring(4) ; + if (key.startsWith('Meta+')) spec.acceperator = "Ctrl+Alt+" + key.substring(5) ; + break; + } + } + const entry = customItems[id] ; + if (entry) { + if (!System.DEVEL) { + console.error('[Dome] Duplicate menu item:',spec); + return; + } else { + if (entry.spec) Object.assign( entry.spec , spec ); + if (entry.item) Object.assign( entry.item , spec ); + } + } else { + customItems[id] = { spec } ; + submenu.push( spec ); + } + } + requestUpdate(); +} + +export function setMenuItem({ id, ...options }) +{ + const entry = customItems[id] ; + if (entry) { + if (entry.spec) Object.assign( entry.spec , options ); + if (entry.item) Object.assign( entry.item , options ); + if ( options.label || options.type || options.click ) requestUpdate(); + } else + console.warn(`[Dome] unknown menu item #${id}`); +} + +// -------------------------------------------------------------------------- +// --- Menu Bar Template +// -------------------------------------------------------------------------- + +function template() { + switch(System.platform) { + case 'macos': + return [].concat( + [ + { label: app.name, submenu: macosAppMenuItems(app.name) }, + { label: 'File', submenu: fileMenuItems_custom }, + { label: 'Edit', submenu: concatSep(editMenuItems,editMenuItems_custom) }, + { label: 'View', submenu: concatSep(viewMenuItems_custom,viewMenuItems(true)) } + ], + customMenus, + [ + { label: 'Window', role: 'window', submenu: windowMenuItems_macos }, + { label: 'Help', role: 'help', submenu: helpMenuItems } + ] + ); + case 'windows': + case 'linux': + default: + return [].concat( + [ + { label: 'File', submenu: concatSep(fileMenuItems_custom,fileMenuItems_linux) }, + { label: 'Edit', submenu: concatSep(editMenuItems,editMenuItems_custom) }, + { label: 'View', submenu: concatSep(viewMenuItems_custom,viewMenuItems(false)) } + ], + customMenus, + [ + { label: 'Window', submenu: windowMenuItems_linux }, + { label: 'Help', submenu: helpMenuItems } + ] + ); + } +} + +// -------------------------------------------------------------------------- +// --- MenuBar SetUp +// -------------------------------------------------------------------------- + +var menubar ; + +function registerCustomItems( menu ) { + menu.items.forEach((item) => { + const entry = customItems[item.id]; + if (entry) entry.item = item ; + item.submenu && registerCustomItems( item.submenu ); + }); +} + +export function install() { + updateRequired = true; + updateTriggered = false; + menubar = Menu.buildFromTemplate(template()); + registerCustomItems( menubar ); + Menu.setApplicationMenu( menubar ); +} + +// Called by reload above +function reset() { + fileMenuItems_custom = [] ; + editMenuItems_custom = [] ; + viewMenuItems_custom = [] ; + customMenus = [] ; + customItems = {} ; + install(); +} + +// -------------------------------------------------------------------------- +// --- Export Default +// -------------------------------------------------------------------------- + +export default { + install, + addMenu, + addMenuItem, + setMenuItem +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/misc/devtools.js b/Ivette/src/dome/src/misc/devtools.js new file mode 100644 index 00000000000..222b66d9d3d --- /dev/null +++ b/Ivette/src/dome/src/misc/devtools.js @@ -0,0 +1,12 @@ +// -------------------------------------------------------------------------- +// --- Dummy clone of electron-dev-installer +// -------------------------------------------------------------------------- + +// No need to export dummy identifiers (undefined is ok) + +export const REACT_DEVELOPER_TOOLS = undefined ; + +// Shall not be used in non-development mode +export default function installExtension(_id) { + return Promise.reject(); +} diff --git a/Ivette/src/dome/src/misc/events.js b/Ivette/src/dome/src/misc/events.js new file mode 100644 index 00000000000..16c0b380da3 --- /dev/null +++ b/Ivette/src/dome/src/misc/events.js @@ -0,0 +1,81 @@ +// -------------------------------------------------------------------------- +// --- A Ghost Component aware of its enclosing positionned container +// -------------------------------------------------------------------------- + +import React from 'react' ; +import Props from 'prop-types' ; + +const SIZED = { + display: 'block', + position: 'absolute', + top: 0, + left: 0, + height: '100%', + width: '100%', + overflow: 'hidden', + pointerEvents: 'none', + zIndex: -1 +}; + +// -------------------------------------------------------------------------- +// --- Components +// -------------------------------------------------------------------------- + +/* + This component is a ghost element to be inserted inside a _positionned_ + container. It makes the container aware of its bounding client rectangle + _via_ the `onResize` property. + + The `onResize` callback is invoked whenever the parent container is + positionned or resized. The callback is passed the + `container.getBoundingClientRect()` rectangle. +*/ +export class Layout extends React.Component { + + // Init the element + componentDidMount() { + this.element.data = 'about:blank'; + this.handleResize = this.handleResize.bind(this); + } + + // Callback on Resize + handleResize() { + if (this.props.onResize) { + const r = this.element.getBoundingClientRect(); + this.props.onResize(r); + } + } + + componentWillUnmount() { + if (this.state.view) + this.state.view.removeEventListener('resize', this.handleResize); + } + + render() { + return React.createElement('object', { + type: 'text/html', style: SIZED, + ref: elt => { this.element = elt; }, + onLoad: evt => { + this.setState( + { view: evt.target.contentDocument.defaultView }, + () => { + this.state.view.addEventListener('resize', this.handleResize); + this.handleResize(); + } + ); + } + }); + } + +} + +// -------------------------------------------------------------------------- +// --- Props & Defaults +// -------------------------------------------------------------------------- + +Layout.propTypes = { onResize: Props.func }; +Layout.defaultProps = { }; + +export default { Layout }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/misc/plugins.js b/Ivette/src/dome/src/misc/plugins.js new file mode 100644 index 00000000000..5d468d4017a --- /dev/null +++ b/Ivette/src/dome/src/misc/plugins.js @@ -0,0 +1,97 @@ +// -------------------------------------------------------------------------- +// --- Dome Plugins Management +// -------------------------------------------------------------------------- + +import fs from 'fs' ; +import path from 'path' ; + +const registry = {} ; + +// -------------------------------------------------------------------------- +// --- Installing Bundle +// -------------------------------------------------------------------------- + +export function register( id, exports ) +{ + registry[id] = Object.assign( {} , exports ); +} + +const WRAPPER_OPEN = '(function(module,require,__static){\n' ; +const WRAPPER_CLOSE = '\n})' ; +const PLUGINS = '@plugins/' ; + +export function install( name ) +{ + // Resolve plugin directory + let dir = path.resolve( __static , "plugins" , name ); + if (!fs.isDirectory()) + throw `Plugin '${name}' not installed` ; + + // Resolve plugin configuration + let pkg = path.resolve( dir , 'package.json' ); + if (!fs.isFile(pkg)) + throw `Plugin '${name}' has no 'package.json' file` ; + let config ; + try { config = JSON.pargse(fs.readFileSync( pkg , 'UTF-8' )); } + catch(err) { + console.error( `[Dome] reading '${pkg}':\n`, err ); + throw `Plugin '${name}' has invalid 'package.json' file` ; + } + + // Resolve plugin entry points + let bundlejs = path.resolve( dir, config.main || 'bundle.js' ); + if (!fs.isFile(bundlejs)) + throw `Plugin '${name}' entry point not found` ; + let static_d = path.resolve( dir, 'static' ); + if (!fs.isDirectory(static_d)) static_d = undefined; + + // Load bundle file + let bundle ; + try { bundle = fs.readFileSync( bundlejs , 'UTF-8' ); } + catch(err) { + console.error( `[Dome] loading '${bundlejs}':\n`, err ); + throw `Plugin '${name}' can not load its entry point` ; + } + + // Install bundle file + let id = PLUGINS + name ; + let exports = {} ; + register( id, exports ); // cut circularities + try { + let wrapped = WRAPPER_OPEN + bundle + WRAPPER_CLOSE ; + let compiled ; eval(wrapped); + let module = { id, exports }; + compiled( module, require, static_d ); + } catch(err) { + console.error( `[Dome] running '${bundlejs}':\n`, err ); + throw `Plugin '${name}' can not install bundle` ; + } + register( id, exports ); // final exports + + // Finally return exports + return exports ; +} + +// -------------------------------------------------------------------------- +// --- Resolving Modules +// -------------------------------------------------------------------------- + +export function require(id) +{ + let exports = registry[id]; + if (exports) return Object.assign( {} , exports ); + + // Resolving plugin + + if (id.startsWith(PLUGINS)) + { + let exports = install( id.substring(PLUGINS.length) ); + return Object.assign( {} , exports ); + } + + // Trap + + throw `Module '${id}' not found` ; +} + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/misc/register.js b/Ivette/src/dome/src/misc/register.js new file mode 100644 index 00000000000..17d3be008b3 --- /dev/null +++ b/Ivette/src/dome/src/misc/register.js @@ -0,0 +1,100 @@ +// -------------------------------------------------------------------------- +// --- Dome Classes +// -------------------------------------------------------------------------- + +import React from 'react' ; +import _ from 'lodash' ; + +// -------------------------------------------------------------------------- +// --- Register a Dome Class +// -------------------------------------------------------------------------- + +export function register(Component,NAME) { + Component._DOME = NAME ; + Component.istanceOf = (elt) => (elt.type ? elt.type._DOME === NAME : false) ; +} + +// -------------------------------------------------------------------------- +// --- Get the Dome Class of a Component +// -------------------------------------------------------------------------- + +export function classOf(elt) { + return elt && elt.type && elt.type._DOME ; +} + +// -------------------------------------------------------------------------- +// --- Dispatch Children components among different Dome Classes +// -------------------------------------------------------------------------- + +/* + Split a React Children structure according to filter. + For each field { key: spec } in the filter, returns + a field { key: selection } with all children satisfying + the given spec (undefined if none). + Filter specification can be: a Dome class name, + an array of Dome class names, or 'undefined' for all non-matched + children in the filter. + + Relies on React.Children.map instead ot React.Children.toArray + in order to avoid putting keys in original children when not necessary. +*/ +export function dispatch(children,filter) +{ + + var others = undefined; + + const acceptor = _.mapValues( filter , (spec,field) => { + switch(typeof(spec)) { + case 'string': + return (elt) => classOf(elt) === spec ; + case 'undefined': + others = field ; + return undefined ; + default: + console.error('[Dome.common.register] non-supported filter spec',spec); + return undefined ; + } + } ); + + var count = 0 , first = true , accepted = [] ; + const collected = _.mapValues( acceptor , (accept,_field) => { + if (accept) { + var empty = true ; + var filtered = + React.Children.map( children , (elt) => { + var ok = elt && accept(elt); + if (ok) empty = false ; + if (others) { + if (first) accepted.push(ok); + else { + if (ok) accepted[count] = ok ; + count++; + } + } + return ok && elt; + }); + first = false ; count = 0 ; + return empty ? undefined : filtered ; + } else + return undefined ; + }); + + if (others) { + var empty = true ; + var remaining = React.Children.map( children , (elt) => { + var ok = elt && !accepted[count] ; + if (ok) empty = false ; + count++; + return ok ? elt : null ; + }); + if (!empty) collected[others] = remaining ; + } + + return collected; +} + +// -------------------------------------------------------------------------- + +export default { register , classOf , dispatch }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/misc/system.js b/Ivette/src/dome/src/misc/system.js new file mode 100644 index 00000000000..ae4bed45862 --- /dev/null +++ b/Ivette/src/dome/src/misc/system.js @@ -0,0 +1,653 @@ +/** @module dome/system */ + +// -------------------------------------------------------------------------- +// --- Evolved Spawn Process +// -------------------------------------------------------------------------- + +import _ from 'lodash' ; +import Emitter from 'events' ; +import Exec from 'child_process' ; +import fspath from 'path' ; +import fs from 'fs' ; +import { app, remote } from 'electron' ; + +// -------------------------------------------------------------------------- +// --- Platform Specificities +// -------------------------------------------------------------------------- + +var thePlatform = 'linux' ; +{ + switch( process.platform ) { + case 'darwin': + thePlatform = 'macos'; break; + case 'win32': + case 'win64': + thePlatform = 'windows'; break; + case 'aix': + case 'freebsd': + case 'linux': + case 'openbsd': + case 'sunos': + thePlatform = 'linux'; break; + default: + console.warn(`Unkwnon OS platform '${process.platform}' (fallback to 'linux')`); + thePlatform = 'linux'; break; + } +} + +/** + @summary System platform. + @description + Similar to `process.platform`, but fall into fewer categories: + - `'macos'` for Mac OSX, + - `'windows'` for Windows (32 or 64) + - `'linux'` for most unix-like platforms + +Non-recognized platforms will fallback to `'linux'` with the emission of a warning. +*/ +export const platform = thePlatform ; + +// -------------------------------------------------------------------------- +// --- Logging +// -------------------------------------------------------------------------- + +/** Development mode flag */ +export const DEVEL = process.env.NODE_ENV !== 'production' ; + +// -------------------------------------------------------------------------- +// --- At Exit +// -------------------------------------------------------------------------- + +const exitJobs = []; + +function exitJob(job,...args) { + try { job(...args); } + catch(err) { console.err('[Dome] atExit:',err); } +} + +/** + @summary Execute a routine at exit. + @param {function} callback - the function to be called when application is closing + @param {...any} [args] - the argument to be provided to the callback + @description + Exceptions thrown by the function are captured and reported on the console. + */ +export function atExit(callback,...args) { + exitJobs.push(() => exitJob(callback,...args)); +} + +/** + @summary Execute a callback at exit on each elements of a collection. + @param {array|object} elements - the collection to iterate over + @param {function} callback - the function to be called on each element + @description + The function will be invoked with `callback(value,key,elements)` via + the [Lodash `_.forOwn()`](https://lodash.com/docs/4.17.10#forOwn) iterator. + + Exceptions thrown by the function are individually captured and reported + on the console for each element in the object or array. + */ +export function atExitForEach(elements,callback) { + atExit(() => + _.forOwn(elements,(value,key,data) => exitJob(callback,value,key,data)) + ); +} + +/** Execute all pending exit jobs (and flush the list). */ +export function doExit() { + exitJobs.forEach((f) => f()); + exitJobs.length = 0; +} + +// -------------------------------------------------------------------------- +// --- Command Line Arguments +// -------------------------------------------------------------------------- + +var command_wdir = undefined ; +var command_argv = undefined ; + +function setCommand(argv,wdir) { + command_argv = argv ; + command_wdir = wdir ; +} + +// -------------------------------------------------------------------------- +// --- User's Directories +// -------------------------------------------------------------------------- + +const appProxy = app || remote.app ; + +/** Returns user's home directory. */ +export function getHome() { return appProxy.getPath('home'); } + +/** Returns user's desktop directory. */ +export function getDesktop() { return appProxy.getPath('desktop'); } + +/** Returns user's documents directory. */ +export function getDocuments() { return appProxy.getPath('documents'); } + +/** Returns user's downloads directory. */ +export function getDownloads() { return appProxy.getPath('downloads'); } + +/** + @summary Working directory (Application Window). + @return {string} absolute path + @description + This the current working directory from where the application window + was opened. + + The function returns `undefined` until the `dome.command` event has been emitted + from the `Main` process. + + See also [Dome.onCommand](dome_.html#.onCommand) event handler. +*/ +export function getWorkingDir() { return command_wdir; } + +/** + @summary Command-line arguments (Application Window). + @return {Array.<string>} command-line arguments + @description + This the command-line arguments used to open the application window. + + The function returns `undefined` until the `dome.command` event has been emitted + from the `Main` process. + + See also [Dome.onCommand](dome_.html#.onCommand) event handler. +*/ +export function getArguments() { return command_argv; } + +/** @summary Returns static assets. + @param {string} [...path] - a sequecne of path segments + @description + Returns the path to the associated `./static/<...path>` of your application. + The `./static/` directory is automatically packed into your application + by Dome thanks to `electron-webpack` default configuration. +*/ +export function getStatic(...path) { return fspath.join( __static, ...path ); } + +// -------------------------------------------------------------------------- +// --- File Join +// -------------------------------------------------------------------------- + +/** + @summary Join file paths. + @param {string} [...paths] - a sequence of path segments + @return {string} the joined filepath + @description + Same as [Node `path.join`](https://nodejs.org/dist/latest-v12.x/docs/api/path.html#path_path_join_paths) +*/ +export const join = fspath.join ; + +/** + @summary Absolute (joined) file paths. + @param {string} [...paths] - a sequence of path segments + @return {string} the corresponding absolute path + @description + Same as [Node `path.resolve`](https://nodejs.org/dist/latest-v12.x/docs/api/path.html#path_path_resolve_paths) +*/ +export const resolve = fspath.resolve ; + +/** + @summary Dirname of path. + @param {string} path - a file path + @return {string} the dirname of the path + @description + Same as [Node `path.dirname`](https://nodejs.org/dist/latest-v12.x/docs/api/path.html#path_path_dirname_path) +*/ +export const dirname = fspath.dirname ; + +/** + @summary Basename of path. + @param {string} path - a file path + @param {string} [ext] - file extension to remove + @return {string} the basename of the path + @description + Same as [Node `path.basename`](https://nodejs.org/dist/latest-v12.x/docs/api/path.html#path_path_basename_path_ext) +*/ +export const basename = fspath.basename ; + +/** + @summary File extension of path. + @param {string} path - a file path + @return {string} the file extension of the path + @description + Same as [Node `path.extname`](https://nodejs.org/dist/latest-v12.x/docs/api/path.html#path_path_extname_path) +*/ +export const extname = fspath.extname ; + +// -------------------------------------------------------------------------- +// --- File Stats +// -------------------------------------------------------------------------- + +/** + @summary Return an `fs.stat()` object for the path. + @param {string} path - the file path + @return {Promise<fs.Stats>} the file stats + @description +Promisified [Node `fs.stat`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_stat_path_callback). + +Returns a (promised) [Node `fs.Stats`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_class_fs_stats) object, +including the following usefull fields and methods (and more): + - `stats.isFile()` returns `true` for a regular file + - `stats.isDirectory()` returns `true` for a directory + - `stats.mode` the bitfield (integer) of the file access mode + - `stats.size` the size of the file (in bytes) + - `stats.mtime` last modification time stamp (javascript `Date` object) + +The promise is rejected if the file does not exists. +*/ +export function fileStat( path ) { + return new Promise((resolve,reject) => { + fs.stat( path, (err,data) => err ? reject(err) : resolve(data) ); + }); +} + +/** + @summary Check is a path exists and is a regular file. + @param {string} path - the file path + @return {boolean} synchronous check +*/ +export function isFile( path ) +{ + try { + return path && fs.statSync( path ).isFile(); + } catch(_err) { + return false; + } +} + +/** + @summary Check is a path exists and is a directory. + @param {string} path - the dir path + @return {boolean} synchronous check +*/ +export function isDirectory( path ) +{ + try { + return path && fs.statSync( path ).isDirectory(); + } catch(_err) { + return false; + } +} + +/** + @summary Check is a path exists and is a file or directory. + @param {string} path - the dir path + @return {boolean} synchronous check +*/ +export function exists( path ) +{ + try { + if (!path) return false; + let stats = fs.statSync( path ); + return stats.isFile() || stats.isDirectory(); + } catch(_err) { + return false; + } +} + +// -------------------------------------------------------------------------- +// --- Read File +// -------------------------------------------------------------------------- + +/** + @summary Reads a textual file contents. + @param {string} path - the file path + @return {Promise<string>} the file's content + @description + Promisified + [Node `fs.readFile`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_readfile_path_options_callback) + using `UTF-8` encoding. + */ +export function readFile( path ) { + return new Promise((resolve,reject) => { + fs.readFile( path, 'UTF-8', (err,data) => err ? reject(err) : resolve(data) ); + }); +} + +// -------------------------------------------------------------------------- +// --- Write File +// -------------------------------------------------------------------------- + +/** + @summary Writes a textual content in a file. + @param {string} path - the file path + @param {string} content - the content to write in + @return {Promise} to handle the request. + @description + Promisified + [Node `fs.writeFile`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_writefile_file_data_options_callback) + using `UTF-8` encoding. + */ +export function writeFile( path , content ) { + return new Promise((resolve,reject) => { + fs.writeFile( path, content, 'UTF-8', (err) => err ? reject(err) : resolve() ); + }); +} + +// -------------------------------------------------------------------------- +// --- Copy File +// -------------------------------------------------------------------------- + +/** + @summary Copy file to a new path. + @param {string} srcPath - the source file path + @param {string} tgtPath - the target file path + @return {Promise} to handle the request. + @description + Promisified + [Node `fs.copyFile`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_copyfile_src_dest_flags_callback) + using `UTF-8` encoding. + */ +export function copyFile( srcPath , tgtPath ) { + return new Promise((resolve,reject) => { + fs.copyFile( srcPath, tgtPath, (err) => err ? reject(err) : resolve() ); + }); +} + +// -------------------------------------------------------------------------- +// --- Read Directory +// -------------------------------------------------------------------------- + +/** + @summary Reads a directory. + @param {string} path - the directory path + @return {Promise<string[]>} the directory content as an array of its file names (not full path) + @description + Promisified + [Node `fs.readdir`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_readdir_path_options_callback). + + Uses `UTF-8` encoding to obtain (relative) file names instead of byte buffers. On MacOS, `.DS_Store` entries + are filtered out. +*/ +export function readDir( path ) { + const filterDir = (f) => f !== '.DS_Store' ; + return new Promise((resolve,reject) => { + fs.readdir( path, 'UTF-8', (err,files) => err ? reject(err) : resolve(files.filter(filterDir)) ); + }); +} + +// -------------------------------------------------------------------------- +// --- Make Directory +// -------------------------------------------------------------------------- + +/** + @summary Creates a new directory. + @param {string} path - the directory path + @param {object} options - permissions and mode (defaults to recursive, `0o777`) + @return {Promise} to handle the request. + @description + Promisified + [Node `fs.mkdir`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_mkdir_path_options_callback). + Options: + - `mode:number` permission modes (default is `0o777`) + - `recursive:boolean` recursively create parent directories (default is `true`) +*/ +export function mkDir( path, { recursive=true, mode=0o777 }={} ) +{ + return new Promise((resolve,reject) => { + fs.mkdir( path, { recursive, mode }, (err) => err ? reject(err) : resolve() ); + }); +} + +// -------------------------------------------------------------------------- +// --- Remove File +// -------------------------------------------------------------------------- + +/** + @summary Remove a file. + @param {string} path - the file path to unlink + @return {Promise} to handle the request. + @description + Promisified + [Node `fs.unlink`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_unlink_path_callback) +*/ +export function remove( path ) +{ + return new Promise((resolve,reject) => { + fs.unlink( path, (err) => err ? reject(err) : resolve() ); + }); +} + +// -------------------------------------------------------------------------- +// --- Remove Directory +// -------------------------------------------------------------------------- + +// Not (yet) implemented in Node for Electron +function rmDirNonRec(path) { + return new Promise((resolve,reject) => { + fs.rmdir( path, (err) => err ? reject(err) : resolve() ); + }); +} + +// Not (yet) implemented in Node for Electron +function rmDirRec(path) { + try { + let stats = fs.statSync( path ); + if (stats.isFile()) { + return remove(path); + } + if (stats.isDirectory()) { + const rmDirSub = (name) => rmDirRec(fspath.join(path,name)); + return readDir(path) + .then((names) => Promise.all(names.map(rmDirSub))) + .then(() => rmDirNonRec(path)); + } + return Promise.resolve(); + } catch(_err) { + return Promise.resolve(); + } +} + +/** + @summary Remove a directory. + @param {string} path - the directory path + @param {object|boolean} [options] - deletion mode (defaults to non-recursive) + @return {Promise} to handle the request. + @description + Promisified + [Node `fs.rmdir`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_mkdir_path_options_callback). + Options: + - `recursive:boolean` recursively remove sub-directories (default is `true`) +*/ +export function rmDir( path, { recursive=true }={} ) +{ + return recursive ? rmDirRec( path ) : rmDirNonRec( path ); +} + +// -------------------------------------------------------------------------- +// --- Rename File +// -------------------------------------------------------------------------- + +/** + @summary Rename of file of direcory. + @param {string} oldPath - the old path + @param {string} newPath - the new path + @return {Promise} to handle the request. + @description + Promisified + [Node `fs.rename`](https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_rename_oldpath_newpath_callback) +*/ +export function rename( oldPath, newPath ) +{ + return new Promise((resolve,reject) => { + fs.rename( oldPath, newPath, (err) => err ? reject(err) : resolve() ); + }); +} + +// -------------------------------------------------------------------------- +// --- Child Process +// -------------------------------------------------------------------------- + +const childprocess = {} ; + +atExitForEach(childprocess,(process) => process.kill()); + +function stdSpec( spec , isOutput ) { + switch(spec) { + case undefined: + return { io: isOutput ? 'pipe' : 'ignore' }; + case null: + case 'null': + case 'ignore': + return { io: 'ignore' }; + case 'pipe': + return { io: 'pipe' }; + default: + const fd = fs.openSync( spec.path , spec.mode || (isOutput ? 'w' : 'r') ); + return (isOutput && spec.pipe) ? { io: 'pipe', fd } : { io: fd } ; + } +} + +function pipeTee( std , fd ) +{ + if (!fd) return; + const out = fs.createWriteStream(null,{ fd, encoding: 'UTF-8' }); + out.on('error',(err) => { + console.warn("[Dome] can not pipe:",err); + std.unpipe(out); + }); + std.pipe(out); +} + +/** + @summary Spawn a child process. + @param {string} command - the command to spawn + @param {string[]} [args] - the command arguments + @param {object} [options] - spawning options (see above) + @return {Promise<ChildProcess>} unless rejected, returns a process + object to interact with the spawned command + @description +Based on [Node `child_process.spawn`](https://nodejs.org/dist/latest-v12.x/docs/api/child_process.html#child_process_child_process_spawn_command_args_options). The promised process object is a regular [Node `ChildProcess`](https://nodejs.org/api/child_process.html#child_process_class_childprocess) object, for which we recall the main useful methods below: + + - `child.on('exit',(code) => {...})` emitted event when the process is terminated + - `child.on('close',(code) => {...})` emitted event when the process is fully terminated (all pipes closed) + - `child.on('message',(...data) => {...})` emitted from the _forked_ process (if applicable) + - `child.stdout.on('data',(text) => {...})` emitted when the process writes on piped stdout (receives `UTF-8` strings) + - `child.stderr.on('data',(text) => {...})` emitted when the process writes on piped stderr (receives `UTF-8` strings) + - `child.kill()` sends a `'SIGTERM'` unix message to the process + +Options is an object similar to the original Node options, with small adaptations. +The possible option fields are described as follows: + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `cwd` | `string` | `process.cmd` | Working directory for the command | +| `env` | `object` | `{}` | _additional_ environment variables | +| `stdin` | _stdio_ | `'ignored'` | Standard input stream | +| `stdout` | _stdio_ | `'pipe'` | Standard output stream | +| `stderr` | _stdio_ | `'pipe'` | Standard error stream | +| `fork` | `boolean` | `false` | Fork a Node-child process | + +Environment variables are _added_ to the default `process.env` environment. + +Input and output streams are defined according to the following table: + +| _stdio_ | Description | +|----------|-------------| +| `'pipe'` | Accessible _via_ the promised child-process object | +| `'ignored'` | Connected to `/dev/null` | +| `{ path[,mode][,pipe] }` | Connected to file `path` | + +All pipes have their encoding set to `UTF-8`, +hence all callbacks on process events will receive natural strings instead of raw byte buffers. + +When specifying a file for a process standard stream, an optional mode can be specified. +Default is `'r'` for input streams and `'w'` for output ones. +If option `pipe:true` is provided (output streams only), the output of the process is +also piped through the Process object. The file-path is relative to the current working directory +of the _application_, not be confused with the `cwd` option of the spawned command. + +When the `fork` flag is set, the child process is spawned using +[Node `child_process.fork`](https://nodejs.org/dist/latest-v12.x/docs/api/child_process.html#child_process_child_process_fork_modulepath_args_options). This enables Node inter-process communication _via_ the +`process.send()` and `process.on('message')` methods of the child process object. +*/ + +export function spawn(command,args,options) { + return new Promise((resolve,reject) => { + + const cwd = options ? options.cwd : undefined ; + const env = options && options.env ? Object.assign( {} , process.env , options.env ) : undefined ; + const stdin = stdSpec( options && options.stdin , false ); + const stdout = stdSpec( options && options.stdout , true ); + const stderr = stdSpec( options && options.stderr , true ); + const stdio = [ stdin.io , stdout.io , stderr.io ] ; + const opt = { cwd , env , stdio , windowsHide: true }; + const fork = options && options.fork ; + var process ; + + if (fork) { + opt.stdio.push( 'ipc' ); + process = Exec.fork(command,args,opt); + } else { + process = Exec.spawn(command,args,opt); + } + + if ( !process ) { + throw "[Dome] Can not create process ('"+command+"')"; + return; + } + + const pid = process.pid ; + + if ( !pid ) { + // Must defer rejection, otherwize an uncaught exception is raised. + process.on('error',(err) => reject(err)); + return; + } + + childprocess[pid] = process ; + process.on('exit',() => delete childprocess[pid]); + + const out = process.stdout ; + const err = process.stderr ; + + if (out) { + out.setEncoding('UTF-8'); + pipeTee( out , stdout.fd ); + } + if (err) { + err.setEncoding('UTF-8'); + pipeTee( err , stderr.fd ); + } + + resolve(process); + }); +} + +// -------------------------------------------------------------------------- +// --- Window Management +// -------------------------------------------------------------------------- + +const WINDOW_APPLICATION_ARGV = '--dome-application-window' ; +const WINDOW_PREFERENCES_ARGV = '--dome-preferences-window' ; + +// -------------------------------------------------------------------------- +// --- Export Default +// -------------------------------------------------------------------------- + +export default { + platform, + DEVEL, + atExit, + atExitForEach, + doExit, + getHome, + getDesktop, + getDocuments, + getDownloads, + getWorkingDir, + getArguments, + getStatic, + join, resolve, dirname, basename, extname, + fileStat, + isFile, readFile, writeFile, copyFile, + isDirectory, readDir, mkDir, rmDir, + rename, remove, exists, + spawn, + setCommand, + WINDOW_APPLICATION_ARGV, + WINDOW_PREFERENCES_ARGV +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/controls/buttons.css b/Ivette/src/dome/src/renderer/controls/buttons.css new file mode 100644 index 00000000000..8d83de5e744 --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/buttons.css @@ -0,0 +1,257 @@ +/* -------------------------------------------------------------------------- */ +/* --- Base Styling --- */ +/* -------------------------------------------------------------------------- */ + +.dome-control-enabled { + color: #333 ; + font-weight: normal ; +} + +.dome-control-disabled { + color: #b0b0b0 ; + fill: #b0b0b0 ; + font-weight: lighter ; +} + +.dome-control-hidden { + visibility: hidden ; +} + +.dome-control-erased { + display: none ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Buttons --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xButton { + flex: 0 0 auto ; + align-self: baseline ; +} + +.dome-xBoxButton { + padding: 3px 8px ; + margin: 2px 4px ; + line-height: 1.4; + cursor: default; + border: 1px solid transparent; + border-radius: 6px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.06); +} + +.dome-xCircButton { + padding: 2px ; + margin: 2px 4px ; + cursor: default; + border: 1px solid transparent; + border-radius: 20px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.06); +} + +.dome-xButton:disabled, +.dome-xButton:active:disabled, +.dome-window-inactive .dome-xButton +{ + fill: #b0b0b0 ; + border-color: #ccc ; + background-color: #f4f4f4 ; + background-image: none; +} + +.dome-xButton:active { + background-color: #ddd; + background-image: none; +} + +.dome-xButton-lcd { + text-align: right ; + color: #61611a ; + background-color: #b2b798 ; + border-color: #c2c0c2 ; +} + +.dome-xButton-default { + border-color: #c2c0c2 ; + background-color: #f4f4f4 ; +} + +.dome-xButton-default:hover:not(:disabled) { + background-color: #fff ; +} + +.dome-xButton-selected { + border-color: #c2c0c2 ; + background-color: #ccc ; +} + +.dome-xButton-selected:hover:not(:disabled) { + background-color: #fff ; +} + +.dome-xButton-primary { + border-color: #888; + background-image: linear-gradient(to bottom, #449bef 0%, #4990e2 100%); +} + +.dome-xButton-primary:hover:not(:disabled) { + background-color: #00b6ff ; + background-image: none ; +} + +.dome-xButton-positive { + border-color: #888; + background-image: linear-gradient(to bottom, #60f577 0%, #3efb5b 100%); +} + +.dome-xButton-positive:hover:not(:disabled) { + background-color: #00ff00 ; + background-image: none ; +} + +.dome-xButton-negative { + border-color: #888; + fill: #333; + color: #333 ; + background-image: linear-gradient(to bottom, #ff827d 0%, #fb3832 100%); +} + +.dome-xButton-negative:hover:not(:disabled) { + background-color: #ff0000 ; + background-image: none ; +} + +.dome-xButton-warning { + border-color: #888; + background-image: linear-gradient(to bottom, #ffd483 0%, #ffb426 100%); +} + +.dome-xButton-warning:hover:not(:disabled) { + background-color: #ecdd09 ; + background-image: none ; +} + +.dome-xButton-label { + position: relative ; + padding: 2px ; + display: inline ; + font-size: 12px ; +} + +.dome-xButton-label.dome-control-enabled { + position: absolute ; left: 0 ; top: 0 ; width: 100% ; + /* font is smaller than disabled => absolute position */ +} + +.dome-xButton-label.dome-control-disabled { + position: relative ; width: 100% ; + /* font is larger than enabled => relative position */ +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Checkbox --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xCheckbox { + padding: 0 ; + margin: 1px 4px ; +} + +.dome-xCheckbox input { + margin-right: 8px ; + position: relative ; + left: 2px ; +} + +.dome-xRadio-group { + display: flex ; + overflow: hidden ; + flex-flow: column nowrap ; + align-items: flex-start ; + justify-contents: flex-start ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling IconButton --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xIconButton { + margin: 4px ; + background: transparent ; +} + +.dome-xIconButton:hover { + fill: #00b6ff ; +} + +.dome-xIconButton-default { + fill: #777 ; +} + +.dome-xIconButton-selected { fill: #449bef ; } + +.dome-xIconButton-positive { fill: #00d000 ; } + +.dome-xIconButton-negative { fill: #fb3832 ; } + +.dome-xIconButton-warning { + fill: #449bef ; +} + +.dome-xIconButton.dome-control-disabled, +.dome-xIconButton.dome-control-disabled:hover +{ + fill: #eee ; +} + +.dome-xIconButton.dome-control-hidden { + visibility: hidden ; +} + +.dome-xIconButton.dome-control-erased { + display: none ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Switches --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xSwitch { + flex: 0 0 auto ; + padding: 0px ; + margin: 1px 4px ; +} + +.dome-xSwitch .dome-xIcon { + position: relative ; + height: 0px ; + top: 2px ; + margin-right: 3px ; +} + +.dome-xSwitch.dome-control-enabled:hover:not(:disabled) { + fill: blue ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Select --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xSelect { + width: max-content ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Field --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xField { + font-size: 10pt ; + width: 120px ; + padding-top: 1px ; + padding-bottom: 1px ; + padding-right: 4px ; + padding-left: 4px ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/controls/buttons.js b/Ivette/src/dome/src/renderer/controls/buttons.js new file mode 100644 index 00000000000..4688fcc3eda --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/buttons.js @@ -0,0 +1,522 @@ +// -------------------------------------------------------------------------- +// --- Buttons, Check Boxes and Radio Groups +// -------------------------------------------------------------------------- + +/** + @module dome/controls/buttons + @description + + Those controls may work as _controlled_ or _uncontrolled_ components, + although you shall not use both modes at the same times. + +*/ + +import React from 'react' ; +import { Icon } from './icons' ; +import './buttons.css' ; + +const DISABLED = ({ disabled=false, enabled=true }) => !!disabled || !enabled ; +const TRIGGER = (onClick) => (evt) => { + evt.stopPropagation(); + if (onClick) onClick(); +}; + +// -------------------------------------------------------------------------- +// --- LCD +// -------------------------------------------------------------------------- + +const LCDCLASS = 'dome-xButton dome-text-code dome-xButton-lcd ' ; + +/** + @class + @summary Button-like label. + @property {string} [text] - Textual content (prepend to children components, if any) + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Label tooltip (optional) + @property {string} [className] - Additional class + @property {object} [style] - Additional CSS style +*/ +export const LCD = (props) => ( + <label className={LCDCLASS + props.className} + title={props.title} + style={props.style} > + {props.icon && <Icon id={props.icon}/>} + {props.label} + {props.text} + {props.children} + </label> +); + +// -------------------------------------------------------------------------- +// --- Button +// -------------------------------------------------------------------------- + +const VISIBLE = { visibility:'visible' }; +const HIDDEN = { visibility:'hidden' }; + +const LABEL = ({disabled,label}) => ( + <div className="dome-xButton-label" > + <div className="dome-xButton-label dome-control-enabled" + style={disabled ? HIDDEN : VISIBLE} >{label}</div> + <div className="dome-xButton-label dome-control-disabled" + style={disabled ? VISIBLE : HIDDEN}>{label}</div> + </div> +); + +/** + @class + @summary Standard Button. + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [label] - Button label + @property {string} [title] - Optional tooltip + @property {boolean} [selected] - Selected button + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {boolean} [visible] - Defaults to `true` + @property {boolean} [display] - Defaults to `true` + @property {boolean} [focusable] - May gain focus + @property {string} [kind] - Styled button (see below) + @property {function} [onClick] - On-click callback + @property {string} [className] - Additional class + @property {object} [style] - Additional style + @description + The different available kinds for styling a button are: + - `'default'`: normal button; + - `'active'`: active normal button; + - `'primary'`: primary button, in blue; + - `'warning'`: warning button, in orange; + - `'positive'`: positive button, in green; + - `'negative'`: negative button, in red. + + Buttons without focus can not be triggered with the Enter key. +*/ +export const Button = (props) => { + const disabled = DISABLED(props); + const { focusable=false, kind='default', + visible=true, display=true, + selected, icon, label, className='' } = props; + const theClass = 'dome-xButton dome-xBoxButton dome-xButton-' + + (selected ? 'selected' : kind) + + (visible ? '' : ' dome-control-hidden') + + (display ? '' : ' dome-control-erased') + + (className ? ' ' + className : '') ; + const nofocus = focusable ? undefined : true ; + return ( + <button type='button' + className={theClass} + disabled={disabled} + onClick={TRIGGER(props.onClick)} + title={props.title} + style={props.style} + tabIndex={ nofocus && -1 } + onMouseDown={ nofocus && ((evt) => evt.preventDefault()) } + > + {icon && <Icon id={icon}/>} + {label && <LABEL disabled={disabled} label={label}/>} + </button> + ); +}; + +// -------------------------------------------------------------------------- +// --- Icon Button +// -------------------------------------------------------------------------- + +/** + @class + @summary Circled Icon Button. + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Optional tooltip + @property {boolean} [selected] - Selected button + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {boolean} [visible] - Defaults to `true` + @property {boolean} [display] - Defaults to `true` + @property {boolean} [focusable] - May gain focus + @property {string} [kind] - Styled button (see below) + @property {function} [onClick] - On-click callback + @property {string} [className] - Additional class + @property {object} [style] - Additional style + @description + The different available kinds for styling a button are: + - `'default'`: normal button; + - `'active'`: active normal button; + - `'primary'`: primary button, in blue; + - `'warning'`: warning button, in orange; + - `'positive'`: positive button, in green; + - `'negative'`: negative button, in red. + + Buttons without focus can not be triggered with the Enter key. +*/ + +export const CircButton = (props) => { + const disabled = DISABLED(props); + const { focusable=false, kind='default', + visible=true, display=true, + selected, icon, label, className='' } = props; + const theClass = 'dome-xButton dome-xCircButton dome-xButton-' + + (selected ? 'selected' : kind) + + (visible ? '' : ' dome-control-hidden') + + (display ? '' : ' dome-control-erased') + + (className ? ' ' + className : '') ; + const nofocus = focusable ? undefined : true ; + return ( + <button type='button' + className={theClass} + disabled={disabled} + onClick={TRIGGER(props.onClick)} + title={props.title} + style={props.style} + tabIndex={ nofocus && -1 } + onMouseDown={ nofocus && ((evt) => evt.preventDefault()) } + > + {icon && <Icon offset={-1} id={icon}/>} + </button> + ); +}; + +// -------------------------------------------------------------------------- +// --- Icon Button +// -------------------------------------------------------------------------- + +/** + @class + @summary Borderless Icon Button. + @property {string} icon - Icon identifier + @property {number} size - Icon size (default `12`) + @property {number} offset - Icon offset + @property {string} [title] - Optional tooltip + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {boolean} [visible] - Defaults to `true` + @property {boolean} [display] - Defaults to `true` + @property {boolean} [selected] - Defaults to `false` + @property {function} [onClick] - Callback (receives the newly expected value) + @property {string} [kind] - Styled button (see below) + @property {string} [className] - Additional class + @property {object} [style] - Additional style + @description + The different available kinds for styling a button are: + - `'default'`: normal button; + - `'active'`: active normal button; + - `'warning'`: warning button, in orange; + - `'positive'`: positive button, in green; + - `'negative'`: negative button, in red. +*/ + +export const IconButton = (props) => { + const disabled = DISABLED(props); + const { icon, size, visible=true, display=true, selected, kind='default' } = props ; + const className = 'dome-xIconButton' + + ' dome-xIconButton-' + (selected ? 'selected' : kind) + + (disabled ? ' dome-control-disabled' : ' dome-control-enabled') + + (visible ? '' : ' dome-control-hidden') + + (display ? '' : ' dome-control-erased') + + (props.className ? ' ' + props.className : '') ; + return ( + <Icon + size={size} id={icon} + style={props.style} + offset={props.offset} + className={className} + onClick={TRIGGER(props.onClick)} + /> + ); +}; + +// -------------------------------------------------------------------------- +// --- CheckBox +// -------------------------------------------------------------------------- + +const CHECKBOX_ENABLED = 'dome-control-enabled dome-xCheckbox ' ; +const CHECKBOX_DISABLED = 'dome-control-disabled dome-xCheckbox ' ; + +/** + @class + @summary CheckBox with its label. + @property {string} [label] - Button label + @property {string} [title] - Optional tooltip + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {boolean} [value] - Checked or not (defaults to internal state) + @property {function} [onChange] - Callback (receives the newly expected value) + @property {string} [className] - Additional class + @property {object} [style] - Additional style +*/ +export const Checkbox = (props) => { + const disabled = DISABLED(props); + const onChange = props.onChange && ((evt) => props.onChange(evt.target.checked)) ; + const baseClass = disabled ? CHECKBOX_DISABLED : CHECKBOX_ENABLED ; + const labelClass = props.className || '' ; + return ( + <label + title={props.title} + style={props.style} + className={baseClass + labelClass} > + <input type="checkbox" + disabled={disabled} + checked={props.value} + onChange={onChange} /> + {props.label} + </label> + ); +}; + +// -------------------------------------------------------------------------- +// --- Switch +// -------------------------------------------------------------------------- + +/** + @class + @summary Switch with its label. + @property {string} [label] - Button label + @property {string} [title] - Optional tooltip + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {boolean} [visible] - Defaults to `true` + @property {boolean} [display] - Defaults to `true` + @property {boolean} [value] - Checked or not (defaults to internal state) + @property {function} [onChange] - Callback (receives the newly expected value) + @property {string} [className] - Additional class + @property {object} [style] - Additional style +*/ +export const Switch = (props) => { + const disabled = DISABLED(props); + const { visible=true, display=true } = props ; + const onChange = props.onChange && ((evt) => props.onChange(evt.target.checked)) ; + const iconId = props.value ? 'SWITCH.ON' : 'SWITCH.OFF' ; + const onClick = (disabled || !props.onChange) + ? undefined : () => props.onChange(!props.value) ; + const className = 'dome-xSwitch ' + + (disabled ? 'dome-control-disabled' : 'dome-control-enabled') + + (visible ? '' : ' dome-control-hidden') + + (display ? '' : ' dome-control-erased') + + (props.className ? ' ' + props.className : '') ; + return ( + <label + title={props.title} + style={props.style} + className={className} + onClick={TRIGGER(onClick)} + > + <Icon size={16} id={iconId} /> + {props.label} + </label> + ); +}; + +// -------------------------------------------------------------------------- +// --- Radio Button +// -------------------------------------------------------------------------- + +/** + @class + @summary Radio Button with its label. + @property {string} [label] - Button label + @property {string} [title] - Optional tooltip + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {any} [value] - Associated value to the radio + @property {any} [selection] - Currently selected value + @property {function} [onSelection] - On-click callback + @property {string} [className] - Additional class + @property {object} [style] - Additional style + @description + See also [RadioGroup](module-dome_controls_buttons.RadioGroup.html). + + <strong>Note:</strong> property `value` and `selection` are consistent + with HTML standards and DOM element properties. +*/ +export const Radio = (props) => { + const disabled = DISABLED(props); + const checked = props.value === props.selection ; + const onChange = props.onSelection && (() => props.onSelection(props.value)) ; + const baseClass = disabled ? CHECKBOX_DISABLED : CHECKBOX_ENABLED ; + const labelClass = props.className || '' ; + return ( + <label + title={props.title} + style={props.style} + className={baseClass + labelClass} > + <input type="radio" disabled={disabled} checked={checked} onChange={onChange} /> + {props.label} + </label> + ); +}; + +// -------------------------------------------------------------------------- +// --- Radio Group +// -------------------------------------------------------------------------- + +/** + @class + @summary Selector of Radio Buttons. + @property {any} [value] - Currently selected value + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {function} [onChange] - On-selection callback + @property {string} [className] - Additional class of the container `<div>` + @property {object} [style] - Additional style of the container `<div>` + @description + Childrens of the `RadioGroup` shall be [Radio](module-dome_controls_buttons.Radio.html) + buttons. + + The selected value of the group is broadcasted to the radio buttons. Their + callbacks are activated _before_ the radio group one, if any. + + If the radio group is disabled, all the radio buttons are disabled also and + their `disabled` properties are ignored. On the contrary, when the radio + group is enabled, the `disabled` property of each radio button is taken into + account. + + The radio buttons inside a group are laidout in a vertical box with the additional + styling properties. +*/ +export class RadioGroup extends React.Component { + + constructor(props) { + super(props); + this.state = { value: props.value }; + this.onChange = this.onChange.bind(this); + } + + componentDidUpdate() { + let v = this.props.value ; + if (v && this.state.value !== v) this.setState( { value: v } ); + } + + onChange(value) { + this.setState( { value } ); + this.props.onChange && this.props.onChange( value ); + } + + render() { + const groupdisabled = DISABLED(this.props); + const { className='', style } = this.props ; + const selection = this.state.value ; + const makeRadio = (radio) => { + const disabled = groupdisabled || DISABLED(radio.props) ; + const { onSelection: onRadioSelect } = radio.props ; + const onSelection = + onRadioSelect + ? (v) => { onRadioSelect(v) ; this.onChange(v); } + : this.handleSelect ; + return React.cloneElement( radio , { selection , disabled , onSelection } , null ); + } ; + return ( + <div className={ 'dome-xRadio-group ' + className } style={style}> + {React.Children.map( this.props.children , makeRadio )} + </div> + ); + } + +} + +// -------------------------------------------------------------------------- +// --- Selector +// -------------------------------------------------------------------------- + +/** + @class + @summary Menu Button. + @property {string} [placeholder] - Label of undefined selection + @property {string} [title] - Optional tooltip + @property {any} [value] - Currently selected value + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {function} [onChange] - On-selection callback + @property {string} [className] - Additional class + @property {object} [style] - Additional style + @property {string} [id] - Select identifier + @description + Childrens of the `Select` shall be standard `<option>` or `<optgroup>` HTML + elements. When the `placeholder` property is set, an additional option is provided + and associated with any `undefined` value. + + The selected value of the group is broadcasted to the provided options, and their callbacks + linked to the button automatically. + + **Remark:** most non-positionning CSS properties might not work on the `<select>` element due + to the native rendering used by Chrome. + You might use `-webkit-appearance: none` to cancel this behavior, you will have to restyle the + component entirely, which is quite ugly by default. +*/ +export const Select = (props) => { + const disabled = DISABLED(props); + const onChange = props.onChange && ((e) => props.onChange(e.target.value)); + const className = props.className || '' ; + return ( + <select + id={props.id} + disabled={disabled} + className={'dome-xSelect ' + className} + style={props.style} + title={props.title} + value={props.value || ''} + onChange={onChange} + > + {props.placeholder && props.placeholder !=='' && ( + <option disabled value=''>— {props.placeholder} —</option> + )} + {props.children} + </select> + ); +}; + +// -------------------------------------------------------------------------- +// --- Text Input +// -------------------------------------------------------------------------- + +/** + @class + @summary Text Field + @property {string} [value] - Field initial content + @property {string} [edited] - Field current value + @property {boolean} [enabled] - Defaults to `true` + @property {boolean} [disabled] - Defaults to `false` + @property {boolean} [autoFocus] - Defaults to `false` + @property {function} [onChange] - Update callback (on every edit, debounced) + @property {function} [onEnter] - Enter callback (on Enter or Return key) + @property {string} [title] - Field tooltip text + @property {string} [placeholder] - Input field place holder + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {string} [id] - Input field identifier + @description + Field with a Text Input element. The default latency is set to 600ms. +*/ +export const Field = (props) => { + const [ current, setCurrent ] = React.useState(props.value); + const disabled = DISABLED(props); + const className = props.className || '' ; + const { edited, onChange, onEnter } = props ; + const value = edited === undefined ? current : edited ; + const ONCHANGE = (evt) => { + let text = evt.target.value || '' ; + if (edited === undefined) setCurrent(text); + onChange && onChange(text); + }; + const ONKEYPRESS = (evt) => { + if (evt.key === 'Enter' && onEnter) onEnter(value); + }; + return ( + <input id={props.id} type='text' + autoFocus={!disabled && props.autoFocus} + value={value} + className={'dome-xField ' + className} + style={props.style} + disabled={disabled} + placeholder={props.placeholder} + onKeyPress={ONKEYPRESS} + onChange={ONCHANGE} /> + ); +}; + +// -------------------------------------------------------------------------- +// --- Exports +// -------------------------------------------------------------------------- + +export default { + Button, CircButton, IconButton, Switch, Checkbox, Radio, RadioGroup, Select +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/controls/icons.css b/Ivette/src/dome/src/renderer/controls/icons.css new file mode 100644 index 00000000000..066887a3917 --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/icons.css @@ -0,0 +1,42 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling Icons --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xIcon { + flex: 0 0 auto ; + display: inline ; + margin: 1px ; + padding: 1px 0px 0px 0px ; +} + +.dome-xIcon svg { + position:relative ; +} + +.dome-xBadge { + flex: 0 0 auto ; + display: inline ; + margin: 1px ; + padding: 1px 6px 1px 6px ; + height: 16px ; + fill: #dedede ; + color: #dedede ; + font-family: sans-serif ; + font-size: smaller ; + font-weight: bold ; + border-radius: 8px ; + background: #777 ; +} + +.dome-window-inactive .dome-xBadge, +.dome-disabled .dome-xBadge +{ + background: #ccc ; + color: #eee ; + fill: #eee ; +} + +.dome-xBadge label { + position: relative ; + bottom: -1px ; +} diff --git a/Ivette/src/dome/src/renderer/controls/icons.js b/Ivette/src/dome/src/renderer/controls/icons.js new file mode 100644 index 00000000000..808cd0f2ce7 --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/icons.js @@ -0,0 +1,156 @@ +// -------------------------------------------------------------------------- +// --- SVG Icons +// -------------------------------------------------------------------------- + +/** + @module dome/controls/icons + @description + Consult the [Icon Gallery](gallery-icons.html) for default icons. + You can [register](#.register) new icons or override existing ones + and [iterate](#.forEach) over the icon base. +*/ + +import React from 'react' ; +import Icons from './icons.json' ; +import './icons.css' ; +import _ from 'lodash' ; + +// -------------------------------------------------------------------------- +// --- Raw SVG element +// -------------------------------------------------------------------------- + +/** + @class + @property {string} id - icon's identifier (mandatory) + @property {string} [title] - icon's tool-tip (optional) + @property {number} [size] - icon's dimension in pixels (default: `12`) + @property {number} [offset] - vertical alignment offset (default: `- size * 0.125`) + @summary Raw SVG element. + @description + Consult the [Icon Gallery](gallery-icons.html) for default icons. +*/ +export function SVG( { id , title, size, offset } ) +{ + if (!id) return null; + const icon = Icons[id]; + if (!icon) return id; + if (size===undefined) size = 12 ; + if (offset===undefined) offset = _.floor( - size * 0.125 ); + return ( + <svg height={size} + width={size} + style={{bottom: offset }} + viewBox={icon.viewBox || "0 0 24 24"} > + { title && <title>{title}</title> } + <path d={icon.path}/> + </svg> + ); +} + +// -------------------------------------------------------------------------- +// --- Icon Component +// -------------------------------------------------------------------------- + +/** + @class + @summary Icon Component. + @property {string} id - icon's identifier (mandatory) + @property {string} [title] - icon's tool-tip (optional) + @property {function} [onClick] - callback when icon is clicked (optional) + @property {string} [fill] - icon's fill color (optional) + @property {number} [size] - icon's dimension in pixels (default `12`) + @property {number} [offset] - vertical alignment offset (default `-size * 0.125`) + @property {string} [className] - additional class name + @property {object} [style] - additional styles + @description + Consult the [Icon Gallery](gallery-icons.html) for default icons. +*/ +export function Icon( { id, title, onClick, fill, size, className='', offset, style } ) +{ + const divClass = 'dome-xIcon ' + className ; + const divStyle = fill ? Object.assign({fill},style) : style ; + return ( + <div className={divClass} + style={divStyle} + onClick={onClick}> + <SVG id={id} size={size} title={title} offset={offset} /> + </div> + ); +} + +// -------------------------------------------------------------------------- +// --- Badge Component +// -------------------------------------------------------------------------- + +/** + @class + @summary Rounded icon, number or letter. + @property {icon|number|string} [value] - badge content + @property {string} [title] - badge tool-tip (optional) + @property {function} [onClick] - badge on-click callback (optional) + @description + Depending on the type of value, display either a number, + a label, or the corresponding named icon. + Consult the [Icon Gallery](gallery-icons.html) for default icons. +*/ +export function Badge( { value, title, onClick } ) +{ + var content ; + if (Icons[value]) { + content = <Icon id={value} size={10} /> ; + } else { + const style = + ( typeof(value) === 'number' && value < 10 ) || + ( typeof(value) === 'string' && value.length == 1 ) ? + { paddingLeft: 2 , paddingRight: 2 } : {} ; + content = <label style={style} className='dome-text-label'>{value}</label>; + } + return ( + <div className="dome-xBadge" + title={title} onClick={onClick}> + {content} + </div> + ); +} + +// -------------------------------------------------------------------------- +// --- Icon Database +// -------------------------------------------------------------------------- + +/** + @summary Register a new icon. + @param {Object} icon - Icon's data to register (see below) + @description + The icon specification is an object with the following properties: + - `name`: icon's name + - `path`: svg path to draw the icon + - `title`: title for the icon (optional) + - `section`: section of the Icons (optional) + - `viewBox`: svg view-box property (optional, `"0 0 24 24"` by default) +*/ + +export function register(icon) { + const { name , ...deficon } = icon ; + if (!name) console.error(`[Dome] Icon has no name (skipped).`); + if (!deficon.path) console.error(`[Dome] Icon '${name}' has no path (skipped).`); + Icons[name] = deficon ; +} + +/** + @summary Iterate over registered icons. + @param {func} job - function applied to each icon + @description + See [register](#.register) for properties of the icon objects. +*/ + +export function forEach(job) { + for( var name in Icons ) { + job( Object.assign( { name } , Icons[name] )); + } +} + +// -------------------------------------------------------------------------- + +export default { Icon , Badge, SVG, register , forEach } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/controls/icons.json b/Ivette/src/dome/src/renderer/controls/icons.json new file mode 100644 index 00000000000..1afd562e8e0 --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/icons.json @@ -0,0 +1,319 @@ +{ + "SEARCH": { + "section": "Tools", + "title": "Search", + "viewBox": "0 0 22 24", + "path": "M15.429 11.143q0-2.478-1.761-4.239t-4.239-1.761-4.239 1.761-1.761 4.239 1.761 4.239 4.239 1.761 4.239-1.761 1.761-4.239zM22.286 22.286q0 0.696-0.509 1.205t-1.205 0.509q-0.723 0-1.205-0.509l-4.594-4.58q-2.397 1.661-5.344 1.661-1.915 0-3.663-0.743t-3.013-2.009-2.009-3.013-0.743-3.663 0.743-3.663 2.009-3.013 3.013-2.009 3.663-0.743 3.663 0.743 3.013 2.009 2.009 3.013 0.743 3.663q0 2.946-1.661 5.344l4.594 4.594q0.496 0.496 0.496 1.205z" + }, + "EXECUTE": { + "section": "Tools", + "viewBox": "0 0 16 16", + "path": "M5.683 11.282l0.645-0.903-0.707-0.707-0.903 0.645c-0.168-0.094-0.347-0.168-0.535-0.222l-0.183-1.095h-1l-0.183 1.095c-0.188 0.053-0.368 0.128-0.535 0.222l-0.903-0.645-0.707 0.707 0.645 0.903c-0.094 0.168-0.168 0.347-0.222 0.535l-1.095 0.183v1l1.095 0.183c0.053 0.188 0.128 0.368 0.222 0.535l-0.645 0.903 0.707 0.707 0.903-0.645c0.168 0.094 0.347 0.168 0.535 0.222l0.183 1.095h1l0.183-1.095c0.188-0.053 0.368-0.128 0.535-0.222l0.903 0.645 0.707-0.707-0.645-0.903c0.094-0.168 0.168-0.347 0.222-0.535l1.095-0.182v-1l-1.095-0.183c-0.053-0.188-0.128-0.368-0.222-0.535zM3.5 13.5c-0.552 0-1-0.448-1-1s0.448-1 1-1 1 0.448 1 1-0.448 1-1 1zM16 6v-1l-1.053-0.191c-0.019-0.126-0.044-0.25-0.074-0.372l0.899-0.58-0.383-0.924-1.046 0.226c-0.066-0.108-0.136-0.213-0.211-0.315l0.609-0.88-0.707-0.707-0.88 0.609c-0.102-0.074-0.207-0.145-0.315-0.211l0.226-1.046-0.924-0.383-0.58 0.899c-0.122-0.030-0.246-0.054-0.372-0.074l-0.191-1.053h-1l-0.191 1.053c-0.126 0.019-0.25 0.044-0.372 0.074l-0.58-0.899-0.924 0.383 0.226 1.046c-0.108 0.066-0.213 0.136-0.315 0.211l-0.88-0.609-0.707 0.707 0.609 0.88c-0.074 0.102-0.145 0.207-0.211 0.315l-1.046-0.226-0.383 0.924 0.899 0.58c-0.030 0.122-0.054 0.246-0.074 0.372l-1.053 0.191v1l1.053 0.191c0.019 0.126 0.044 0.25 0.074 0.372l-0.899 0.58 0.383 0.924 1.046-0.226c0.066 0.108 0.136 0.213 0.211 0.315l-0.609 0.88 0.707 0.707 0.88-0.609c0.102 0.074 0.207 0.145 0.315 0.211l-0.226 1.046 0.924 0.383 0.58-0.899c0.122 0.030 0.246 0.054 0.372 0.074l0.191 1.053h1l0.191-1.053c0.126-0.019 0.25-0.044 0.372-0.074l0.58 0.899 0.924-0.383-0.226-1.046c0.108-0.066 0.213-0.136 0.315-0.211l0.88 0.609 0.707-0.707-0.609-0.88c0.074-0.102 0.145-0.207 0.211-0.315l1.046 0.226 0.383-0.924-0.899-0.58c0.030-0.122 0.054-0.246 0.074-0.372l1.053-0.191zM10.5 7.675c-1.201 0-2.175-0.974-2.175-2.175s0.974-2.175 2.175-2.175 2.175 0.974 2.175 2.175c0 1.201-0.974 2.175-2.175 2.175z" + }, + "TUNINGS": { + "section": "Tools", + "title": "Tunings", + "viewBox": "0 0 24 24", + "path": "M4.714 18.857v1.714h-4.714v-1.714h4.714zM9.429 17.143q0.348 0 0.603 0.254t0.254 0.603v3.429q0 0.348-0.254 0.603t-0.603 0.254h-3.429q-0.348 0-0.603-0.254t-0.254-0.603v-3.429q0-0.348 0.254-0.603t0.603-0.254h3.429zM11.571 12v1.714h-11.571v-1.714h11.571zM3 5.143v1.714h-3v-1.714h3zM20.571 18.857v1.714h-9.857v-1.714h9.857zM7.714 3.429q0.348 0 0.603 0.254t0.254 0.603v3.429q0 0.348-0.254 0.603t-0.603 0.254h-3.429q-0.348 0-0.603-0.254t-0.254-0.603v-3.429q0-0.348 0.254-0.603t0.603-0.254h3.429zM16.286 10.286q0.348 0 0.603 0.254t0.254 0.603v3.429q0 0.348-0.254 0.603t-0.603 0.254h-3.429q-0.348 0-0.603-0.254t-0.254-0.603v-3.429q0-0.348 0.254-0.603t0.603-0.254h3.429zM20.571 12v1.714h-3v-1.714h3zM20.571 5.143v1.714h-11.571v-1.714h11.571z" + }, + "SETTINGS": { + "section": "Tools", + "title": "Configure", + "viewBox": "0 0 24 24", + "path": "M15.428 12q0-1.42-1.004-2.424t-2.424-1.004-2.424 1.004-1.004 2.424 1.004 2.424 2.424 1.004 2.424-1.004 1.004-2.424zM22.285 10.54v2.973q0 0.161-0.107 0.308t-0.268 0.174l-2.478 0.375q-0.254 0.723-0.522 1.219 0.469 0.67 1.433 1.848 0.134 0.161 0.134 0.335t-0.121 0.308q-0.362 0.496-1.326 1.446t-1.259 0.951q-0.161 0-0.348-0.121l-1.848-1.446q-0.589 0.308-1.219 0.509-0.214 1.821-0.388 2.491-0.094 0.375-0.482 0.375h-2.973q-0.188 0-0.328-0.114t-0.154-0.288l-0.375-2.464q-0.656-0.214-1.205-0.496l-1.888 1.433q-0.134 0.121-0.335 0.121-0.188 0-0.335-0.147-1.688-1.527-2.21-2.25-0.094-0.134-0.094-0.308 0-0.161 0.107-0.308 0.201-0.281 0.683-0.891t0.723-0.944q-0.362-0.67-0.549-1.326l-2.451-0.362q-0.174-0.027-0.281-0.167t-0.107-0.315v-2.973q0-0.161 0.107-0.308t0.254-0.174l2.491-0.375q0.188-0.616 0.522-1.232-0.536-0.763-1.433-1.848-0.134-0.161-0.134-0.321 0-0.134 0.121-0.308 0.348-0.482 1.319-1.44t1.266-0.958q0.174 0 0.348 0.134l1.848 1.433q0.589-0.308 1.219-0.509 0.214-1.821 0.388-2.491 0.094-0.375 0.482-0.375h2.973q0.188 0 0.328 0.114t0.154 0.288l0.375 2.464q0.656 0.214 1.205 0.496l1.902-1.433q0.121-0.121 0.321-0.121 0.174 0 0.335 0.134 1.728 1.594 2.21 2.277 0.094 0.107 0.094 0.295 0 0.161-0.107 0.308-0.201 0.281-0.683 0.891t-0.723 0.944q0.348 0.67 0.549 1.313l2.451 0.375q0.174 0.027 0.281 0.167t0.107 0.315z" + }, + "PRINT": { + "section": "Tools", + "title": "Print", + "viewBox": "0 0 22 24", + "path": "M5.143 20.571h12v-3.429h-12v3.429zM5.143 12h12v-5.143h-2.143q-0.536 0-0.911-0.375t-0.375-0.911v-2.143h-8.571v8.571zM20.571 12.857q0-0.348-0.254-0.603t-0.603-0.254-0.603 0.254-0.254 0.603 0.254 0.603 0.603 0.254 0.603-0.254 0.254-0.603zM22.286 12.857v5.571q0 0.174-0.127 0.301t-0.301 0.127h-3v2.143q0 0.536-0.375 0.911t-0.911 0.375h-12.857q-0.536 0-0.911-0.375t-0.375-0.911v-2.143h-3q-0.174 0-0.301-0.127t-0.127-0.301v-5.571q0-1.058 0.757-1.815t1.815-0.757h0.857v-7.286q0-0.536 0.375-0.911t0.911-0.375h9q0.536 0 1.179 0.268t1.018 0.643l2.036 2.036q0.375 0.375 0.643 1.018t0.268 1.179v3.429h0.857q1.058 0 1.815 0.757t0.757 1.815z" + }, + "RELOAD": { + "section": "Tools", + "title": "Reload", + "viewBox": "0 0 16 16", + "path": "M13.901 2.599c-1.463-1.597-3.565-2.599-5.901-2.599-4.418 0-8 3.582-8 8h1.5c0-3.59 2.91-6.5 6.5-6.5 1.922 0 3.649 0.835 4.839 2.161l-2.339 2.339h5.5v-5.5l-2.099 2.099z M14.5 8c0 3.59-2.91 6.5-6.5 6.5-1.922 0-3.649-0.835-4.839-2.161l2.339-2.339h-5.5v5.5l2.099-2.099c1.463 1.597 3.565 2.599 5.901 2.599 4.418 0 8-3.582 8-8h-1.5z" + }, + "SAVE": { + "section": "Tools", + "title": "Save", + "viewBox": "0 0 16 16", + "path": "M14 0h-14v16h16v-14l-2-2zM8 2h2v4h-2v-4zM14 14h-12v-12h1v5h9v-5h1.172l0.828 0.828v11.172z" + }, + "DUPLICATE": { + "section": "Tools", + "title": "Duplicate", + "viewBox": "0 0 16 16", + "path": "M10 4v-4h-7l-3 3v9h6v4h10v-12h-6zM3 1.414v1.586h-1.586l1.586-1.586zM1 11v-7h3v-3h5v3l-3 3v4h-5zM9 5.414v1.586h-1.586l1.586-1.586zM15 15h-8v-7h3v-3h5v10z" + }, + "LOCK": { + "section": "Tools", + "title":"Lock", + "viewBox":"0 0 16 16", + "path": "M12.249 6.5h-0.25v-3c0-1.654-1.346-3-3-3h-2c-1.654 0-3 1.346-3 3v3h-0.25c-0.413 0-0.75 0.338-0.75 0.75v7.5c0 0.412 0.337 0.75 0.75 0.75h8.5c0.412 0 0.75-0.338 0.75-0.75v-7.5c0-0.412-0.338-0.75-0.75-0.75zM5.999 3.5c0-0.551 0.449-1 1-1h2c0.551 0 1 0.449 1 1v3h-4v-3z" + }, + "EDIT": { + "section": "Tools", + "title":"Edit", + "viewBox":"0 0 16 16", + "path": "M13.5 0c1.381 0 2.5 1.119 2.5 2.5 0 0.563-0.186 1.082-0.5 1.5l-1 1-3.5-3.5 1-1c0.418-0.314 0.937-0.5 1.5-0.5zM1 11.5l-1 4.5 4.5-1 9.25-9.25-3.5-3.5-9.25 9.25zM11.181 5.681l-7 7-0.862-0.862 7-7 0.862 0.862z" + }, + "CHECK": { + "section": "Signs", + "title": "Check", + "viewBox": "0 0 24 24", + "path": "M22.379 7.58q0 0.536-0.375 0.911l-11.518 11.518q-0.375 0.375-0.911 0.375t-0.911-0.375l-6.67-6.67q-0.375-0.375-0.375-0.911t0.375-0.911l1.821-1.821q0.375-0.375 0.911-0.375t0.911 0.375l3.938 3.951 8.786-8.799q0.375-0.375 0.911-0.375t0.911 0.375l1.821 1.821q0.375 0.375 0.375 0.911z" + }, + "CROSS": { + "section": "Signs", + "title": "Cross", + "viewBox": "0 0 19 24", + "path": "M17.384 17.705q0 0.536-0.375 0.911l-1.821 1.821q-0.375 0.375-0.911 0.375t-0.911-0.375l-3.938-3.938-3.938 3.938q-0.375 0.375-0.911 0.375t-0.911-0.375l-1.821-1.821q-0.375-0.375-0.375-0.911t0.375-0.911l3.938-3.938-3.938-3.938q-0.375-0.375-0.375-0.911t0.375-0.911l1.821-1.821q0.375-0.375 0.911-0.375t0.911 0.375l3.938 3.938 3.938-3.938q0.375-0.375 0.911-0.375t0.911 0.375l1.821 1.821q0.375 0.375 0.375 0.911t-0.375 0.911l-3.938 3.938 3.938 3.938q0.375 0.375 0.375 0.911z" + }, + "WARNING": { + "section": "Signs", + "title": "Warning", + "viewBox": "0 0 24 24", + "path": "M13.714 18.415v-2.545q0-0.188-0.127-0.315t-0.301-0.127h-2.571q-0.174 0-0.301 0.127t-0.127 0.315v2.545q0 0.188 0.127 0.315t0.301 0.127h2.571q0.174 0 0.301-0.127t0.127-0.315zM13.688 13.406l0.241-6.147q0-0.161-0.134-0.254-0.174-0.147-0.321-0.147h-2.946q-0.147 0-0.321 0.147-0.134 0.094-0.134 0.281l0.228 6.121q0 0.134 0.134 0.221t0.321 0.087h2.478q0.188 0 0.315-0.087t0.141-0.221zM13.5 0.897l10.286 18.857q0.469 0.844-0.027 1.688-0.228 0.388-0.623 0.616t-0.85 0.228h-20.571q-0.455 0-0.85-0.228t-0.623-0.616q-0.496-0.844-0.027-1.688l10.286-18.857q0.228-0.415 0.629-0.656t0.871-0.241 0.871 0.241 0.629 0.656z" + }, + "INFO": { + "section": "Signs", + "title": "Information", + "viewBox": "0 0 6 16", + "path": "M5.717 12.571v1.143q0 0.232-0.17 0.402t-0.402 0.17h-4.571q-0.232 0-0.402-0.17t-0.17-0.402v-1.143q0-0.232 0.17-0.402t0.402-0.17h0.571v-3.429h-0.571q-0.232 0-0.402-0.17t-0.17-0.402v-1.143q0-0.232 0.17-0.402t0.402-0.17h3.429q0.232 0 0.402 0.17t0.17 0.402v5.143h0.571q0.232 0 0.402 0.17t0.17 0.402zM4.574 2.286v1.714q0 0.232-0.17 0.402t-0.402 0.17h-2.286q-0.232 0-0.402-0.17t-0.17-0.402v-1.714q0-0.232 0.17-0.402t0.402-0.17h2.286q0.232 0 0.402 0.17t0.17 0.402z" + }, + "HELP": { + "section": "Signs", + "title": "Help", + "viewBox": "0 0 9 16", + "path": "M5.874 11.214v2.143q0 0.143-0.107 0.25t-0.25 0.107h-2.143q-0.143 0-0.25-0.107t-0.107-0.25v-2.143q0-0.143 0.107-0.25t0.25-0.107h2.143q0.143 0 0.25 0.107t0.107 0.25zM8.696 5.857q0 0.482-0.138 0.902t-0.313 0.683-0.491 0.531-0.513 0.388-0.545 0.317q-0.366 0.205-0.612 0.58t-0.246 0.598q0 0.152-0.107 0.29t-0.25 0.138h-2.143q-0.134 0-0.228-0.165t-0.094-0.335v-0.402q0-0.741 0.58-1.397t1.277-0.969q0.527-0.241 0.75-0.5t0.223-0.679q0-0.375-0.415-0.661t-0.96-0.286q-0.58 0-0.964 0.259-0.313 0.223-0.955 1.027-0.116 0.143-0.277 0.143-0.107 0-0.223-0.071l-1.464-1.116q-0.116-0.089-0.138-0.223t0.049-0.25q1.429-2.375 4.143-2.375 0.714 0 1.438 0.277t1.304 0.741 0.946 1.138 0.366 1.415z" + }, + "ATTENTION": { + "section": "Signs", + "viewBox": "0 0 6 16", + "path": "M4.574 11.714v2q0 0.232-0.17 0.402t-0.402 0.17h-2.286q-0.232 0-0.402-0.17t-0.17-0.402v-2q0-0.232 0.17-0.402t0.402-0.17h2.286q0.232 0 0.402 0.17t0.17 0.402zM4.841 2.286l-0.25 6.857q-0.009 0.232-0.183 0.402t-0.406 0.17h-2.286q-0.232 0-0.406-0.17t-0.183-0.402l-0.25-6.857q-0.009-0.232 0.156-0.402t0.397-0.17h2.857q0.232 0 0.397 0.17t0.156 0.402z" + }, + "PLUS": { + "section": "Signs", + "viewBox": "0 0 13 16", + "path": "M12.575 7.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-3.714v3.714q0 0.357-0.25 0.607t-0.607 0.25h-1.714q-0.357 0-0.607-0.25t-0.25-0.607v-3.714h-3.714q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h3.714v-3.714q0-0.357 0.25-0.607t0.607-0.25h1.714q0.357 0 0.607 0.25t0.25 0.607v3.714h3.714q0.357 0 0.607 0.25t0.25 0.607z" + }, + "MINUS": { + "section": "Signs", + "viewBox": "0 0 13 16", + "path": "M12.575 7.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-10.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h10.857q0.357 0 0.607 0.25t0.25 0.607z" + }, + "TRASH": { + "section": "Desktop", + "title": "Trash", + "viewBox": "0 0 19 24", + "path": "M6.857 9.857v7.714q0 0.188-0.121 0.308t-0.308 0.121h-0.857q-0.188 0-0.308-0.121t-0.121-0.308v-7.714q0-0.188 0.121-0.308t0.308-0.121h0.857q0.188 0 0.308 0.121t0.121 0.308zM10.286 9.857v7.714q0 0.188-0.121 0.308t-0.308 0.121h-0.857q-0.188 0-0.308-0.121t-0.121-0.308v-7.714q0-0.188 0.121-0.308t0.308-0.121h0.857q0.188 0 0.308 0.121t0.121 0.308zM13.714 9.857v7.714q0 0.188-0.121 0.308t-0.308 0.121h-0.857q-0.188 0-0.308-0.121t-0.121-0.308v-7.714q0-0.188 0.121-0.308t0.308-0.121h0.857q0.188 0 0.308 0.121t0.121 0.308zM15.429 19.554v-12.696h-12v12.696q0 0.295 0.094 0.542t0.194 0.362 0.141 0.114h11.143q0.040 0 0.141-0.114t0.194-0.362 0.094-0.542zM6.429 5.143h6l-0.643-1.567q-0.094-0.121-0.228-0.147h-4.246q-0.134 0.027-0.228 0.147zM18.857 5.571v0.857q0 0.188-0.121 0.308t-0.308 0.121h-1.286v12.696q0 1.112-0.629 1.922t-1.513 0.81h-11.143q-0.884 0-1.513-0.783t-0.629-1.895v-12.75h-1.286q-0.188 0-0.308-0.121t-0.121-0.308v-0.857q0-0.188 0.121-0.308t0.308-0.121h4.138l0.938-2.237q0.201-0.496 0.723-0.844t1.058-0.348h4.286q0.536 0 1.058 0.348t0.723 0.844l0.938 2.237h4.138q0.188 0 0.308 0.121t0.121 0.308z" + }, + "FOLDER": { + "section": "Desktop", + "title": "Folder", + "viewBox": "0 0 22 24", + "path": "M20.573 18.428v-9.429q0-0.536-0.375-0.911t-0.911-0.375h-9.429q-0.536 0-0.911-0.375t-0.375-0.911v-0.857q0-0.536-0.375-0.911t-0.911-0.375h-4.286q-0.536 0-0.911 0.375t-0.375 0.911v12.857q0 0.536 0.375 0.911t0.911 0.375h16.286q0.536 0 0.911-0.375t0.375-0.911zM22.287 9v9.429q0 1.232-0.884 2.116t-2.116 0.884h-16.286q-1.232 0-2.116-0.884t-0.884-2.116v-12.857q0-1.232 0.884-2.116t2.116-0.884h4.286q1.232 0 2.116 0.884t0.884 2.116v0.429h9q1.232 0 2.116 0.884t0.884 2.116z" + }, + "FOLDER.OPEN": { + "section": "Desktop", + "title": "Folder (open)", + "viewBox": "0 0 26 24", + "path": "M23.853 12.469q0-0.469-0.71-0.469h-14.571q-0.536 0-1.145 0.288t-0.958 0.703l-3.938 4.862q-0.241 0.321-0.241 0.536 0 0.469 0.71 0.469h14.571q0.536 0 1.152-0.295t0.951-0.71l3.938-4.862q0.241-0.295 0.241-0.522zM8.571 10.286h10.286v-2.143q0-0.536-0.375-0.911t-0.911-0.375h-7.714q-0.536 0-0.911-0.375t-0.375-0.911v-0.857q0-0.536-0.375-0.911t-0.911-0.375h-4.286q-0.536 0-0.911 0.375t-0.375 0.911v11.424l3.429-4.219q0.589-0.71 1.554-1.172t1.875-0.462zM25.567 12.469q0 0.83-0.616 1.607l-3.951 4.862q-0.576 0.71-1.554 1.172t-1.875 0.462h-14.571q-1.232 0-2.116-0.884t-0.884-2.116v-12.857q0-1.232 0.884-2.116t2.116-0.884h4.286q1.232 0 2.116 0.884t0.884 2.116v0.429h7.286q1.232 0 2.116 0.884t0.884 2.116v2.143h2.571q0.723 0 1.326 0.328t0.897 0.944q0.201 0.429 0.201 0.911z" + }, + "DISPLAY": { + "section": "Desktop", + "viewBox": "0 0 24 24", + "title": "Display", + "path": "M21 15.984v-12h-18v12h18zM21 2.016q0.797 0 1.406 0.586t0.609 1.383v12q0 0.797-0.609 1.406t-1.406 0.609h-6.984v2.016h1.969v1.969h-7.969v-1.969h1.969v-2.016h-6.984q-0.797 0-1.406-0.609t-0.609-1.406v-12q0-0.797 0.609-1.383t1.406-0.586h18z" + }, + "ITEMS.GRID": { + "section": "Desktop", + "viewBox": "0 0 16 16", + "title": "Items (grid)", + "path": "M4.571 11.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM4.571 6.571v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM10.286 11.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM4.571 2v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM10.286 6.571v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM16 11.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM10.286 2v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM16 6.571v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM16 2v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607z" + }, + "ITEMS.LIST": { + "section": "Desktop", + "viewBox": "0 0 16 16", + "title": "Items (list)", + "path": "M4.571 11.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM4.571 6.571v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM16 11.143v1.714q0 0.357-0.25 0.607t-0.607 0.25h-8.571q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h8.571q0.357 0 0.607 0.25t0.25 0.607zM4.571 2v1.714q0 0.357-0.25 0.607t-0.607 0.25h-2.857q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h2.857q0.357 0 0.607 0.25t0.25 0.607zM16 6.571v1.714q0 0.357-0.25 0.607t-0.607 0.25h-8.571q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h8.571q0.357 0 0.607 0.25t0.25 0.607zM16 2v1.714q0 0.357-0.25 0.607t-0.607 0.25h-8.571q-0.357 0-0.607-0.25t-0.25-0.607v-1.714q0-0.357 0.25-0.607t0.607-0.25h8.571q0.357 0 0.607 0.25t0.25 0.607z" + }, + "HOME": { + "section": "Desktop", + "title": "Home", + "viewBox": "0 0 22 24", + "path": "M18.857 13.286v6.429q0 0.348-0.254 0.603t-0.603 0.254h-5.143v-5.143h-3.429v5.143h-5.143q-0.348 0-0.603-0.254t-0.254-0.603v-6.429q0-0.013 0.007-0.040t0.007-0.040l7.701-6.348 7.701 6.348q0.013 0.027 0.013 0.080zM21.844 12.362l-0.83 0.991q-0.107 0.121-0.281 0.147h-0.040q-0.174 0-0.281-0.094l-9.268-7.728-9.268 7.728q-0.161 0.107-0.321 0.094-0.174-0.027-0.281-0.147l-0.83-0.991q-0.107-0.134-0.094-0.315t0.147-0.288l9.629-8.022q0.429-0.348 1.018-0.348t1.018 0.348l3.268 2.732v-2.612q0-0.188 0.121-0.308t0.308-0.121h2.571q0.188 0 0.308 0.121t0.121 0.308v5.464l2.933 2.438q0.134 0.107 0.147 0.288t-0.094 0.315z" + }, + "SIDEBAR": { + "section": "Desktop", + "title": "Sidebar", + "viewBox": "0 0 20 20", + "path": "M7 3h-5v14h5v-14zM9 3v14h9v-14h-9zM0 3c0-1.1 0.9-2 2-2h16c1.105 0 2 0.895 2 2v0 14c0 1.105-0.895 2-2 2v0h-16c-1.105 0-2-0.895-2-2v0-14zM3 4h3v2h-3v-2zM3 7h3v2h-3v-2zM3 10h3v2h-3v-2z" + }, + "FILE": { + "section": "Desktop", + "title": "File", + "viewBox": "0 0 24 24", + "path": "M19.661 5.089q0.375 0.375 0.643 1.018t0.268 1.179v15.429q0 0.536-0.375 0.911t-0.911 0.375h-18q-0.536 0-0.911-0.375t-0.375-0.911v-21.429q0-0.536 0.375-0.911t0.911-0.375h12q0.536 0 1.179 0.268t1.018 0.643zM13.714 1.821v5.036h5.036q-0.134-0.388-0.295-0.549l-4.192-4.192q-0.161-0.161-0.549-0.295zM18.857 22.286v-13.714h-5.571q-0.536 0-0.911-0.375t-0.375-0.911v-5.571h-10.286v20.571h17.143z" + }, + "CIRC.PLUS": { + "section": "Buttons", + "title": "Add", + "viewBox": "0 0 24 24", + "path": "M17.999 12.857v-1.714q0-0.348-0.254-0.603t-0.603-0.254h-3.429v-3.429q0-0.348-0.254-0.603t-0.603-0.254h-1.714q-0.348 0-0.603 0.254t-0.254 0.603v3.429h-3.429q-0.348 0-0.603 0.254t-0.254 0.603v1.714q0 0.348 0.254 0.603t0.603 0.254h3.429v3.429q0 0.348 0.254 0.603t0.603 0.254h1.714q0.348 0 0.603-0.254t0.254-0.603v-3.429h3.429q0.348 0 0.603-0.254t0.254-0.603zM22.285 12q0 2.799-1.379 5.163t-3.743 3.743-5.163 1.379-5.163-1.379-3.743-3.743-1.379-5.163 1.379-5.163 3.743-3.743 5.163-1.379 5.163 1.379 3.743 3.743 1.379 5.163z" + }, + "CIRC.MINUS": { + "section": "Buttons", + "title": "Remove", + "viewBox": "0 0 24 24", + "path": "M17.999 12.857v-1.714q0-0.348-0.254-0.603t-0.603-0.254h-10.286q-0.348 0-0.603 0.254t-0.254 0.603v1.714q0 0.348 0.254 0.603t0.603 0.254h10.286q0.348 0 0.603-0.254t0.254-0.603zM22.285 12q0 2.799-1.379 5.163t-3.743 3.743-5.163 1.379-5.163-1.379-3.743-3.743-1.379-5.163 1.379-5.163 3.743-3.743 5.163-1.379 5.163 1.379 3.743 3.743 1.379 5.163z" + }, + "CIRC.CLOSE": { + "section": "Buttons", + "title": "Close", + "viewBox": "0 0 24 24", + "path": "M8.973 17.102q0.348 0 0.603-0.254l2.424-2.424 2.424 2.424q0.254 0.254 0.603 0.254 0.362 0 0.616-0.254l1.205-1.205q0.254-0.254 0.254-0.616 0-0.348-0.254-0.603l-2.424-2.424 2.424-2.424q0.254-0.254 0.254-0.603 0-0.362-0.254-0.616l-1.205-1.205q-0.254-0.254-0.616-0.254-0.348 0-0.603 0.254l-2.424 2.424-2.424-2.424q-0.254-0.254-0.603-0.254-0.362 0-0.616 0.254l-1.205 1.205q-0.254 0.254-0.254 0.616 0 0.348 0.254 0.603l2.424 2.424-2.424 2.424q-0.254 0.254-0.254 0.603 0 0.362 0.254 0.616l1.205 1.205q0.254 0.254 0.616 0.254zM12 22.285q-2.799 0-5.163-1.379t-3.743-3.743-1.379-5.163 1.379-5.163 3.743-3.743 5.163-1.379 5.163 1.379 3.743 3.743 1.379 5.163-1.379 5.163-3.743 3.743-5.163 1.379z" + }, + "CIRC.CHECK": { + "section": "Buttons", + "title": "Check", + "viewBox": "0 0 24 24", + "path": "M18.91 9.83q0-0.375-0.241-0.616l-1.219-1.205q-0.254-0.254-0.603-0.254t-0.603 0.254l-5.464 5.451-3.027-3.027q-0.254-0.254-0.603-0.254t-0.603 0.254l-1.219 1.205q-0.241 0.241-0.241 0.616 0 0.362 0.241 0.603l4.848 4.848q0.254 0.254 0.603 0.254 0.362 0 0.616-0.254l7.272-7.272q0.241-0.241 0.241-0.603zM22.285 12q0 2.799-1.379 5.163t-3.743 3.743-5.163 1.379-5.163-1.379-3.743-3.743-1.379-5.163 1.379-5.163 3.743-3.743 5.163-1.379 5.163 1.379 3.743 3.743 1.379 5.163z" + }, + "CIRC.QUESTION": { + "section": "Buttons", + "title": "Check", + "viewBox": "0 0 24 24", + "path": "M13.714 18.429v-2.571q0-0.188-0.121-0.308t-0.308-0.121h-2.571q-0.188 0-0.308 0.121t-0.121 0.308v2.571q0 0.188 0.121 0.308t0.308 0.121h2.571q0.188 0 0.308-0.121t0.121-0.308zM17.142 9.429q0-1.179-0.743-2.183t-1.855-1.554-2.277-0.549q-3.254 0-4.969 2.853-0.201 0.321 0.107 0.563l1.768 1.339q0.094 0.080 0.254 0.080 0.214 0 0.335-0.161 0.71-0.911 1.152-1.232 0.455-0.321 1.152-0.321 0.643 0 1.145 0.348t0.502 0.79q0 0.509-0.268 0.817t-0.911 0.603q-0.844 0.375-1.547 1.158t-0.703 1.681v0.482q0 0.188 0.121 0.308t0.308 0.121h2.571q0.188 0 0.308-0.121t0.121-0.308q0-0.254 0.288-0.663t0.73-0.663q0.429-0.241 0.656-0.382t0.616-0.469 0.596-0.643 0.375-0.81 0.167-1.085zM22.285 12q0 2.799-1.379 5.163t-3.743 3.743-5.163 1.379-5.163-1.379-3.743-3.743-1.379-5.163 1.379-5.163 3.743-3.743 5.163-1.379 5.163 1.379 3.743 3.743 1.379 5.163z" + }, + "CIRC.INFO": { + "section": "Buttons", + "title": "Info", + "viewBox": "0 0 24 24", + "path": "M15.428 18.429v-2.143q0-0.188-0.121-0.308t-0.308-0.121h-1.286v-6.857q0-0.188-0.121-0.308t-0.308-0.121h-4.286q-0.188 0-0.308 0.121t-0.121 0.308v2.143q0 0.188 0.121 0.308t0.308 0.121h1.286v4.286h-1.286q-0.188 0-0.308 0.121t-0.121 0.308v2.143q0 0.188 0.121 0.308t0.308 0.121h6q0.188 0 0.308-0.121t0.121-0.308zM13.714 6.429v-2.143q0-0.188-0.121-0.308t-0.308-0.121h-2.571q-0.188 0-0.308 0.121t-0.121 0.308v2.143q0 0.188 0.121 0.308t0.308 0.121h2.571q0.188 0 0.308-0.121t0.121-0.308zM22.285 12q0 2.799-1.379 5.163t-3.743 3.743-5.163 1.379-5.163-1.379-3.743-3.743-1.379-5.163 1.379-5.163 3.743-3.743 5.163-1.379 5.163 1.379 3.743 3.743 1.379 5.163z" + }, + "SWITCH.OFF": { + "section": "Buttons", + "title": "Off", + "viewBox": "0 0 32 28", + "path": "M18 14c0-4.406-3.594-8-8-8s-8 3.594-8 8 3.594 8 8 8 8-3.594 8-8zM30 14c0-4.406-3.594-8-8-8h-6.031c2.438 1.828 4.031 4.734 4.031 8s-1.594 6.172-4.031 8h6.031c4.406 0 8-3.594 8-8zM32 14c0 5.516-4.484 10-10 10h-12c-5.516 0-10-4.484-10-10s4.484-10 10-10h12c5.516 0 10 4.484 10 10z" + }, + "SWITCH.ON": { + "section": "Buttons", + "title": "On", + "viewBox": "0 0 32 28", + "path": "M0 14c0-5.516 4.484-10 10-10h12c5.516 0 10 4.484 10 10s-4.484 10-10 10h-12c-5.516 0-10-4.484-10-10zM22 22c4.406 0 8-3.594 8-8s-3.594-8-8-8-8 3.594-8 8 3.594 8 8 8z" + }, + "TRIANGLE.LEFT": { + "section": "Arrows", + "title": "Left", + "viewBox": "0 0 16 16", + "path": "M13 2l-10 6 10 6z" + }, + "TRIANGLE.UP": { + "section": "Arrows", + "title": "Up", + "viewBox": "0 0 16 16", + "path": "M2 13l6-10 6 10z" + }, + "TRIANGLE.RIGHT": { + "section": "Arrows", + "title": "Right", + "viewBox": "0 0 16 16", + "path": "M3 2l10 6-10 6z" + }, + "TRIANGLE.DOWN": { + "section": "Arrows", + "title": "Down", + "viewBox": "0 0 16 16", + "path": "M14 3l-6 10-6-10z" + }, + "ANGLE.LEFT": { + "section": "Arrows", + "title": "Left", + "viewBox": "0 0 11 16", + "path": "M10.166 3.259l-4.741 4.741 4.741 4.741q0.17 0.17 0.17 0.402t-0.17 0.402l-1.482 1.482q-0.17 0.17-0.402 0.17t-0.402-0.17l-6.625-6.625q-0.17-0.17-0.17-0.402t0.17-0.402l6.625-6.625q0.17-0.17 0.402-0.17t0.402 0.17l1.482 1.482q0.17 0.17 0.17 0.402t-0.17 0.402z" + }, + "ANGLE.RIGHT": { + "section": "Arrows", + "title": "Right", + "viewBox": "0 0 11 16", + "path": "M10.166 8.402l-6.625 6.625q-0.17 0.17-0.402 0.17t-0.402-0.17l-1.482-1.482q-0.17-0.17-0.17-0.402t0.17-0.402l4.741-4.741-4.741-4.741q-0.17-0.17-0.17-0.402t0.17-0.402l1.482-1.482q0.17-0.17 0.402-0.17t0.402 0.17l6.625 6.625q0.17 0.17 0.17 0.402t-0.17 0.402z" + }, + "ANGLE.UP": { + "section": "Arrows", + "title": "Up", + "viewBox": "0 0 16 16", + "path": "M15.027 10.978l-1.482 1.473q-0.17 0.17-0.402 0.17t-0.402-0.17l-4.741-4.741-4.741 4.741q-0.17 0.17-0.402 0.17t-0.402-0.17l-1.482-1.473q-0.17-0.17-0.17-0.406t0.17-0.406l6.625-6.616q0.17-0.17 0.402-0.17t0.402 0.17l6.625 6.616q0.17 0.17 0.17 0.406t-0.17 0.406z" + }, + "ANGLE.DOWN": { + "section": "Arrows", + "title": "Down", + "viewBox": "0 0 16 16", + "path": "M15.027 5.835l-6.625 6.616q-0.17 0.17-0.402 0.17t-0.402-0.17l-6.625-6.616q-0.17-0.17-0.17-0.406t0.17-0.406l1.482-1.473q0.17-0.17 0.402-0.17t0.402 0.17l4.741 4.741 4.741-4.741q0.17-0.17 0.402-0.17t0.402 0.17l1.482 1.473q0.17 0.17 0.17 0.406t-0.17 0.406z" + }, + "DIR.VERTICAL": { + "section": "Arrows", + "title": "Vertical", + "viewBox": "0 0 7 16", + "path": "M6.287 2.857q0 0.232-0.17 0.402t-0.402 0.17h-1.143v9.143h1.143q0.232 0 0.402 0.17t0.17 0.402-0.17 0.402l-2.286 2.286q-0.17 0.17-0.402 0.17t-0.402-0.17l-2.286-2.286q-0.17-0.17-0.17-0.402t0.17-0.402 0.402-0.17h1.143v-9.143h-1.143q-0.232 0-0.402-0.17t-0.17-0.402 0.17-0.402l2.286-2.286q0.17-0.17 0.402-0.17t0.402 0.17l2.286 2.286q0.17 0.17 0.17 0.402z" + }, + "DIR.HORIZONTAL": { + "section": "Arrows", + "title": "Horizontal", + "viewBox": "0 0 16 16", + "path": "M16 8q0 0.232-0.17 0.402l-2.286 2.286q-0.17 0.17-0.402 0.17t-0.402-0.17-0.17-0.402v-1.143h-9.143v1.143q0 0.232-0.17 0.402t-0.402 0.17-0.402-0.17l-2.286-2.286q-0.17-0.17-0.17-0.402t0.17-0.402l2.286-2.286q0.17-0.17 0.402-0.17t0.402 0.17 0.17 0.402v1.143h9.143v-1.143q0-0.232 0.17-0.402t0.402-0.17 0.402 0.17l2.286 2.286q0.17 0.17 0.17 0.402z" + }, + "DIR.EXPAND": { + "section": "Arrows", + "title": "Expand", + "viewBox": "0 0 16 16", + "path": "M16 0h-6.5l2.5 2.5-3 3 1.5 1.5 3-3 2.5 2.5z M16 16v-6.5l-2.5 2.5-3-3-1.5 1.5 3 3-2.5 2.5z M0 16h6.5l-2.5-2.5 3-3-1.5-1.5-3 3-2.5-2.5z M0 0v6.5l2.5-2.5 3 3 1.5-1.5-3-3 2.5-2.5z" + }, + "MEDIA.PREV": { + "section": "Media", + "title": "Previous", + "viewBox": "0 0 14 24", + "path": "M13.112 1.888q0.254-0.254 0.429-0.174t0.174 0.429v19.714q0 0.348-0.174 0.429t-0.429-0.174l-9.509-9.509q-0.121-0.121-0.174-0.254v9.080q0 0.348-0.254 0.603t-0.603 0.254h-1.714q-0.348 0-0.603-0.254t-0.254-0.603v-18.857q0-0.348 0.254-0.603t0.603-0.254h1.714q0.348 0 0.603 0.254t0.254 0.603v9.080q0.054-0.147 0.174-0.254z" + }, + "MEDIA.NEXT": { + "section": "Media", + "title": "Next", + "viewBox": "0 0 14 24", + "path": "M0.603 22.112q-0.254 0.254-0.429 0.174t-0.174-0.429v-19.714q0-0.348 0.174-0.429t0.429 0.174l9.509 9.509q0.107 0.107 0.174 0.254v-9.080q0-0.348 0.254-0.603t0.603-0.254h1.714q0.348 0 0.603 0.254t0.254 0.603v18.857q0 0.348-0.254 0.603t-0.603 0.254h-1.714q-0.348 0-0.603-0.254t-0.254-0.603v-9.080q-0.067 0.134-0.174 0.254z" + }, + "MEDIA.PLAY": { + "section": "Media", + "viewBox": "0 0 19 24", + "path": "M18.547 12.415l-17.786 9.884q-0.308 0.174-0.529 0.040t-0.221-0.482v-19.714q0-0.348 0.221-0.482t0.529 0.040l17.786 9.884q0.308 0.174 0.308 0.415t-0.308 0.415z" + }, + "MEDIA.PAUSE": { + "section": "Media", + "viewBox": "0 0 24 24", + "path": "M20.571 2.571v18.857q0 0.348-0.254 0.603t-0.603 0.254h-6.857q-0.348 0-0.603-0.254t-0.254-0.603v-18.857q0-0.348 0.254-0.603t0.603-0.254h6.857q0.348 0 0.603 0.254t0.254 0.603zM8.571 2.571v18.857q0 0.348-0.254 0.603t-0.603 0.254h-6.857q-0.348 0-0.603-0.254t-0.254-0.603v-18.857q0-0.348 0.254-0.603t0.603-0.254h6.857q0.348 0 0.603 0.254t0.254 0.603z" + }, + "MEDIA.STOP": { + "section": "Media", + "viewBox": "0 0 24 24", + "path": "M20.571 2.571v18.857q0 0.348-0.254 0.603t-0.603 0.254h-18.857q-0.348 0-0.603-0.254t-0.254-0.603v-18.857q0-0.348 0.254-0.603t0.603-0.254h18.857q0.348 0 0.603 0.254t0.254 0.603z" + }, + "MEDIA.EJECT": { + "section": "Media", + "viewBox": "0 0 21 24", + "path": "M0.188 13.112l9.509-9.509q0.254-0.254 0.603-0.254t0.603 0.254l9.509 9.509q0.254 0.254 0.174 0.429t-0.429 0.174h-19.714q-0.348 0-0.429-0.174t0.174-0.429zM19.728 20.571h-18.857q-0.348 0-0.603-0.254t-0.254-0.603v-3.429q0-0.348 0.254-0.603t0.603-0.254h18.857q0.348 0 0.603 0.254t0.254 0.603v3.429q0 0.348-0.254 0.603t-0.603 0.254z" + }, + "COMPONENT": { + "section": "Software", + "title": "Component", + "viewBox": "0 0 16 16", + "path": "M8 14.545l5.714-3.116v-5.679l-5.714 2.080v6.714zM7.429 6.821l6.232-2.268-6.232-2.268-6.232 2.268zM14.857 4.571v6.857q0 0.313-0.161 0.58t-0.438 0.42l-6.286 3.429q-0.25 0.143-0.545 0.143t-0.545-0.143l-6.286-3.429q-0.277-0.152-0.438-0.42t-0.161-0.58v-6.857q0-0.357 0.205-0.652t0.545-0.42l6.286-2.286q0.196-0.071 0.393-0.071t0.393 0.071l6.286 2.286q0.339 0.125 0.545 0.42t0.205 0.652z" + }, + "PACKAGE": { + "section": "Software", + "title": "Package", + "viewBox": "0 0 21 16", + "path": "M5.714 14.571l3.429-1.714v-2.804l-3.429 1.464v3.054zM5.143 10.518l3.607-1.545-3.607-1.545-3.607 1.545zM14.857 14.571l3.429-1.714v-2.804l-3.429 1.464v3.054zM14.286 10.518l3.607-1.545-3.607-1.545-3.607 1.545zM10.286 7.902l3.429-1.473v-2.375l-3.429 1.464v2.384zM9.714 4.518l3.938-1.688-3.938-1.688-3.938 1.688zM19.429 9.143v3.714q0 0.321-0.17 0.598t-0.464 0.42l-4 2q-0.223 0.125-0.509 0.125t-0.509-0.125l-4-2q-0.045-0.018-0.063-0.036-0.018 0.018-0.063 0.036l-4 2q-0.223 0.125-0.509 0.125t-0.509-0.125l-4-2q-0.295-0.143-0.464-0.42t-0.17-0.598v-3.714q0-0.339 0.192-0.625t0.504-0.429l3.875-1.661v-3.571q0-0.339 0.192-0.625t0.504-0.429l4-1.714q0.205-0.089 0.446-0.089t0.446 0.089l4 1.714q0.313 0.143 0.504 0.429t0.192 0.625v3.571l3.875 1.661q0.321 0.143 0.509 0.429t0.188 0.625z" + } + +} diff --git a/Ivette/src/dome/src/renderer/controls/labels.css b/Ivette/src/dome/src/renderer/controls/labels.css new file mode 100644 index 00000000000..e7417b8bd75 --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/labels.css @@ -0,0 +1,18 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling Labels --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xLabel { + padding: 2px ; + margin: 2px 4px ; +} + +.dome-xLabel .dome-xIcon { + margin-right: 4px ; +} + +.dome-xLabel.dome-text-descr { + overflow: auto ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/controls/labels.js b/Ivette/src/dome/src/renderer/controls/labels.js new file mode 100644 index 00000000000..e407ce76c54 --- /dev/null +++ b/Ivette/src/dome/src/renderer/controls/labels.js @@ -0,0 +1,97 @@ +// -------------------------------------------------------------------------- +// --- Labels +// -------------------------------------------------------------------------- + +/** @module dome/controls/labels */ + +import React from 'react' ; +import labels from './labels.css' ; +import { Icon } from './icons' ; + +// -------------------------------------------------------------------------- +// --- Generic Label +// -------------------------------------------------------------------------- + +const addClass = (a,b) => b ? a + ' ' + b : a ; + +const makeLabel = (classes,props) => ( + <label className={addClass(classes,props.className)} + title={props.title} + style={props.style} > + {props.icon && <Icon title={props.title} id={props.icon}/>} + {props.label} + {props.text} + {props.children} + </label> +); + +// -------------------------------------------------------------------------- +// --- CSS Classes +// -------------------------------------------------------------------------- + +const LABEL = "dome-xLabel dome-text-label" ; +const TITLE = "dome-xLabel dome-text-title" ; +const DESCR = "dome-xLabel dome-text-descr" ; +const TDATA = "dome-xLabel dome-text-data" ; +const TCODE = "dome-xLabel dome-text-code" ; + +// -------------------------------------------------------------------------- +// --- Components +// -------------------------------------------------------------------------- + +/** + @class + @summary Component labels. + @property {string} [label] - Textual content (prepend to children components, if any) + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Label tooltip (optional) + @property {string} [className] - Additional class + @property {object} [style] - Additional CSS style +*/ +export const Label = (props) => makeLabel(LABEL,props); + +/** + @class + @summary Title and headings. + @property {string} [label] - Textual content (prepend to children components, if any) + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Label tooltip (optional) + @property {string} [className] - Additional class + @property {object} [style] - Additional CSS style +*/ +export const Title = (props) => makeLabel(TITLE,props); + +/** + @class + @summary Description, textbook content. + @property {string} [label] - Textual content (prepend to children components, if any) + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Label tooltip (optional) + @property {string} [className] - Additional class + @property {object} [style] - Additional CSS style +*/ +export const Descr = (props) => makeLabel(DESCR,props); + +/** + @class + @summary Selectable textual information. + @property {string} [label] - Textual content (prepend to children components, if any) + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Label tooltip (optional) + @property {string} [className] - Additional class + @property {object} [style] - Additional CSS style +*/ +export const Data = (props) => makeLabel(TDATA,props); + +/** + @class + @summary Selectable source-code content. + @property {string} [text] - Textual content (prepend to children components, if any) + @property {string} [icon] - Label icon (optional, on left side) + @property {string} [title] - Label tooltip (optional) + @property {string} [className] - Additional class + @property {object} [style] - Additional CSS style +*/ +export const Code = (props) => makeLabel(TCODE,props); + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/dialogs.js b/Ivette/src/dome/src/renderer/dialogs.js new file mode 100644 index 00000000000..92f5416323c --- /dev/null +++ b/Ivette/src/dome/src/renderer/dialogs.js @@ -0,0 +1,318 @@ +/** + @module dome/dialogs + @description + Various kind of (modal) dialogs attached to the main application window. + */ + +import { remote } from 'electron' ; +import System from 'dome/system' ; + +// -------------------------------------------------------------------------- +// --- Message Box +// -------------------------------------------------------------------------- + +const defaultItems = [ + { value:undefined }, + { value:true, label:'Ok' } +]; + +const valueLabel = (v) => { + switch(v) { + case undefined: return 'Cancel' ; + case true: return 'Ok' ; + case false: return 'No' ; + default: return ''+v ; + } +}; + +const itemLabel = ({value,label}) => label || valueLabel(value) ; +const isDefault = ({value,label}) => value===true || label==='Ok' || label==='Yes' ; +const isCancel = ({value,label}) => !value || label==='Cancel' || label==='No' ; + +/** + @summary Show a configurable message box. + @parameter {object} options - configuration (see above) + @return {Promise} the selected option (see above) + @description +The available fields and options for configuring the dialog are: + +| Options | Type | Description | +|:--------|:----:|:------------| +| `kind` | `'none','info','error','warning'` | Icon of the message box | +| `title` | `string` (_opt._) | Heading of message box | +| `message` | `string` | Message text | +| `buttons` | `button[]` (_opt._) | Dialog buttons | +| `defaultValue` | (any) (_opt._) | Value of the default button | +| `cancelValue` | (any) (_opt._) | Value of the cancel key | + +The dialog buttons are specified by objects with the following fields: + +| Button Field | Type | Description | +|:-------------|:----:|:------------| +| `label` | `string` | Button label | +| `value` | (any) | Button identifier (items only) | + +The returned promise object is never rejected, and is asynchronously +resolved into: +- the cancel value if the cancel key is pressed, +- the default value if the enter key is pressed, +- or the value of the clicked button otherwised. + +The default buttons are `"Ok"` and `"Cancel"` associated to values `true` and +`undefined`, which are also associated to the enter and cancel keys. +Unless specified, the default value is associated with the first button +with 'true' value or 'Ok' or 'Yes' label, +and the cancel value is the first button with a falsy value or 'Cancel' +or 'No' label. +*/ +export function showMessageBox( options ) +{ + const { + kind, + title, + message, + defaultValue, + cancelValue, + buttons = defaultItems + } = options ; + + const labels = buttons.map(itemLabel); + let defaultId = + defaultValue === undefined + ? buttons.findIndex(isDefault) + : buttons.findIndex((a) => a.value === defaultValue); + let cancelId = + cancelValue === undefined + ? buttons.findIndex(isCancel) + : buttons.findIndex((a) => a.value === cancelValue); + + if (cancelId === defaultId) cancelId = -1; + + return remote.dialog.showMessageBox( + remote.getCurrentWindow(), + { + type:kind, + message: message && title, + detail: message || title, + defaultId, cancelId, buttons: labels + } + ).then((result) => { + let itemIndex = result ? result.response : -1 ; + return itemIndex ? buttons[itemIndex].value : cancelValue ; + }); +} + +// -------------------------------------------------------------------------- +// --- openFile dialog +// -------------------------------------------------------------------------- + +import filepath from 'path' ; +const defaultPath = (path) => filepath.extname(path) ? filepath.dirname(path) : path ; + +/** + @summary Show a dialog for opening file. + @parameter {object} options - configuration (see above) + @return {Promise} the selected file (see above) + @description +The available fields and options for configuring the dialog are: + +| Options | Type | Description | +|:--------|:----:|:------------| +| `message` | `string` (_opt._) | Prompt message | +| `label` | `string` (_opt._) | Open button label | +| `path` | `filepath` (_opt._) | Initially selected path | +| `hidden` | `boolean` (_opt._) | Show hidden files (not by default) | +| `filters` | `filter[]` (_opt._) | File filters (all files by default) | + +The file filters are object with the following fields: + +| Filter Field | Type | Description | +|:-------------|:----:|:------------| +| `name` | `string` | Filter name | +| `extensions` | `string[]` | Allowed file extensions, _without_ dots («.») | + +A file filter with `extensions:["*"]` would accept any file extension. + +The returned promise object will be asynchronously: +- either _resolved_ with `undefined` if no file has been selected, +- or _resolved_ with the selected path + +The promise is never rejected. + +*/ +export function showOpenFile( options ) +{ + const { message, label, path, hidden, filters } = options ; + const properties = [ 'openFile' ]; + if (hidden) properties.push('showHiddenFiles'); + + return remote.dialog.showOpenDialog( + remote.getCurrentWindow(), + { + message, buttonLabel: label, + defaultPath: path && defaultPath(path), + properties, filters + } + ).then(result => { + if (!result.canceled && result.filePaths && result.filePaths.length > 0) + return result.filePaths[0] ; + else + return undefined ; + }); +} + +/** + @summary Show a dialog for opening file. + @parameter {object} options - configuration (see above) + @return {Promise} the selected file(s) (see above) + @description +The available fields and options for configuring the dialog are: + +| Options | Type | Description | +|:--------|:----:|:------------| +| `message` | `string` (_opt._) | Prompt message | +| `label` | `string` (_opt._) | Open button label | +| `path` | `filepath` (_opt._) | Initially selected path | +| `hidden` | `boolean` (_opt._) | Show hidden files (not by default) | +| `filters` | `filter[]` (_opt._) | File filters (all files by default) | + +The file filters are object with the following fields: + +| Filter Field | Type | Description | +|:-------------|:----:|:------------| +| `name` | `string` | Filter name | +| `extensions` | `string[]` | Allowed file extensions, _without_ dots («.») | + +A file filter with `extensions:["*"]` would accept any file extension. + +The returned promise object will be asynchronously: +- either _resolved_ with `undefined` if no file has been selected, +- or _resolved_ with the selected paths + +The promise is never rejected. + +*/ +export function showOpenFiles( options ) +{ + const { message, label, path, hidden, filters } = options ; + const properties = [ 'openFile', 'multiSelections' ]; + if (hidden) properties.push('showHiddenFiles'); + + return remote.dialog.showOpenDialog( + remote.getCurrentWindow(), + { + message, buttonLabel: label, + defaultPath: path && defaultPath(path), + properties, filters + } + ).then(result => { + if (!result.canceled && result.filePaths && result.filePaths.length > 0) + return result.filePaths ; + else + return undefined ; + }); +} + + +// -------------------------------------------------------------------------- +// --- saveFile dialog +// -------------------------------------------------------------------------- + +/** + @summary Show a dialog for saving file. + @parameter {object} options - configuration (see above) + @return {Promise} the selected path (see above) + @description +The available fields and options for configuring the dialog are: + +| Options | Type | Description | +|:--------|:----:|:------------| +| `message` | `string` (_opt._) | Prompt message | +| `label` | `string` (_opt._) | Save button label | +| `path` | `filepath` (_opt._) | Initially selected path | +| `filters` | `filter[]` (_opt._) | Cf. `openFileDialog` | + +The returned promise object will be asynchronously: +- either _resolved_ with `undefined` if no file has been selected, +- or _resolved_ with the selected (single) path. + +The promise is never rejected. + +*/ +export function showSaveFile( options ) +{ + const { message, label, path, filters } = options ; + + return remote.dialog.showSaveDialog( + remote.getCurrentWindow(), + { + message, buttonLabel: label, + defaultPath: path, + filters + } + ); +} + +// -------------------------------------------------------------------------- +// --- openDir dialog +// -------------------------------------------------------------------------- + +/** + @summary Show a dialog for selecting directories. + @parameter {object} options - configuration (see above) + @return {Promise} the selected directories (see above) + @description +The available fields and options for configuring the dialog are: + +| Options | Type | Description | +|:--------|:----:|:------------| +| `message` | `string` (_opt._) | Prompt message | +| `label` | `string` (_opt._) | Open button label | +| `path` | `filepath` (_opt._) | Initially selected path | +| `hidden` | `boolean` (_opt._) | Show hidden files (not by default) | + +The returned promise object will be asynchronously: +- either _resolved_ with `undefined` if no file has been selected, +- or _resolved_ with the selected path + +*/ +export function showOpenDir( options ) +{ + const { message, label, path, hidden } = options ; + const properties = [ 'openDirectory' ]; + if (hidden) properties.push('showHiddenFiles'); + + switch(System.platform) { + case 'macos': properties.push( 'createDirectory' ); break; + case 'windows': properties.push( 'promptToCreate' ); break; + } + + return remote.dialog.showOpenDialog( + remote.getCurrentWindow(), + { + message, + buttonLabel: label, + defaultPath: path, + properties + } + ).then(result => { + if (!result.canceled && result.filePaths && result.filePaths.length > 0) + return result.filePaths[0] ; + else + return undefined ; + }); +} + +// -------------------------------------------------------------------------- +// --- Export +// -------------------------------------------------------------------------- + +export default { + showMessageBox, + showOpenFile, + showOpenFiles, + showSaveFile, + showOpenDir +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/dnd.js b/Ivette/src/dome/src/renderer/dnd.js new file mode 100644 index 00000000000..89829fbb5a3 --- /dev/null +++ b/Ivette/src/dome/src/renderer/dnd.js @@ -0,0 +1,860 @@ +/** + @module dome/dnd + @summary Drag & Drop Features. + @description + +## D&D Sequences + +A Drag & Drop sequence is monitored by a D&D controller. +Drag Sources initiates the a D&D sequence, and the D&D controller will then +notify the Drop Target when they are dragged over. + +More precisely, the D&D controller is notified with all events of any D&D sequence. +Drag sources are notified will all events of the D&D sequences they have initiated. +Drop targets are only notified when they are actually participating into some D&D sequence. +For instance, when the dragged item directly moves from one target into another one, both +targets will be notified, but not the others. + + +## Dragging Events + +Many dragging events are triggered during a D&D sequence. +All event listeners will be notified with a single argument, +which is a `Dragging` object with the following properties: + - `move`: the kind of move (see below); + - `meta`: a boolean indicating whether Ctrl, Alt or Meta key is pressed during the move; + - `held`: a boolean indicating whether the mouse is holding over position; + - `sourceClientRect`: the position of the drag source element; + - `targetClientRect`: the position of the drop target element; + - `deltaX`, `deltaY`: the current offset position of the dragged element, +relative to its _initial_ position; + - `clientX`, `clientY`: the current client position of the _cursor_, as obtained from the dragging event; + - `position`: the current position from React-Draggable API (see DragSource documentation). + +All coordinates are provided in the window coordinate system, +as returned by the `getBoundingClientRect` DOM method. + + +## Dragging State + +During the entire sequence, the D&D controller is responsible for managing a shared +state among source and targets. +The drag source and each drop targets may update the shared state when receiving +events, and will be re-rendered in turn when necessary. + +This design eases the separation of concern: each participant in the D&D +sequence is only responsible with its own rendering, while synchronizing between the +participants is ensured through the global state. + + +## Kind of Moves + +During a D&D sequence, different kind of events can be triggered. +They can be distinguished with the `move` property of the dragging events, +as follows: + - `'START'`: D&D sequence initiated; + - `'STOP'`: D&D sequence finished without drop target; + - `'DROP'`: D&D sequence finished over some drop target; + - `'DRAG'`: the source is dragged over some drop target; + - `'HOLD'`: the source is holding the position for a while; + - `'MOVE'`: the source is moving again after holding for a while ; + - `'ENTER'`: the source is entering a target from _no_ other target; + - `'LEAVE'`: the source is leaving a target into _no_ other target; + - `'SWITCH'`: the source is leaving a target into another target. + +Notice that in kind of a `'SWITCH'` event, the leaved target will receive a `'LEAVE'` event +and the entered target will receive an `'ENTER'` event. + + +## Event Callbacks + +D&D controllers, drag sources and drop targets can listen to +dragging events _via_ various callbacks. + +Each callback has signature `(Dragging) => void` and is sensible to +specific kinds of events, as described below: + - `onDnd()`: all kind of events; + - `onStart()`: `START` events; + - `onEnter()`: `ENTER` and `SWITCH` events; + - `onLeave()`: `LEAVE` and `SWITCH` events; + - `onDrag()`: `DRAG` and `MOVE` events; + - `onHold()`: `HOLD` events; + - `onMove()`: `MOVE` events; + - `onDrop()`: `DROP` events; + - `onStop()`: `STOP` events; + - `onUpdate()`: only for D&D controllers, see below. + +In case of a `SWITCH` event, the `onLeave` listener is called first, +then the `onEnter` listener. This is only relevant for the D&D controller +and the drag source, since drop targets will receive either `ENTER` or `LEAVE` events. + +The same `Dragging` object is shared across all the event listeners, but +not among different drag source and drop targets. For each source or target +participating into the event, the `onDnd` listener is called first, +then the more specific ones, when defined. Hence, you can modify the `Dragging` +object during the process of `onDnd` and safely propagate those modifications accross +all listeners. + +Inside a D&D sequence, the leaved targets are notified first, +then the source and the target, and finally the D&D controller. +This allow you to maintain the D&D state in sync with the different participants. + +Additionally, the D&D controller might be equiped with +an `onUpdate()` handler, which is responsible for listening only to state update events. +This event handler will receive the current D&D state in argument, with the cumulated +updates from all participants merged in. + +*/ + +import React from 'react' ; +import Draggable, { DraggableCore } from 'react-draggable'; +import _ from 'lodash' ; + +const HOLD_TIME = 100 ; /* time in ms */ +const HOLD_FIRE = 6 ; /* number of HOLD_TIME before « hold » */ +const HOLD_MOVE = 3 ; /* maximum moved pixels for « holding » */ + +// -------------------------------------------------------------------------- +// --- Events Dispatcher +// -------------------------------------------------------------------------- + +const notify = ( cb, evt ) => cb && cb(evt); + +/** + @method + @summary Dispatch a dragging event over listeners. + @param {Dragging} dragging - the Dragging event to dispatch over + @param {object} [handlers] - an object with (optional) listeners + @description + +Dispatch a `Dragging` event among listeners defined in the `handlers` object, +when defined. For instance, `disptachEvents( evt , { onStop: myCallback } )` +will trigger `myCallback(evt)` if and only if `evt` is a `STOP` event. + +See event listeners documentation above for more details on listeners. + +You normally don't have to call this function, unless when you need to add +D&D features into your own component. Here is a typical pattern: + + const MyComponent = (props) => ( + <DragSource + dnd={props.dnd} + onDnd={(evt) => DnD.dispatchEvent(Object.assign(evt,…),props)} > + … + </DragSource> + ); + + */ +export const dispatchEvent = ( dragging , handlers ) => { + if (!handlers) return; + const dragged = Object.assign( {} , dragging ); + notify( handlers.onDnd , dragged ); + switch( dragged.move ) { + case 'START': + notify( handlers.onStart, dragged ); + return; + case 'STOP': + notify( handlers.onStop, dragged ); + return; + case 'ENTER': + notify( handlers.onEnter, dragged ); + return; + case 'SWITCH': + notify( handlers.onLeave, dragged ); + notify( handlers.onEnter, dragged ); + return; + case 'LEAVE': + notify( handlers.onLeave, dragged ); + return; + case 'DRAG': + notify( handlers.onDrag, dragged ); + return; + case 'MOVE': + notify( handlers.onMove, dragged ); + notify( handlers.onDrag, dragged ); + return; + case 'HOLD': + notify( handlers.onHold, dragged ); + return; + case 'DROP': + notify( handlers.onDrop, dragged ); + return; + default: + return; + } +}; + +// -------------------------------------------------------------------------- +// --- Dnd Controllers +// -------------------------------------------------------------------------- + +/** + @class + @summary D&D Controller. + @param {object} [handlers] - D&D events callbacks + @property {object} state - Current D&D state + @property {Dragging} dragging - Last D&D event + @description + D&D controlers are responsible for managing various drop targets + and dispatching the drag source events among them. + + The handler object shall define listeners to the D&D dragging events. + Each callback is sensible to specific kind of events, as specified + in the [event listeners](module-dome_dnd.html) + documentation. + + You need a D&D controller whenever an element can be dragged + between different containers. D&D controllers also offers an + abstraction over dragging events, dispatching among several + drop targets and the management of « holding » the mouse over + one drop target. + + Normally, you simply have to create D&D controllers in your global + (or local) state and pass them around into the hierarchy of your + components. For lower-level control, see the documentation of + the exposed methods. + + Having several D&D controllers allows you to assign specific + sources to specific targets. You shall have one D&D controller + for each « kind » of data that you can drag over. + + The `state` and `dragging` properties are shared across all partipants + of a D&D sequence, which are also re-rendered when the state is updated. + Outside of a D&D sequence, the `state` and `dragging` properties are undefined. + +*/ + +export class DnD { + + constructor(handlers) { + this.kid = 0 ; + this.targets = {} ; + this.tickHold = this.tickHold.bind(this); + this.triggerUpdate = this.triggerUpdate.bind(this); + this.triggerDnd = this.triggerDnd.bind(this); + this.handlers = handlers || {} ; + } + + /** @summary Update the D&D event handlers. + @param {object} [handlers] - D&D events callbacks + @description + Replace the event handlers by those specified in the `handlers` object. + Not mentionned callbacks are left unchanged. + If the `null` object is given, all current handlers are removed. + */ + setHandlers( handlers ) { + this.handlers = + handlers === null ? {} : Object.assign( this.handlers, handlers ); + } + + //--- Registering + + /** @summary Registers a target into the D&D controller. + @param {React.ref} ref - a referrence on the drop target DOM element + @param {function} callback - generic D&D events callback + @return {ident} the target identifier + @description + You normally don't call this method by yoursef, it is automatically + called when `<DropTarget/>` are mounted in the DOM. + */ + register( ref, callback ) + { + if (!ref) return undefined; + const id = 'DOME$' + (++this.kid) ; + this.targets[id] = { id, ref , callback } ; + return id; + } + + //--- Updating + + /** @summary Update the event handlers associated to a drop target. + @param {ident} id - the drop target identifier + @param {React.ref} ref - a referrence on the drop target DOM element + @param {function} callback - generic D&D events callback + @description + You normally don't call this method by yoursef, it is automatically + called when `<DropTarget/>` are updated. If the target data is falsy, the target identifier + is used instead. + */ + update( id, ref, callback ) { + if (this.targets[id]) { + this.targets[id] = { id, ref, callback }; + } + } + + //--- Un-Registering + + /** @summary Un-register a target from the D&D controller. + @param {ident} id - the drop target identifier to remove + @description + You normally don't call this method by yoursef, it is automatically + called when `<DropTarget/>` are unmounted from the DOM. + */ + remove( id ) { + delete this.targets[id] ; + } + + //--- Generic Mouse Event + + handleMouseEvent( evt, x, y ) { + const d = this.dragging ; + d.meta = evt.ctrKey || evt.altKey || evt.metaKey ; + d.deltaX = x - this.rootX ; + d.deltaY = y - this.rootY ; + d.position = {x,y} ; + const ex = d.clientX = evt.clientX ; + const ey = d.clientY = evt.clientY ; + d.targetClientRect = undefined ; + this.leaved = this.target ; + this.leavedHandler = this.targetHandler ; + this.target = undefined ; + this.targetHandler = undefined ; + const elts = document.elementsFromPoint(ex,ey); + elts.find((elt) => { + const target = _.find( this.targets, (tgt) => tgt.ref.current === elt ); + if (target) { + const { id, callback } = target ; + this.target = id ; + this.targetHandler = target.callback ; + if (id === this.leaved) this.leavedHandler = undefined ; + d.targetClientRect = elt.getBoundingClientRect(); + return true; + } + return false; + }); + } + + //--- Starting D&D sequence + + /** @summary Initiates a new drag. + @param {Event} evt - the mouse event originating the drag + @param {number} x - initial horizontal coordinate + @param {number} y - initial vertical coordinate + @param {Element} node - the source DOM element + @param {function} callback - generic D&D events callback + @description +You normally don't call this method by sourself, it is automatically +called by `DragSource` objects. + +Initial `(x,y)` coordinates can be in any coordinate system, they +are only used to compute relative offsets of further D&D events. +They can be typically taken from React-Draggable events data. + +The generic callback shall handle two kind of events: + - `callback()` when the global D&D state has been updated; + - `callback(Dragging)` when some D&D event is triggered. + +Generally, you shall `forceUpdate()` your component in the first case, +and `dispatchEvent()` the event to D&D listeners in the second case. + + */ + handleStart( evt, x, y, node, callback ) { + if (this.dragging) { + this.triggerDnd('STOP'); + if (this.timer) clearInterval(this.timer); + } + this.state = {}; + this.dragging = { + sourceClientRect: node.getBoundingClientRect() + }; + this.sourceHandler = callback ; + this.targetHandler = undefined ; + this.leavedHandler = undefined ; + this.rootX = x; + this.rootY = y; + this.lastX = x; + this.lastY = y; + this.ticks = 0; + this.handleMouseEvent( evt, x, y ); + this.triggerDnd( 'START' ); + this.timer = setInterval( this.tickHold , HOLD_TIME ); + } + + //--- Dragging D&D sequence + + /** @summary Dispatch a drag-event amoung registered drop targets. + @param {Event} evt - the dragging mouse event + @param {number} x - the horizontal coordinate + @param {number} y - the vertical coordinate + @description +You normally don't call this method by sourself, it is automatically +called by `DragSource` objects. + +The `(x,y)` coordinates shall be in the same coordinate system than +when starting the D&D sequence. It is only used to compute relative +the offsets of the associated D&D event. + */ + handleDrag( evt, x, y ) { + let kind = 'DRAG' ; + let delta = Math.abs( x - this.lastX ) + Math.abs( y - this.lastY ); + this.lastX = x ; + this.lastY = y ; + if (delta > HOLD_MOVE) { + this.ticks = 0 ; + const d = this.dragging ; + if (d.held) { + d.held = false ; + kind = 'MOVE' ; + } + } + this.handleMouseEvent( evt, x, y ); + const target = this.target ; + const leaved = this.leaved ; + if (target !== leaved) { + if (target && !leaved) kind = 'ENTER' ; else + if (!target && leaved) kind = 'LEAVE' ; else + if (target && leaved) kind = 'SWITCH' ; + } + this.triggerDnd(kind); + } + + //--- Stopping D&D sequence + + /** @summary Dispatch a drop-event over registered drop targets. + @param {Event} evt - the dropping mouse event + @param {number} x - the horizontal coordinate + @param {number} y - the vertical coordinate + @description +You normally don't call this method by sourself, it is automatically +called by `DragSource` objects. + +The `(x,y)` coordinates shall be in the same coordinate system than +when starting the D&D sequence. It is only used to compute relative +the offsets of the associated D&D event. + */ + handleStop( evt, x, y ) { + clearInterval( this.timer ); + this.handleMouseEvent( evt, x, y ); + this.triggerDnd(this.target ? 'DROP' : 'STOP'); + this.dragging = undefined ; + this.state = undefined ; + this.timer = undefined; + this.ticks = undefined; + this.triggerUpdate(); + } + + //--- Hold Detection + + tickHold() { + if (this.dragging && (this.ticks++) > HOLD_FIRE) + { + this.dragging.held = true ; + this.triggerDnd('HOLD'); + this.ticks = 0 ; + } + } + + //--- Update State + + /** + @summary Update the controller state. + @parameter {object} update - the data to update the state with + @description + Update the state with the given updates, like React component states. + This will force the drag source target and drop target components to re-render. + */ + setState(update) { + const state = this.state ; + if (state && update) { + this.state = Object.assign( state, update ); + if (!this.dirty) { + this.dirty = true ; + setImmediate( this.triggerUpdate ); + } + } + } + + triggerUpdate() { + this.dirty = false ; + notify( this.leavedHandler ); // always different from target + notify( this.sourceHandler ); + notify( this.targetHandler ); + notify( this.handlers.onUpdate , this.state ); + } + + //--- Trigger Dragging Events + + triggerDnd(move) { + const d = this.dragging ; + d.move = move ; + switch( move ) { + case 'ENTER': + notify( this.sourceHandler, d ); + notify( this.targetHandler, d ); + break; + case 'LEAVE': + notify( this.leavedHandler, d ); + notify( this.sourceHandler, d ); + break; + case 'SWITCH': + d.move = 'LEAVE' ; notify( this.leavedHandler, d ); + d.move = 'SWITCH' ; notify( this.sourceHandler, d ); + d.move = 'ENTER' ; notify( this.targetHandler, d ); + d.move = 'SWITCH' ; + break; + default: + notify( this.leavedHandler, d ); // allways different from target + notify( this.sourceHandler, d ); + notify( this.targetHandler, d ); + break; + } + dispatchEvent( d, this.handlers ); + } + +} + +// -------------------------------------------------------------------------- +// --- Drag Overlay +// -------------------------------------------------------------------------- + +/** + @class + @summary Display a Drag Source with an Overlay. + @property {Dragging} [dragging] - current dragging event + @property {string} [className] - source content class + @property {object} [style] - source content style + @property {object} [draggedStyle] - additional style for the source placeholder + @property {object} [draggingStyle] - additional style for the source being dragged + @property {number} [offsetX] - horizontal offset during drag (default 4) + @property {number} [offsetY] - vertical offset during drag (default 4) + @property {number} [zIndex] - fixed positioning during drag (default 1) + @property {any} [...divProps] - other properties to inject in the root element + @property {React.children|function} [children] - drag source content + @description + When dragged, a source drag is generally blit by its embedding container. + Using z-index CSS property might be a solution, but this is generally not + enough to escape from a positionned parent `<div>` element. + + The alternative is to separate the internal content of + a drag source from its outer `<div>`, and to use fixed positionning + during a D&D sequence. + + The `<Overlay>` component implements this behaviour. The root element is + normally laid out with the `className`, `style` and `divProps` properties and + its internal content is wrapped inside an internal `<div>` container. + + During dragging, this normal layout is slightly altered, without causing + extra React mounting or unmounting. The outer `<div>` is styled with its + original class plus the `'dome-dragged'` class which provides by default a + light-blue background and invisible border style. The inner class is styled + with its original class plus the `dome-dragging` class, canceled margins and + fixed positionning with respect to the dragging event. You may use those + additinal classes to add conditional styling when dragging. + + Additionnaly, when dragged around, the source content is offsets + with `offsetX` and `offsetY`, which defaults to 4 pixels each. + + Finally, you may supply a custom rendering function for rendering the drag + source content, which is fed with the current dragging event. + */ + +export const Overlay = ({ + dragging, className='', style, styleDragged, styleDragging, + offsetX=4, offsetY=4, insetX=0, insetY=0, + zIndex=1, + children, + ...divProps +}) => { + let outerClass,outerStyle,innerStyle,innerClass ; + if (dragging) { + const { left, top, width, height } = dragging.sourceClientRect ; + const position = { + position: 'fixed', + left: left + offsetX + dragging.deltaX, + top: top + offsetY + dragging.deltaY, + width, height, zIndex, margin: 0 + }; + const holder = { + width, height + }; + outerClass = 'dome-dragged ' + className ; + innerClass = 'dome-dragging ' + className ; + outerStyle = Object.assign( {}, style, styleDragged, holder ); + innerStyle = Object.assign( {}, style, styleDragging, position ); + } else { + outerClass = className ; + outerStyle = style ; + innerClass = undefined ; + innerStyle = undefined ; + } + return ( + <div className={outerClass} style={outerStyle} {...divProps}> + <div className={innerClass} style={innerStyle}> + {typeof(children)==='function' ? children(dragging) : children} + </div> + </div> + ); +}; + +// -------------------------------------------------------------------------- +// --- Drag Sources +// -------------------------------------------------------------------------- + +/** + @class + @summary Drag Source Component. + @property {DnD} [dnd] - the associated D&D controller + @property {string} [handle] - DOM selector initiating the drag (eg. `'.handle'`) + @property {boolean} [disabled] - cancel D&D events if non falsy value + @property {object} [draggable] - additional properties for the internal react-draggable wrapper + @property {function} [onDnd] - callback to D&D generic events + @property {function} [onXxx] - callback to other D&D specific events + @property {string} [className] - the class of the internal 'div' component (unless custom rendering) + @property {object} [style] - the style of the internal 'div' component (unless custom rendering) + @property {object} [position] - relative position of the internal 'div' component (unless custom rendering) + @property {boolean|object} [overlay] - use an `Overlay` to display the content + @property {React.children|function} children - element content or custom rendering function + @description + +Creates a drag source element and manage its dragging state. The component +is rendered by an internal `<div>` element with the given class and style with specific +handlers attached in. You can use the `'position'` property to modify its relative position +_after_ a D&D sequence, the position being `{x:0,y:0}`. This position is set relative to the normal +positioning of the internal `<div>` element, as specified by the provided class and style properties. +Notice that during dragging, your component is attached an additional `'dome-dragging'` class name that +you can use to alter its rendering. + +Alternatively, you may provide a custom rendering function as the unique children of the Drag Source element. +The function will be given the current D&D dragging events, or `undefined` when outside a D&D sequence. +The custom rendering _shall_ return a single root element supporting property injection in order for the Drag +Source element to attach its event handlers into it. You are then fully responsible for rendering and positioning +the element both _during_ and _outside_ of a D&D sequence. No internal `<div>` element is inserted for you, +and the `className`, `style` and `position` properties are ignored. + +Finally, you may also use an [Overlay](module-dome_dnd.Overlay.html) component to render +your content, by setting `overlay=true` or passing `overlay` the desired properties. + +When dragged, the [DnD](module-dome_dnd.DnD.html) controller is informed and dispatches +the dragging events to the registered drop targets. The `handle` selector can be used +to identify which parts of the content may initiate the drag. By default, any drag event +may initiate the drag. + +The `onDnd` event listener receives all D&D events associated to this drop target. +See [event callbacks](module-dome_dnd.html) +documentation for more details on other specific event listeners. + +The `draggable` object, when provided, is used to inject additional properties +into the internal `Draggable` or `DraggableCore` wrapper used to manage D&D events. +By default, a full featured `Draggable` component is used. +When a custom rendering function is specified, a `DraggableCore` is used instead. +See [react-draggable](https://github.com/mzabriskie/react-draggable) +documentation for more details. + +*/ + +export class DragSource extends React.Component +{ + constructor(props) + { + super(props); + this.onStart = this.onStart.bind(this); + this.onDrag = this.onDrag.bind(this); + this.onStop = this.onStop.bind(this); + this.handleDnd = this.handleDnd.bind(this); + this.state = { }; + } + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + onStart(evt,drag) { + const { dnd, disabled } = this.props; + if (dnd) dnd.handleStart(evt,drag.x,drag.y,drag.node,this.handleDnd); + } + + onDrag(evt,drag) { + const { dnd, disabled } = this.props ; + if (dnd) dnd.handleDrag(evt,drag.x,drag.y); + } + + onStop(evt,drag) { + const { dnd, disabled } = this.props ; + if (dnd) dnd.handleStop(evt,drag.x,drag.y); + } + + handleDnd(dragging) { + if (!this.mounted) return; + if (!dragging) + this.forceUpdate(); + else { + dispatchEvent( dragging, this.props ); + switch(dragging.move) { + case 'STOP': + case 'DROP': + this.setState({dragging:undefined}); + break; + default: + this.setState({dragging}); + break; + } + } + } + + render() { + const { dnd, disabled, className, style, + handle, draggable, overlay, + children } = this.props ; + if (overlay || typeof(children)==='function') { + const dragging = this.state.dragging ; + return ( + <DraggableCore + handle={handle} + disabled={!dnd || disabled} + onStart={this.onStart} + onDrag={this.onDrag} + onStop={this.onStop} + {...draggable} + > + { overlay ? + ( + <Overlay + dragging={dragging} + className={className} style={style} + {...overlay} > + {children} + </Overlay> + ) + : children(dragging) + } + </DraggableCore> + ); + } else { + const { className, style, position={x:0,y:0} } = this.props ; + return ( + <Draggable + handle={handle} + disabled={!dnd || disabled} + position={position} + defaultClassName='' + defaultClassNameDragged='' + defaultClassNameDragging='dome-dragging' + onStart={this.onStart} + onDrag={this.onDrag} + onStop={this.onStop} + {...draggable} + > + <div className={className} style={style}>{children}</div> + </Draggable> + ); + } + } + +} + +// -------------------------------------------------------------------------- +// --- Drop Target +// -------------------------------------------------------------------------- + +/** + @class + @summary Drop Target Container. + @property {DnD} [dnd] - the associated D&D Controller + @property {function} [onDnd] - callback to D&D generic events + @property {function} [onXxx] - callback to other D&D specific events + @property {string} [className] - class name(s) of the internal `<div>` element (unless custom rendering) + @property {object} [style] - style property for the internal `<div>` element (unless custom rendering) + @property {React.ref} [targetRef] - the React ref to use for identifying the target DOM element + @property {React.children|function} children - element content or custom rendering function + @description + +Crates a drop target container and register its callbacks into the specified +[DnD](module-dome_dnd.DnD.html) controller. In case the DnD controller is undefined, +the drag events are just disabled. + +The drop target container must inform the D&D controller of its DOM element that is responsible +for reacting to dragging events. By default, the drop target element renders its children elements +inside an internal `<div>` element with the specified class ans style properties. Notice that, during +a D&D sequence, the `dome-dragging` class name is added to this `<div>` element and you can use this selector +for your styling. + +Alternatively, you may provide a custom rendering function as the unique children of the Drag Source element. +Your rendering function will receive the current D&D dragging of the D&D sequence, if any. +The [targetRef] property shall be used to identify the target DOM element, otherwize, the drop target +will not respond to dragging events. +In case of custom rendering, the `className` and `style` properties are ignored. + +During a D&D sequence, the `onDnd` event listener receives all D&D events associated +to this drop target. See [event callbacks](module-dome_dnd.html) +documentation for more details on other specific event listeners. + +*/ +export class DropTarget extends React.Component +{ + + constructor(props) { + super(props); + this.targetRef = this.props.targetRef || React.createRef() ; + this.handleDnd = this.handleDnd.bind(this); + this.state = {}; + } + + componentDidMount() { + const { dnd } = this.props ; + this.id = dnd && dnd.register( this.targetRef, this.handleDnd ); + this.mounted = true ; + } + + componentDidUpdate() { + const { dnd } = this.props ; + dnd && dnd.update(this.id, this.targetRef, this.handleDnd ); + } + + componentWillUnmount() { + const { dnd } = this.props ; + dnd && dnd.remove( this.id ); + this.mounted = false ; + } + + handleDnd(dragging) { + if (!this.mounted) return; + if (!dragging) + this.forceUpdate(); + else { + dispatchEvent( dragging, this.props ); + switch(dragging.move) { + case 'STOP': + case 'DROP': + case 'LEAVE': + this.setState({dragging:undefined}); + break; + default: + this.setState({dragging}); + break; + } + } + } + + render() { + const targetRef = this.targetRef ; + const { children } = this.props ; + const { dragging } = this.state ; + if (typeof(children)==='function') + return children(dragging); + else { + let { className='', style } = this.props ; + return ( + <div ref={targetRef} + className={ dragging ? className + ' dome-dragging' : className } + style={style} > + {children} + </div> + ); + } + } + +} + +// -------------------------------------------------------------------------- +// --- Export +// -------------------------------------------------------------------------- + +export default { + DnD, DragSource, DropTarget, dispatchEvent +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/dome.css b/Ivette/src/dome/src/renderer/dome.css new file mode 100644 index 00000000000..3320c9f5100 --- /dev/null +++ b/Ivette/src/dome/src/renderer/dome.css @@ -0,0 +1,131 @@ +/* -------------------------------------------------------------------------- */ +/* --- Main Dome Styles --- */ +/* -------------------------------------------------------------------------- */ + +* { + user-select: none; + box-sizing: border-box; + margin: 0 ; + padding: 0 ; + } + +body { + overflow: hidden ; + position: fixed ; + font-family: sans-serif ; + font-size: 13px ; + color: #333333 ; + background: #f0f0f0 ; + top: 0 ; + bottom: 0 ; + left: 0 ; + right: 0 ; +} + +#app { + width: 100% ; + height: 100% ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Frame Colors --- */ +/* -------------------------------------------------------------------------- */ + +.dome-window-active .dome-color-frame { + fill: #606060 ; + color: #606060 ; + border-color: #afafaf ; + background: #d8d8d8 ; +} + +.dome-window-inactive .dome-color-frame { + fill: #b0b0b0 ; + color: #b0b0b0 ; + border-color: #d6d6d6 ; + background: #f6f6f6 ; +} + +.dome-window-active .dome-color-selected { + border-color: #e8e8e8 ; + background: #ff9504 ; + color: #ffffff ; +} + +.dome-window-inactive .dome-color-selected { + border-color: #e8e8e8 ; + background: #d8d8d8 ; +} + +.dome-color-dragzone { + opacity: 0.0 ; + background: transparent ; + transition: opacity .1s linear 0.1s , background .1s linear 0.1s ; +} + +.dome-color-dragzone:hover { + background: #808080 ; + opacity: 0.2 ; + transition: opacity .1s linear 0.1s , background .1s linear 0.1s ; +} + +.dome-color-dragging { + background: #64b4f0 ; + opacity: 0.5 ; + transition: opacity .1s linear 0.1s , background .1s linear 0.1s ; +} + +div.dome-dragged { + background: lightblue ; + border: none ; +} + +.dome-dragging * { + cursor: move ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Text Properties --- */ +/* -------------------------------------------------------------------------- */ + +.dome-text-label { + font-family: sans-serif ; + user-select: none ; + white-space: nowrap ; + text-overflow: ellipsis ; +} + +.dome-text-title { + font-family: sans-serif ; + font-size: larger ; + font-weight: bolder ; + user-select: none ; + white-space: nowrap ; + text-overflow: ellipsis ; +} + +.dome-text-descr { + font-family: sans-serif ; + font-size: smaller ; + user-select: none ; + white-space: wrap ; + text-overflow: ellipsis ; +} + +.dome-text-data { + cursor: text ; + user-select: text ; + font-family: sans-serif ; + white-space: nowrap ; + text-overflow: clip ; +} + +.dome-text-code { + cursor: text ; + user-select: text ; + font-family: 'Andale mono', monospace ; + font-size: 9pt ; + white-space: pre ; + text-overflow: clip ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/dome.js b/Ivette/src/dome/src/renderer/dome.js new file mode 100644 index 00000000000..8a4b389dc5d --- /dev/null +++ b/Ivette/src/dome/src/renderer/dome.js @@ -0,0 +1,987 @@ +/** + @module dome(renderer) + @description + + ## Dome Application (Renderer Process) + + This modules manages your main application window + and its interaction with the main process. + + @example // File 'src/renderer/index.js': + import Dome from 'dome'; + import Application from './Application.js' ; + Dome.setContent( Application ); + */ + +import _ from 'lodash' ; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { AppContainer } from 'react-hot-loader' ; +import { remote , ipcRenderer } from 'electron'; +import System from 'dome/system' ; +import './dome.css' ; + +// -------------------------------------------------------------------------- +// --- Context +// -------------------------------------------------------------------------- + +// main window focus +var focus = true ; + +function setContextAppNode() +{ + const node = document.getElementById('app'); + if (node) { + node.className = + 'dome-container dome-platform-' + System.platform + + ( focus ? ' dome-window-active' : ' dome-window-inactive' ) ; + } + return node; +} + +// -------------------------------------------------------------------------- +// --- Helpers +// -------------------------------------------------------------------------- + +/** @summary Development mode flag. + @description + Configured to be `'true'` when in development mode +*/ +export const DEVEL = System.DEVEL ; + +/** @summary System platform. + @description + Same as [`platform`](module-dome_system.html#.platform) from `dome/system` */ +export const platform = System.platform ; + +// -------------------------------------------------------------------------- +// --- Application Emitter +// -------------------------------------------------------------------------- + +import { EventEmitter } from 'events' ; + +/** @summary Application Emitter. + @description + Can be used as a basic _Flux_ dispatcher. */ +export const emitter = new EventEmitter(); + +/** Same as `emitter.on` */ +export function on(evt,job) { emitter.on(evt,job); } + +/** Same as `emitter.off` */ +export function off(evt,job) { emitter.off(evt,job); } + +/** Same as `emitter.emit` */ +export function emit(evt,...args) { emitter.emit(evt,...args); } + +// -------------------------------------------------------------------------- +// --- Application Events +// -------------------------------------------------------------------------- + +/** @event 'dome.update' + @description + Convenient pre-defined events for triggering a global re-render. + See also [Dome.onUpdate](#.onUpdate), [Dome.update](#.update) methods and + the [Dome.useUpdate](#.useUpdate) hook. +*/ + +/** @event 'dome.reload' + @description + Triggered when the application has been loaded or re-loaded + See also [Dome.onReload](#.onReload). +*/ + +/** @event 'dome.command' + @param {Array.<string>} argv - command line arguments + @param {string} wdir - working directory + @description + Triggered when the command line argument has been received, and when + the application is re-loaded (in development mode). + + See also [Dome.onCommand](#.onCommand). +*/ + +/** + @summary Emits the `dome.update` event. +*/ +export function update() { emitter.emit('dome.update'); } + +/** + @summary Update event handler. + @param {function} cb - invoked on update events. + @description + Register a callback on [dome.update](#~event:'dome.update') event. +*/ +export function onUpdate(job) { emitter.on('dome.update',job); } + +/** + @summary Update event handler. + @param {function} cb - invoked on reload events. + @description + Register a callback on [dome.reload](#~event:'dome.reload') event. +*/ +export function onReload(job) { emitter.on('dome.reload',job); } + +/** @summary Command-line event handler. + @param {function} cb - invoked with `cb(argv,wdir)` + @description +Register a callback on [dome.command](#~event:'dome.reload') event, +emitted by the `Main` process when the application instance is launched. + +See also: + - [Dome.useCommand](#.useCommand) + - [System.getArguments](module-dome_system.html#.getArguments) + - [System.getWorkingDir](module-dome_system.html#.getWorkingDir) +*/ +export function onCommand(job) { emitter.on('dome.command',job); } + +ipcRenderer.on('dome.ipc.reload',() => emitter.emit('dome.reload')); +ipcRenderer.on('dome.ipc.command', (_event,argv,wdir) => { + System.setCommand(argv,wdir); + emitter.emit('dome.command',argv,wdir); +}); + +// -------------------------------------------------------------------------- +// --- Main-Process Communication +// -------------------------------------------------------------------------- + +// -------------------------------------------------------------------------- +// --- Window Management +// -------------------------------------------------------------------------- + +export function isApplicationWindow() +{ + return process.argv.includes( System.WINDOW_APPLICATION_ARGV ); +} + +export function isPreferencesWindow() +{ + return process.argv.includes( System.WINDOW_PREFERENCES_ARGV ); +} + +// -------------------------------------------------------------------------- +// --- Window Title +// -------------------------------------------------------------------------- + +export function setModified( modified ) +{ + ipcRenderer.send('dome.ipc.window.modified',modified); +} + +export function setTitle( title ) +{ + ipcRenderer.send('dome.ipc.window.title',title); +} + +// -------------------------------------------------------------------------- +// --- Main Content +// -------------------------------------------------------------------------- + +/** + @summary Defines the user's main window content. + @param {React.Component} Component - to be rendered in the main window + @description + Binds the component to the main window. + + <strong>Notes:</strong> a `<Component/>` instance is generated and rendered in the `#app` + window element. Its class name is set to `dome-platform-<platform>` with + the `<platform>` set to the `Dome.platform` value. This class name can be used + as a CSS selector for platform-dependent styling. +*/ +export function setApplicationWindow( Component ) +{ + if (isApplicationWindow()) { + syncSettings(); + const appNode = setContextAppNode(); + ReactDOM.render( <AppContainer><Component/></AppContainer> , appNode ); + } +} + +// -------------------------------------------------------------------------- +// --- Settings Window +// -------------------------------------------------------------------------- + +/** + @summary Defines the user's preferences window content. + @param {React.Component} Component - to be rendered in the settings window + @description + Binds the component to the settings window. + + <strong>Notes:</strong> a `<Component/>` instance is generated and rendered in the `#app` + window element. Its class name is set to `dome-platform-<platform>` with + the `<platform>` set to the `Dome.platform` value. This class name can be used + as a CSS selector for platform-dependent styling. +*/ +export function setPreferencesWindow( Component ) +{ + if (isPreferencesWindow()) { + syncSettings(); + const appNode = setContextAppNode(); + ReactDOM.render( <AppContainer><Component/></AppContainer> , appNode ); + } +} + +// -------------------------------------------------------------------------- +// --- MenuBar Management +// -------------------------------------------------------------------------- + +const customItemCallbacks = {} ; + +/** + @summary Create a new custom menu in the menu bar. + @param {string} label - the menu title (shall be unique) + @description + This function can be triggered at any time, and will eventually trigger + an update of the whole application menubar. + + It is also possible to call this function from the main process. +*/ +export function addMenu( label ) { ipcRenderer.send( 'dome.ipc.menu.addmenu' , label ); } + +/** + @summary Insert a new custom item in a menu. + @param {object} spec - the menu-item specification + @description +The menu-item shall be specified by using the following fields: + - `menu` (`string`, _required_) : the label of the menu to insert the item in; + can be a custom menu, or one of the predefined `'File'`, `'Edit'` or `'View'` menus. + - `id` (`string|number`, _required_) : the item identifier; + shall be unique among the entire menu-bar. + - `type` (`string`, _optional_) : one of `'normal'`, `'separator'`, `'checkbox'` or `'radio'`. + - `label` (`string`, _optional_) : the item label. + - `visible` (`boolean`, _optional_, default is `true`). + - `enabled` (`boolean`, _optional_, default is `true`). + - `checked` (`boolean`, _optional_, for `type:'checkbox'` and `type:'radio'` only, default is `false`). + - `key` (`string`, _optional_) : a keyboard shortcut for menu-item. + - `onClick` (`function`, _optional_) : an optional callback. + +These options (except `menu` and `id`) can be modified later on by using the [setMenuItem](#.setMenuItem) function. + +When clicked, the menu-item will also trigger a `'dome.menu.clicked'` event on the entire application (both process) +with the corresponding `id`. + +Key short cuts shall be specified with the following codes: + - `"Cmd+<Key>"` for command (MacOS) or control (Linux) key + - `"Alt+<Key>"` for command+option (MacOS) or alt (Linux) key + - `"Meta+<Key>"` for command+shift (MacOS) or control+alt (Linux) key + +Alternatively, more precise keybord shortcuts can be specified with the `'accelerator'` option, +which follows the same encoding that menu-item specifications from Electron. + +The `addMenu` function can be triggered at any time, and will eventually trigger +an update of the whole application menubar. +It is also possible to call this function from the main process. + +*/ +export function addMenuItem( spec ) +{ + if (!spec.id && spec.type !== 'separator') { + console.error('[Dome] Missing menu-item identifier',spec); + return; + } + const { onClick , ...options } = spec ; + if ( onClick ) customItemCallbacks[ spec.id ] = onClick ; + ipcRenderer.send( 'dome.ipc.menu.addmenuitem' , options ); +} + +/** + @summary Update properties of an existing menu-item. + @param {object} options - the menu-item specification to update + @description + Options must follow the specification of the [addMenuItem](#.addMenuItem) function. + Option `id` must specify the identifier of the menu item to update. + The menu and item positions can _not_ be modified. + If an `onClick` callback is specified, it will _replace_ the previous one. + You shall specify `null` to remove the previously registered callback + (`undefined` callback is ignored). + + This function can be triggered at any time, and will possibly trigger + an update of the whole application menubar if the properties + can not be changed dynamically in Electron. + + It is also possible to call this function from the main process. + When specified, the item callback is only invoked in the process which + specify it. To register callbacks in other process, + you shall listen to the `'dome.menu.clicked'` event. + */ +export function setMenuItem( options ) { + if (!options.id) { + console.error('[Dome] Missing menu-item identifier',options); + return; + } + const { onClick , ...updates } = options ; + if (onClick !== undefined) { + if (onClick) customItemCallbacks[options.id] = onClick ; + else delete customItemCallbacks[options.id] ; + } + ipcRenderer.send( 'dome.ipc.menu.setmenuitem', updates ); +} + +/** @event 'dome.menu.clicked' + @description Emitted with the clicked menu-item identifier */ + +ipcRenderer.on('dome.ipc.menu.clicked',(id) => { + const callback = customItemCallbacks[id] ; + callback && callback(); +}); + +// -------------------------------------------------------------------------- +// --- Context Menus +// -------------------------------------------------------------------------- + +/** + @summary Popup a contextual menu. + @param {item[]} items - the array of menu items + @param {function} [callback] - an optional callback + @description +Each menu item is specified by an object with the following fields: + - `id` (`string|number`, _optional_) : the item identifier. + - `label` (`string`, _optional_) : the item label. + - `enabled` (`boolean`, _optional_, default is `true`). + - `display` (`boolean`, _optional_, default is `true`). + - `onClick` (`function`, _optional_) : callback on item selection. + +Items can be separated by inserting a `'separator'` constant string +in the array. Item identifier and label default to each others. Alternatively, +an item can be specified by a single string that will be used for both +its label and identifier. + +The menu is displayed at the current mouse location. +The callback is called with the selected item identifier or label. +If the menu popup is canceled by the user, the callback is called with `undefined`. + +@example +let myPopup = (_evt) => Dome.popupMenu([ …items… ],(id) => … ); +<div onRightClick={myPopup}>...</div> + +*/ +export function popupMenu( items, callback ) +{ + const { Menu , MenuItem } = remote ; + const menu = new Menu(); + var selected = undefined ; + items.forEach((item,kid) => { + if (item === 'separator') + menu.append(new MenuItem({ type:'separator' })); + else + { + const { display=true } = item ; + if (display) { + const label = item.label || '#'+(kid+1) ; + const id = item.id || label ; + const enabled = item.enabled ; + const click = () => { + selected = id ; + item.onClick && item.onClick(); + }; + menu.append(new MenuItem({ label, enabled, click })); + } + } + }); + const job = callback ? () => callback( selected ) : undefined ; + menu.popup({window: remote.getCurrentWindow(), callback:job }); +} + +// -------------------------------------------------------------------------- +// --- Settings +// -------------------------------------------------------------------------- + +var globals = {} ; +var globalPatches = {} ; + +var settings = {} ; +var settingsPatches = {} ; + +// initial values => synchronized event +function syncSettings() { + const fullSettings = ipcRenderer.sendSync('dome.ipc.settings.sync'); + globals = fullSettings.globals ; + settings = fullSettings.settings ; +} + +const readSetting = ( local, key, defaultValue ) => { + const value = _.get( local ? settings : globals , key ); + return value === undefined ? defaultValue : value ; +}; + +const writeSetting = ( local, key, value ) => { + if (key) { + const theValue = value===undefined ? null : value ; + const store = local ? settings : globals ; + const patches = local ? settingsPatches : globalPatches ; + _.set( store, key, theValue ); + _.set( patches, key, theValue ); + emitter.emit('dome.settings'); + if (local) { + if (DEVEL) fireSaveSettings(); + } else { + fireSaveGlobals(); + } + } +}; + +const fireSaveSettings = _.debounce( + () => { + if (!_.isEmpty(settingsPatches)) { + ipcRenderer.send( 'dome.ipc.settings.window', settingsPatches ) ; + settingsPatches = {} ; + } + }, 200 +); + +const fireSaveGlobals = _.debounce( + () => { + if (!_.isEmpty(globalPatches)) { + ipcRenderer.send( 'dome.ipc.settings.global', globalPatches ) ; + globalPatches = {} ; + } + }, 200 +); + +ipcRenderer.on('dome.ipc.closing', (_evt) => { + fireSaveSettings(); + fireSaveSettings.flush(); + fireSaveGlobals(); + fireSaveGlobals.flush(); + System.doExit(); +}); + +/** @event 'dome.settings' + @description Emitted when the settings have been updated. */ + +/** @event 'dome.defaults' + @description Emitted when the settings have been reset to default. */ + +ipcRenderer.on('dome.ipc.settings.defaults',(sender) => { + fireSaveSettings.cancel(); + fireSaveGlobals.cancel(); + settingsPatches = {}; + globalPatches = {}; + settings = {}; + globals = {}; + emitter.emit('dome.defaults'); + emitter.emit('dome.settings'); +}); + +ipcRenderer.on('dome.ipc.settings.update',(sender,patches) => { + // Don't cancel local updates + _.merge( globals , patches , globalPatches ); + emitter.emit('dome.settings'); +}); + +/** + @summary Get value from local window (persistent) settings. + @param {string} key User's Setting Key (`'dome.*'` are reserved keys) + @param {any} [defaultValue] - default value if the key is not present + @return {any} associated value of object or `undefined`. + @tutorial application + @description + This settings are local to the current window, but persistently + saved in the user's home directory.<br/> + For global application settings, use `getGlobal()` instead. +*/ +export function getWindowSetting( key, defaultValue ) { + return key ? readSetting( true, key , defaultValue ) : defaultValue ; +} + +/** @summary Set value into local window (persistent) settings. + @param {string} key to store the data + @param {any} value associated value or object + @tutorial application + @description + This settings are local to the current window, but persistently + saved in the user's home directory.<br/> + For global application settings, use `setGlobal()` instead. +*/ +export function setWindowSetting( key , value ) { + writeSetting( true, key, value ); +} + +/** + @summary Get value from application (persistent) settings. + @param {string} key User's Setting Key (`'dome.*'` are reserved keys) + @param {any} [defaultValue] - default value if the key is not present + @return {any} associated value of object or `undefined`. + @tutorial application + @description + These settings are global to the application and persistently + saved in the user's home directory.<br/> + For local window settings, use `get()` instead. +*/ +export function getGlobalSetting( key, defaultValue ) { + return key ? readSetting( false, key , defaultValue ) : defaultValue ; +} + +/** @summary Set value into application (persistent) settings. + @param {string} key to store the data + @param {any} value associated value or object + @tutorial application + @description + These settings are global to the current window, but persistently + saved in the user's home directory. Updated values are broadcasted + in batch to all other windows, which in turn receive a `'dome.settings'` + event for synchronizing.<br/> + For local window settings, use `set()` instead. +*/ +export function setGlobalSetting( key , value ) { + writeSetting( false, key, value ); +} + +// -------------------------------------------------------------------------- +// --- Focus Management +// -------------------------------------------------------------------------- + +/** Current focus state of the main window. */ +export function isFocused() { return focus; } + +/** + @event 'dome.focus' + @param {boolean} state - updated focus state + @description Emitted when the application gain or loses focus. +*/ +ipcRenderer.on('dome.ipc.focus',(sender,value) => { + focus = value; + setContextAppNode(); + emitter.emit('dome.focus',value); +}); + +// -------------------------------------------------------------------------- +// --- Web Navigation +// -------------------------------------------------------------------------- + +/** + @event 'dome.href' + @param {string} href - internal `<a href=...>` target + @description + Emitted when the user clicks on a local `<a href=...>`. + URL with an `http://` protocole are opened externally + by the user's default browser. +*/ +ipcRenderer.on('dome.ipc.href',(href) => emitter.emit('dome.href',href)); + +// -------------------------------------------------------------------------- +// --- Function Component +// -------------------------------------------------------------------------- + +/** + @class + @summary Inlined Function React Component + @property {function} children - render function as children + @description + Allows to define an inlined functional component inside JSX. + The children function _can_ use hooks. + +@example +<Render> + {() => { + let [ state, setState ] = React.useState(); + … + return (<div>…</div>); + }} +</Render> +*/ +export const Render = ({children}) => { + return children(); +}; + +// -------------------------------------------------------------------------- +// --- React Hooks +// -------------------------------------------------------------------------- + +/** + @summary Hook to re-render on demand (Custom React Hook). + @return {function} to trigger re-rendering + @description + Returns a callback to trigger a render on demand. +*/ +export function useForceUpdate() +{ + const [tac,onTic] = React.useState(); + return () => onTic(!tac); +} + +/** + @summary Hook to re-render on Dome events (Custom React Hook). + @param {string} [event] - event name (default: `'dome.update'`) + @tutorial hooks + @description + Returns nothing. +*/ +export function useUpdate(evt = 'dome.update') +{ + const update = useForceUpdate(); + React.useEffect(() => { + emitter.on(evt,update); + return () => emitter.off(evt,update); + }); +} + +/** + @summary Hook to register callbacks to Dome events (Custom React Hook). + @param {string} event - Event to register on + @param {function} callback - The callback to register + @tutorial hooks + @description + Register the callback on event until the component is unmount. + Do not force the component to re-render (unless the callback does).<br/> + Returns nothing. +*/ +export function useEvent(evt,callback) +{ + React.useEffect(() => { + emitter.on(evt,callback); + return () => emitter.off(evt,callback); + }); +} + +/** + @summary Hook to register callbacks to events (Custom React Hook). + @param {EventEmitter} emitter - event emitter + @param {string} event - Event to register on + @param {function} callback - The callback to register + @tutorial hooks + @description + Register the callback on event until the component is unmount. + Do not force the component to re-render (unless the callback does).<br/> + Returns nothing. +*/ +export function useEmitter(emitter,evt,callback) +{ + React.useEffect(() => { + emitter.on(evt,callback); + return () => emitter.off(evt,callback); + }); +} + +const NULL = {}; // Dummy initial value + +// -------------------------------------------------------------------------- +// --- Commands Hooks +// -------------------------------------------------------------------------- + +/** + @summary Hook for command-line interface (Custom React Hook). + @return {array} `[argv,wdir]` command-line arguments and working directory + @tutorial hooks + @description + Returns the command-line arguments and working directory for the application + instance running in the window. Automatically updated on `dome.command` events. + + See also [Dome.onCommand](#.onCommand) event handler. +*/ +export function useCommand() { + useUpdate('dome.command'); + let wdir = System.getWorkingDir(); + let argv = System.getArguments(); + return [ argv , wdir ]; +} + +// -------------------------------------------------------------------------- +// --- Settings Hooks +// -------------------------------------------------------------------------- + +function useSettings( local, settings, defaultValue ) +{ + let [ value, setValue ] = React.useState(() => readSetting( local, settings, defaultValue )); + React.useEffect(() => { + if (settings) { + let callback = () => { + let v = readSetting( local, settings , defaultValue ); + setValue(v); + }; + emitter.on('dome.settings',callback); + return () => emitter.off( 'dome.settings', callback ); + } else { + let callback = () => setValue(defaultValue); + emitter.on('dome.defaults',callback); + return () => emitter.off( 'dome.defaults', callback ); + } + }); + let doUpdate = (upd) => { + const theValue = typeof(upd)==='function' ? upd(value) : upd ; + if (settings) writeSetting( local, settings, theValue ); + else setValue(theValue); + }; + return [ value, doUpdate ]; +} + +/** + @summary Local state with optional window settings (Custom React Hook). + @param {string} [settings] - optional window settings to backup the value + @param {any} [defaultValue] - the initial (and default) value + @return {array} `[value,setValue]` of the local state + @tutorial hooks + @description + Similar to `React.useState()` with persistent _window_ settings. + When the settings key is undefined, it simply uses a local React state. + Also responds to `'dome.settings'` to update the state and `'dome.defaults'` + to restore the default value. + + The `setValue` callback accepts either a value, or a function to be applied + on current value. +*/ +export function useState( settings, defaultValue ) { + return useSettings( true, settings, defaultValue ); +} + +/** + @summary Local boolean state with optional window settings (Custom React Hook). + @param {string} [settings] - optional window settings to backup the value + @param {boolean} [defaultValue] - the initial value (default is `false`) + @return {array} `[value,flipValue]` for the local state + @tutorial hooks + @description + Same as [useState](#.useState) with a boolean value that can be set or flipped: + - `flipValue()` change the value to its opposite; + - `flipValue(v)` change the value to `v`. +*/ +export function useSwitch( settings, defaultValue ) { + let [ value, update ] = useSettings( true, settings, defaultValue ); + return [ value, v => update(v===undefined ? !value : v) ]; +} + +/** + @summary Local state with global settings (Custom React Hook). + @param {string} settings - global settings for storing the value + @param {any} [defaultValue] - the initial and default value + @return {array} `[value,setValue]` of the local state + @tutorial hooks + @description + Similar to `React.useState()` with persistent _global_ settings. + When the settings key is undefined, it simply uses a local React state. + Also responds to `'dome.settings'` to update the state and `'dome.defaults'` + to restore the default value. + + The `setValue` callback accepts either a value, or a function to be applied + on current value. +*/ +export function useGlobalSetting( settings, defaultValue ) +{ + return useSettings( false, settings, defaultValue ); +} + +// -------------------------------------------------------------------------- +// --- Global States +// -------------------------------------------------------------------------- + +/** @event 'dome.state.update' + @description + Notify updates within a State object. +*/ + +const STATE_UPDATE = 'dome.state.update' ; + +/** + @summary Global state object. + @property {object} state - the current state properties + @property {object} defaults - the default state properties + @description + +You may use this class as convenient way to implement global +state for your Dome application. Simply create a state `s` with `new State(defaults)` +and use `s.setState()`, `s.getState()` or `s.state` property, and `s.useState()` +custom hooks. + +A state is also an event emitter that you can use to fire events, and you can use +the React custom hooks `s.useUpdate()` and `s.useEvent()`. + +All above methods are bound to `this` by the constructor. + +*/ +export class State extends EventEmitter +{ + + constructor(props) { + super(); + // Makes this field private + this.defaults = props ; + this.state = Object.assign( {}, props ); + this.update = this.update.bind(this); + this.getState = this.getState.bind(this); + this.setState = this.setState.bind(this); + this.clearState = this.clearState.bind(this); + this.replaceState = this.replaceState.bind(this); + this.useState = this.useState.bind(this); + this.useEvent = this.useEvent.bind(this); + this.useUpdate = this.useUpdate.bind(this); + } + + /** Emits the `dome.state.update` event */ + update() { this.emit('dome.state.update'); } + + /** Returns the state property. */ + getState() { return this.state; } + + /** @summary Update the state with (some) properties. + @param {object} props - the properties to be updated + @description + Update the state with `Object.assign`, like `setState()` on React components. + Also fire the `'dome.update'` property on the object. */ + setState(props) { + Object.assign( this.state, props ); + this.update(); + } + + /** @summary Replace (all) state properties. + @description + Replace the entire store with the new properties. + Also fire the `'dome.update'` property on the object. */ + replaceState(props) { + this.state = Object.assign( {}, props ); + this.update(); + } + + /** @summary Reset (all) state properties. + @description + Restore the entire store with the default properties. + Also fire the `'dome.state.update'` property on the object. */ + clearState() { + this.state = Object.assign( {}, this.defaults ); + this.update(); + } + + /** @summary Hook to use the state (custom React Hook). + @return {array} `[state,setState]` with current object properties and + function to update them. */ + useState() { + let forceUpdate = useForceUpdate(); + useEmitter( this, 'dome.state.update', forceUpdate ); + return [ this.state , this.setState ]; + } + + /** @summary Hook to re-render your component on State events. + @param {string} [event] - the event to listen to (defaults to `'dome.update'`) + */ + useUpdate(evt = 'dome.state.update') { + let forceUpdate = useForceUpdate(); + useEmitter( this, evt, forceUpdate ); + } + + /** @summary Hook to trigger callbacks on State events. + @param {string} event - the event to listen to + @param {function} callback - the callback triggered on event + */ + useEvent(evt,callback) { + useEmitter( this, evt, callback ); + } + +} + +// -------------------------------------------------------------------------- +// --- Timer Hooks +// -------------------------------------------------------------------------- + +// Collection of { pending, timer, period, time, event } indexed by period +const clocks = {}; + +const CLOCKEVENT = (period) => 'dome.clock.' + period ; + +const TIC_CLOCK = (clk) => () => { + if (0 < clk.pending) { + clk.time += clk.period ; + emitter.emit(clk.event,clk.time); + } else { + clearInterval(clk.timer); + delete clocks[clk.period]; + } +}; + +const INC_CLOCK = (period) => { + let clk = clocks[period] ; + if (!clk) { + let event = CLOCKEVENT(period); + let time = (new Date()).getTime(); + clk = { pending: 0, time, period, event }; + clocks[period] = clk ; + let tic = TIC_CLOCK(clk); + clk.timer = setInterval(tic,period); + } + clk.pending++; +}; + +const DEC_CLOCK = (period) => { + let clk = clocks[period] ; + if (clk) { + clk.pending--; + } +}; + +/** + @summary Synchronized start & stop timer (Custom React Hook). + @param {number} period - timer interval, in milliseconds (ms) + @param {boolean} [initStart] - whether to initially start the timer (default is `false`) + @tutorial hooks + @return {timer} Timer object + @description + Create a local timer, synchronized on a global clock, that can be started + and stopped on demand during the life cycle of the component. + + Each timer has its individual start & stop state. However, + all timers with the same period _are_ synchronized with each others. + + The timer object has the following properties and methods: + - `timer.start()` starts the timer, + - `timer.stop()` starts the timer, + - `timer.time` is the time stamp of the last clock (see below) + + It is safe to call `start()` and `stop()` whether the timer is running or not. + When `timer.time` is `-1`, it means the timer is stopped. + When `timer.time` is `0` it means the timer has just been started and no tic has + been received yet. The time stamp is in milliseconds; it is shared among all + timers synchronized on the same period and roughly equal to the `Date.getTime()` + of the associated clock. + + */ + +export function useClock(period,initStart) +{ + const [time,setTime] = React.useState(initStart ? 0 : -1); + const running = 0 <= time ; + React.useEffect(() => { + if (running) { + INC_CLOCK(period); + const event = CLOCKEVENT(period); + emitter.on(event,setTime); + return () => { + DEC_CLOCK(period); + emitter.off(event,setTime); + }; + } else + return undefined ; + }); + return { + time, + start: () => { if (!running) setTime(0); }, + stop: () => { if (running) setTime(-1); } + }; +} + +// -------------------------------------------------------------------------- +// --- Export +// -------------------------------------------------------------------------- + +export default { + platform, + DEVEL, + setTitle, + setModified, + isApplicationWindow, setApplicationWindow, + isPreferencesWindow, setPreferencesWindow, + isFocused, + emitter, emit, on, off, + addMenu, + addMenuItem, + setMenuItem, + popupMenu, + setWindowSetting, getWindowSetting, + setGlobalSetting, getGlobalSetting, + update, onUpdate, onReload, onCommand, + State, Render, + useForceUpdate, + useUpdate, useEvent, useEmitter, + useCommand, useClock, + useState, useSwitch, + useGlobalSetting +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/errors.js b/Ivette/src/dome/src/renderer/errors.js new file mode 100644 index 00000000000..bb3ea064aae --- /dev/null +++ b/Ivette/src/dome/src/renderer/errors.js @@ -0,0 +1,75 @@ +// -------------------------------------------------------------------------- +// --- Managing Errors +// -------------------------------------------------------------------------- + +import React from 'react' ; +import { Label } from 'dome/controls/labels' ; +import { Button } from 'dome/controls/buttons' ; + +/** @module dome/errors */ + +// -------------------------------------------------------------------------- +// --- Error Boundaries +// -------------------------------------------------------------------------- + +/** + @summary React Error Boundaries. + @property {string} [label] - Default error box label + @property {function} [onError] - Alternative renderer + @description + Install an error boundary. In case of error, the default + rendering is a warning button that output on console the + catched error. + + An alternative rendering can be supplied + with `onError:(error,info) => React.Element`. + + */ +export class Catch extends React.Component +{ + + constructor(props) { + super(props); + this.state = { }; + this.logerr = this.logerr.bind(this); + this.reload = this.reload.bind(this); + } + + dumpError(error,info) { + } + + componentDidCatch(error, info) { + this.setState({ error, info }); + } + + logerr() { + const { error, info } = this.state ; + console.error('[dome] Catched error:',error,info); + } + + reload() { + this.setState({ error: undefined, info: undefined }); + } + + render() { + const { error, info } = this.state ; + if (error) { + const { onError, label='Error' } = this.props ; + if (typeof(onError)==='function') + return onError(error,info,this.reload); + else + return ( + <div> + <Button icon='WARNING' kind='warning' + title={error} + onClick={this.logerr} /> + <Button icon='RELOAD' onClick={this.reload} /> + <Label>{label}</Label> + </div> + ); + } + return this.props.children || null ; + } +} + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/boxes.css b/Ivette/src/dome/src/renderer/layout/boxes.css new file mode 100644 index 00000000000..a53382360de --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/boxes.css @@ -0,0 +1,86 @@ +/* -------------------------------------------------------------------------- */ +/* --- Box Containers --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xBoxes-hbox +{ + display: flex ; + overflow: hidden ; + flex-flow: row nowrap ; + align-items: stretch ; +} + +.dome-xBoxes-vbox +{ + display: flex ; + overflow: hidden ; + flex-flow: column nowrap ; + align-items: stretch ; +} + +.dome-xBoxes-grid +{ + flex: 1 1 auto ; + overflow: auto ; + display: grid ; + display: grid; + grid-auto-rows: auto; + grid-auto-flow: row; + align-items: stretch; + align-content: start; + justify-content: start; +} + +/* -------------------------------------------------------------------------- */ +/* --- Extensibility --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xBoxes-pack +{ + flex: 0 0 auto ; + align-self: flex-start ; +} + +.dome-xBoxes-box +{ + flex: 0 0 auto ; +} + +.dome-xBoxes-fill +{ + flex: 1 1 auto ; +} + +.dome-xBoxes-scroll +{ + flex: 1 1 auto ; + overflow: auto ; +} + +.dome-container > .dome-xBoxes-fill +{ + width: 100% ; + height: 100% ; +} + +.dome-container > .dome-xBoxes-scroll +{ + width: 100% ; + height: 100% ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Spaces --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xBoxes-space +{ + flex: 0 1 24px ; +} + +.dome-xBoxes-filler +{ + flex: 1 1 24px ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/boxes.js b/Ivette/src/dome/src/renderer/layout/boxes.js new file mode 100644 index 00000000000..b648f612cfb --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/boxes.js @@ -0,0 +1,201 @@ +// -------------------------------------------------------------------------- +// --- Box Layout +// -------------------------------------------------------------------------- + +/** @module dome/layout/boxes + @description + +This modules offers several `<div>` containers with various +predefined layout. + +Boxes are the very elementary way to layout components horizontally +or vertically. The different kinds of proposed boxes differ in how they +extends in both directions: normal boxes extends +along their layout direction, _pack_ boxes don't extends and _fill_ boxes +extends along both directions. + +Grids layout their component from left-to-right inside predefined _columns_, +then vertically by wrapping cells in rows. + +The various containers are summarized on the table below: + +| **Box** | Layout | Extends | +|:-------------:|:-----------:|:----------:|:----------:| +| [Hbox](module-dome_layout_boxes.Hpack.html) | horiz. | horiz. | +| [Vbox](module-dome_layout_boxes.Vpack.html) | vert. | vert. | +| [Hpack](module-dome_layout_boxes.Hpack.html) | horiz. | none | +| [Vpack](module-dome_layout_boxes.Vpack.html) | vert. | none | +| [Hfill](module-dome_layout_boxes.Hpack.html) | horiz. | both | +| [Vfill](module-dome_layout_boxes.Vpack.html) | vert. | both | +| [Grid](module-dome_layout_boxes.Hpack.html) | columns | both | +| [Scroll](module-dome_layout_boxes.Scroll.html) | n/a | both | + +Inside a box, you may add `<Space/>` and `<Filler/>` to separate items. +Inside a grid, you may also use `<Space/>` or an empty `<div/>` for empty cells. + +<strong>Warning:</strong> large elements will be clipped if they overflow. +If you want to add scrolling capabilities to some item that does not manage overflow +natively, place it inside a `<Scroll/>` sub-container. + +*/ + +import React from 'react'; +import Dome from 'dome'; +import { Title } from 'dome/controls/labels' ; +import './boxes.css' ; + +// -------------------------------------------------------------------------- +// --- Generic Box +// -------------------------------------------------------------------------- + +const makeBox = ( boxClasses, props, morestyle ) => { + const { children, className, style, ...others } = props ; + const allClasses = className ? boxClasses + ' ' + className : boxClasses ; + const allStyles = morestyle ? (style ? Object.assign( {}, style, morestyle ) : morestyle) : style ; + return ( + <div className={allClasses} style={allStyles} {...others} > + {children} + </div> + ); +}; + +// -------------------------------------------------------------------------- +// --- Predefined Defaults +// -------------------------------------------------------------------------- + +/** + @class + @summary Horizontal box (extends horizontally, no overflow) + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + <strong>Warning:</strong> large elements will be clipped if they overflow. +*/ +export const Hbox = (props) => makeBox( 'dome-xBoxes-hbox dome-xBoxes-box' , props ); + +/** + @class + @summary Vertical box (extends vertically, no overflow) + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + <strong>Warning:</strong> large elements will be clipped if they overflow. +*/ +export const Vbox = (props) => makeBox( 'dome-xBoxes-vbox dome-xBoxes-box' , props ); + +/** + @class + @summary Compact Horizontal box (fixed dimensions, no overflow) + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + <strong>Warning:</strong> large elements would be clipped if they overflow. +*/ +export const Hpack = (props) => makeBox( 'dome-xBoxes-hbox dome-xBoxes-pack' , props ); + +/** + @class + @summary Compact Vertical box (fixed dimensions, no overflow) + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + <strong>Warning:</strong> large elements will be clipped if they overflow. +*/ +export const Vpack = (props) => makeBox( 'dome-xBoxes-vbox dome-xBoxes-pack' , props ); + +/** + @class + @summary Horizontally filled box (fixed height, maximal width, no overflow) + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + <strong>Warning:</strong> large elements will be clipped if they overflow. +*/ +export const Hfill = (props) => makeBox( 'dome-xBoxes-hbox dome-xBoxes-fill' , props ); + +/** + @class + @summary Vertically filled box (fixed width, maximal height, no overflow) + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + <strong>Warning:</strong> large elements will be clipped if they overflow. +*/ +export const Vfill = (props) => makeBox( 'dome-xBoxes-vbox dome-xBoxes-fill' , props ); + +// -------------------------------------------------------------------------- +// --- Scrolling & Spacing +// -------------------------------------------------------------------------- + +/** + @class + @summary Scrolling container + @property {object} [...props] - Extra properties passed to the `<div>` container +*/ +export const Scroll = (props) => makeBox( 'dome-xBoxes-scroll dome-container' , props ); + +/** + @class + @summary rigid space between items in a box + @property {object} [...props] - Extra properties passed to the `<div>` separator +*/ +export const Space = (props) => makeBox( 'dome-xBoxes-space' , props ); + +/** + @class + @summary extensible space between items in a box + @property {object} [...props] - Extra properties passed to the `<div>` separator +*/ +export const Filler = (props) => makeBox( 'dome-xBoxes-filler' , props ); + +// -------------------------------------------------------------------------- +// --- Grids +// -------------------------------------------------------------------------- + +/** + @class + @summary Grid box container + @property {string} [columns] - Grid column specifications + @property {object} [...props] - Extra properties passed to the `<div>` container + @description + Layout its children in a multi-column grid. Each column is specified by its + width, following the CSS Grid Layout `grid-template-columns` property. + + The rows are populated with children from left-to-right, using one column at a time. + Items layout can be modified by adding CSS Grid Layout item properties. + + Example: `<Grid columns="25% auto auto"> ... </Grid>` +*/ +export const Grid = ({columns='auto',...props}) => + makeBox( 'dome-xBoxes-grid', props , { gridTemplateColumns: columns }); + +// -------------------------------------------------------------------------- +// --- Folders +// -------------------------------------------------------------------------- + +/** + @class + @summary Foldable Vpack box + @property {string} label - box label + @property {string} [title] - box label tooltip + @property {string} [settings] - window setting to store the fold/unfold state + @property {boolean} [defaultUnfold] - initial state (default is `false`) + @property {React.Children} [children] - content of the vertical box + @description + A vertical `Vpack` box with a clickable head label to fold/unfold its content. +*/ +export function Folder( { settings, defaultUnfold=false, indent=18, label, title, children } ) +{ + const [ unfold , setUnfold ] = Dome.useState( settings, defaultUnfold ); + const icon = unfold ? 'TRIANGLE.DOWN' : 'TRIANGLE.RIGHT' ; + const onClick = () => setUnfold( !unfold ); + return ( + <Vpack> + <Hpack onClick={onClick}><Title icon={icon} label={label} title={title} /></Hpack> + <Vpack style={{ marginLeft:indent }}> + { unfold && children } + </Vpack> + </Vpack> + ); +} + +// -------------------------------------------------------------------------- + +export default { Hpack, Vpack, Hbox, Vbox, Hfill, Vfill, + Space, Filler, Scroll, Grid, Folder }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/dispatch.js b/Ivette/src/dome/src/renderer/layout/dispatch.js new file mode 100644 index 00000000000..fd40b802d3f --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/dispatch.js @@ -0,0 +1,118 @@ +// -------------------------------------------------------------------------- +// --- Dispatch Layout +// -------------------------------------------------------------------------- + +/** @module dome/layout/dispatch + @description + +This module allow to declare components anywhere in a component hierarchy +and to render them a totally different place. + +You shall wrap dispatched components inside a `<Dispatch.Item>` container, +and render them wherever you want with `<Dispatch.Render>`. Each target +place can display only one uniquely identified item. + +This can be also used to display some item among many in one unique place. +*/ + +import _ from 'lodash' ; +import React from 'react'; +import Dome from 'dome' ; + +// -------------------------------------------------------------------------- +// --- Global Dispatcher +// -------------------------------------------------------------------------- + +const EVENT = (id) => 'dome.dispatch.' + id ; +const ITEMS = {}; + +const getItem = (id) => { + let item = ITEMS[id]; + if (!item) item = ITEMS[id] = { + id, evt: EVENT(id) + }; + return item; +}; + +const trigger = (item) => { + if (item.rendered) { + item.rendered = false ; + setImmediate(() => Dome.emit(item.evt)); + } +}; + +const setItem = (id,children) => { + let item = getItem(id); + item.content = children ; + trigger(item); +}; + +const removeItem = (id) => { + let item = getItem(id); + item.content = null ; + trigger(item); +}; + +// -------------------------------------------------------------------------- +// --- Dispatched Items +// -------------------------------------------------------------------------- + +/** + @class + @summary Define dispatched item + @property {string} id - the item _global_ unique identifier + @property {React.Children} {children} - item contents + @description + Declare the content of some dispatched item. + Each item identifier shall be assigned once from the mounted + hierarchy of components. Otherwize, the content that would be + displayed is totally unpredictable. +*/ +export function Item({ id, children }) +{ + React.useEffect(() => { + setItem(id,children); + return () => removeItem(id); + }); + return null; +} + +// -------------------------------------------------------------------------- +// --- Render Targets +// -------------------------------------------------------------------------- + +/** + @class + @summary Render dispatched item + @property {string} id - the item _global_ unique identifier to render + @property {function|React.Children} {children} - conditional or alternative content (default: `null`) + @description + Render the content of some dispatched item. + In case multiple of rendering, the children elements would be shared + among several places, with unpredicatable behavior. + + If the render element has a function as children, it is passed the content of the + item, or undefined. This allows for conditional rendering, depending on whether the item + has been specified somewhere in the hierarchy or not. + + Otherwized, when the item is not specified, the render element display + its own content, if any. +*/ +export function Render({ id, children=null }) +{ + Dome.useUpdate(EVENT(id)); + let item = getItem(id); + item.rendered = true ; + if (typeof(children)==='function') + return children(item.content); + else { + let content = item.content || children ; + return content && <React.Fragment>{content}</React.Fragment>; + } +} + +// -------------------------------------------------------------------------- + +export default { Item, Render }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/forms.css b/Ivette/src/dome/src/renderer/layout/forms.css new file mode 100644 index 00000000000..23a1712dc34 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/forms.css @@ -0,0 +1,254 @@ +/* -------------------------------------------------------------------------- */ +/* --- Form Containers --- */ +/* -------------------------------------------------------------------------- */ + +/* Main Form */ +.dome-xForm-grid +{ + flex: 1 1 auto; + overflow: auto; + display: grid; + padding: 12px 32px; + grid-template-columns: [left] auto [field] auto [right] ; + grid-gap: 4px 12px; + grid-auto-rows: auto; + grid-auto-flow: row; + align-items: start; + align-content: start; + justify-content: start; +} + +/* Field List */ +.dome-xForm-list +{ + display: grid; + grid-template-columns: [field] auto [right] ; + grid-gap: 4px ; + grid-auto-rows: auto; + grid-auto-flow: row; + align-items: start; +} + +/* Block Container */ +.dome-xForm-block +{ + margin-bottom: 6px ; + margin-top: 6px ; + position: relative ; + grid-column-start: left ; + grid-column-end: right ; + justify-self: start ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Fields --- */ +/* -------------------------------------------------------------------------- */ + +/* Label */ +.dome-xForm-label +{ + position: relative ; + grid-column-start: left ; + grid-column-end: field ; + justify-self: end ; +} + +.dome-xForm-section +{ + margin-bottom: 6px ; + position: relative ; + left: -6px ; + grid-column-start: left ; + grid-column-end: right ; + justify-self: start ; +} + +.dome-xForm-section .dome-disabled { + color: #aaa ; +} + +.dome-xForm-hsep +{ + grid-column-start: left ; + grid-column-end: right ; + height: 6px ; +} + +.dome-xForm-fold +{ + position: absolute ; + top: 2px ; + fill: #888 ; + left: -14px ; +} + +.dome-xForm-block .dome-xForm-label +{ + display: none ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Field --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xForm-field +{ + position: relative ; + grid-column-start: field ; + grid-column-end: right ; + justify-self: start ; +} + +.dome-xForm-label.dome-disabled, .dome-xForm-field.dome-disabled +{ + color: #aaa ; + opacity: 0.9 ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Errors --- */ +/* -------------------------------------------------------------------------- */ + +/* Error Icon */ +.dome-xForm-error +{ + position: absolute ; + top: -1px ; + fill: darkorange ; + margin-left: 6px ; +} + +/* Error Warning */ +.dome-xForm-warning +{ + visibility: hidden ; + position: absolute ; + top: 3px ; + color: darkorange ; + margin-left: 4px ; + font-size: smaller ; +} + +/* Hovered Warning */ +.dome-xForm-error:hover .dome-xForm-warning +{ + visibility: visible ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Text Fields --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xForm-text-field +{ + font-size: 10pt ; + width: 180px ; + padding-top: 1px ; + padding-bottom: 1px ; + padding-right: 4px ; + padding-left: 4px ; +} + +.dome-xForm-textarea-field +{ + border-color: #d6d6d6 ; + font-size: 10pt ; + padding-top: 2px ; + padding-bottom: 2px ; + padding-right: 4px ; + padding-left: 4px ; +} + +.dome-xForm-field.dome-disabled .dome-xForm-textarea-field +{ + opacity: 0.6 ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Number Fields --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xForm-number-field +{ + text-align: right ; + padding-right: 12px ; + padding-left: 12px ; + width: 80px ; +} + +.dome-xForm-spinner-field +{ + text-align: right ; + padding-left: 12px ; + width: 80px ; +} + +.dome-xForm-units +{ + color: #888 ; + font-size: smaller ; + margin-left: 4px ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Sliders --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xForm-slider-field +{ + padding-right: 12px ; + padding-left: 12px ; + width: 120px ; +} + +.dome-xForm-slider-value +{ + position: relative ; + top: -4px ; +} + +.dome-xForm-slider-hide +{ + opacity: 0.0 ; + transition: opacity 0.5s ease-in 0.1s ; +} + +.dome-xForm-slider-show +{ + transition: none ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Date & Time --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xForm-date-field +{ + text-align: right ; + width: 137px ; +} + +.dome-xForm-time-field +{ + text-align: right ; + width: 109px ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Color --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xForm-color-field +{ + position: relative ; + top: -1px ; + height: 21px ; + width: 32px ; +} + +.dome-disabled .dome-xForm-color-field +{ + opacity: 0.2 ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/forms.js b/Ivette/src/dome/src/renderer/layout/forms.js new file mode 100644 index 00000000000..2753c40bff6 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/forms.js @@ -0,0 +1,1147 @@ +// -------------------------------------------------------------------------- +// --- Form Layout +// -------------------------------------------------------------------------- + +/** @module dome/layout/forms */ + +import React from 'react' ; +import Dome from 'dome' ; +import { SVG } from 'dome/controls/icons' ; +import { Checkbox, Radio, Select as Selector } from 'dome/controls/buttons' ; +import _ from 'lodash' ; +import './forms.css' ; + +// -------------------------------------------------------------------------- +// --- Utilities +// -------------------------------------------------------------------------- + +const Context = React.createContext(); + +const SELECT = (props,context) => props === undefined ? context : props ; +const ACCESS = (props,context,path) => props === undefined ? _.get(context,path) : props ; +const CONDITION = (context,cond,undef) => { + switch(typeof(cond)) { + case 'undefined': + return undef; + case 'string': + case 'array': + return _.get(context,cond); + default: + return cond; + } +}; + +const COMBINE = (a,b) => { + if (a === undefined) return b; + if (b === undefined) return a; + return (...args) => { a(...args); b(...args); }; +}; + +const UPDATE = (value,error,path,callback) => callback && + ((v,e) => { + let update = value || {} ; + _.set( update, path, v ); + let errors ; + if (error || e) { + errors = error || {} ; + _.set( errors, path, e ); + if (!_.find(errors)) + errors = undefined; + } + callback(update,errors); + }); + +const CHECK = (validate,v) => { + if (typeof(validate) === 'function') + return validate(v); + if (_.isRegExp(validate)) + return validate.test(v); + return validate; +}; + +const ERROR = (validate,warning,v) => { + let ok = CHECK(validate,v); + switch(ok) { + case undefined: + case true: + return undefined ; + default: + return ok || warning ; + } +}; + +const VALIDATE = (validate,warning,callback) => { + if (!validate) return callback; + return ((v,e) => { + if (!callback) return; + else if (v===undefined || e) callback(v,e); + else { + let e = ERROR(validate,warning,v); + callback(v,e); + } + }); +}; + +const RENDER = (children,context) => ( + children ? + ( typeof(children)==='function' + ? children(context) + : children ) + : null +); + +const ONCHANGE = (onChange) => + typeof(onChange)==='function' + ? (evt) => onChange(evt.target.value) + : undefined ; + +const CLASSES = (...args) => _.filter(args).join(' '); + +// -------------------------------------------------------------------------- +// --- Filtering DataFlow +// -------------------------------------------------------------------------- + +const FILTER_ERROR = (err) => + err ? _.toString(err) : 'Invalid input, enter a new value to fix' +; + +class FILTER extends React.Component +{ + + constructor(props) { + super(props); + this.state = this.forward(); + this.onChange = this.onChange.bind(this); + if (props.period) + this.backward = _.debounce(this.backward,props.period); + } + + componentDidUpdate(prevProps) { + const props = this.props ; + if (props.value !== prevProps.value || + props.error !== prevProps.error) + this.setState(this.forward()); + } + + onChange(value,error) { + this.setState({value,error}); + this.backward(value,error); + } + + forward() { + try { + const { input , value , error } = this.props ; + return { value: input ? input(value) : value, error }; + } catch(err) { + return { value: undefined, error: FILTER_ERROR(err) }; + } + }; + + backward(v,e) + { + const { output, onChange } = this.props ; + try { + if (output) v = output(v); + } catch(err) { + this.setState({error: FILTER_ERROR(err)}); + return; + } + if (onChange) onChange(v,e); + } + + render() { + const { disabled, children } = this.props ; + const { value, error } = this.state ; + const context = { onChange: this.onChange, disabled, value, error }; + return ( + <Context.Provider value={context}> + {RENDER(children,context)} + </Context.Provider> + ); + } + +} + +// -------------------------------------------------------------------------- +// --- Generic Field +// -------------------------------------------------------------------------- + +const PERIOD = (latency) => { + switch(typeof(latency)) { + case 'undefined': return 0; + case 'number': return latency; + default: + return latency ? 600 : 0 ; + } +}; + +/** + @class + @summary Generic context wrapper for field values + @property {string} [path] - select a property in the context value (and error) + @property {any} [value] - set the inherited or edited value + @property {any} [error] - set the inherited or edited error + @property {function} [input] - pre-processing of input values (after `path` selection) + @property {function} [output] - post-processing of output values (before `path` update) + @property {function} [onChange] - callback for edited values and errors + @property {boolean|string|function} [disabled] - disabled field (default is `false`) + @property {boolean|string|function} [enabled] - conditional enabling (default is `true`) + @property {boolean|string|function} [visible] - conditional rendering (default is `true`) + @property {boolean|string|function} [hidden] - conditional hidding (default is `false`) + @property {boolean|regexp|function} [validate] - validation of the updated value + @property {string} [warning] - error message in case `validate` returns `false` + @property {boolean|number} [latency] - delay validation and propagation callbacks + @property {boolean} [state] - maintain a locally edited state (default is `false`) + @property {React.children|function} [children] - elements to render in the new context + @description + +Forms are based on a local context that can be modified by using this multi-purposed +component. The local context consists of: +- `value`: the currently edited value; +- `error`: the last emitted error for this value; +- `onChange(value[,error])`: the callback to be used on updates; +- `disabled`: whether this value can be edited or not. + +Undefined properties are inherited from the context. If the `path` property is defined, +the `<Select>` component extract the associated value and error from the inherited context. +When both `path` and `value` properties are defined, the specified value takes the precedence. +Access and updates of `path` are performed with the lodash `_.get()` and `_.set()` functions. +Although, the `<Select>` might perform in-place modifications of previous object or array value. +Use `_.cloneDeep()` to build a (recursive) copy of some value. + +Before being processed downward, the inherited or selected value can be transformed. +The `input` function is applied on incomming value, and `output` function is applied +on updated values. + +The specified callback `onChange` is invoked with the updated value and error. The callback +inherited from the context is _also_ notified. When the `path` property is set, +the contextual callback will be notified with the full context values and errors, +updated with local changes to the selected path. + +The validation callback is invoked on updates. It shall return `undefined` +or a string explaining why the value is invalid. Boolean are also accepted, +leading to an error string defined by the `warning` property, which defaults to `"Invalid field"`. +Alternatively, `validate` can be a regexp that is tested against the value. +For instance, to accept only numbers, you can use `validate={/^[0-9]+$/}` +and `warning='Must be a number'`. + +To avoid too many callback and validation checks, typically for text-based fields, it is possible to +set a latency period before validating the input and emitting the callback. In such a case, a transient +local state for value and error is maintained until the edited value is stabilized, before performing +validation and upward propagation. The default lantency period is 600ms. + +It is possible to conditionally enabling, disabling or hiding the content by using +the `disabled`, `enabled`, `visible` and `hidden` properties. They all can be boolean values, +or path in or function of the inherited value. For instance, `<Select path='f.g' enabled='f.ok'/>` +would allow to edit the value `value.f.g`, but disable edition when `value.f.ok` is falsy. +Remark that if the inherited context is disabled, the selected content is disabled too. + +When latency, or input/output transformation are required, a local state is maintained. +Otherwized, context and callbacks are propagated upward and backward. However, you can +force this local state to be maintained by specifying the property `state` to `true`. +This shall be used only at top-level for implementing a non-controlled component. + +*/ +export function Select({ + path, latency, + defaultValue:def, + children, state, + ...props +}) { + let context = React.useContext( Context ); + if (!CONDITION(context.value,props.visible,true) || + CONDITION(context.value,props.hidden,false)) + return null; + let disabled = context.disabled + || CONDITION(context.value,props.disabled,false) + || !CONDITION(context.value,props.enabled,true); + let value,error,callback ; + if (path) { + value = ACCESS( props.value , context.value , path ); + error = ACCESS( props.error , context.error , path ); + if (!disabled) + callback = UPDATE(context.value,context.error,path,context.onChange); + } else { + value = SELECT( props.value , context.value ); + error = SELECT( props.error , context.error ); + if (!disabled) + callback = context.onChange; + }; + + let onChange ; + if (!disabled) { + onChange = VALIDATE( props.validate, props.warning, + COMBINE(props.onChange,callback) ); + } + + if (props.validate && value && !error) { + error = ERROR( props.validate, props.warning, value ); + } + + let newContext = { value,error, disabled, onChange }; + if (state || latency || props.input || props.output) { + return ( + <FILTER period={PERIOD(latency)} + input={props.input} + output={props.output} + {...newContext}> + {children} + </FILTER> + ); + } else + return ( + <Context.Provider value={newContext}> + {RENDER(children,newContext)} + </Context.Provider> + ); +} + +// -------------------------------------------------------------------------- +// --- Form Container +// -------------------------------------------------------------------------- + +/** + @class + @summary Form Container + @property {string} [className] - Container additional class + @property {object} [style] - Container additional style + @property {object} [value] - Set the form context value + @property {object} [error] - Set the form context error + @property {boolean} [disabled] - Disables the form (default is `false`) + @property {onChange} [function] - Callback to updated `(value,error)` + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @property {React.children|function} [children] - Fields to populate the form + @description + + Setup a form context with the provided values. + A local state is maintained unless you fully control the `value` and `error` + properties. You may also specify any other properties of the + [Select](module-dome_layout_forms.Select.html) filter component. + +*/ + +export const Form = ({className,style,...props}) => + ( + <div className={CLASSES('dome-xForm-grid',className)}> + <Context.Provider value={{}}> + <Select state {...props}/> + </Context.Provider> + </div> + ); + +// -------------------------------------------------------------------------- +// --- Generic Error Badge +// -------------------------------------------------------------------------- + +const ERROR_MSG = (error) => { + switch(typeof(error)) { + case 'undefined': + return undefined ; + case 'string': + return error; + case 'object': + case 'array': + var n = 0; + _.forEach(error,(err) => { if (err) n++; }); + if (n==1) return 'Invalid field' ; + if (n>1) return n + ' Invalid fields' ; + return undefined ; + default: + return _.toString(error); + } +}; + +/** + @class + @summary Warning badge with description + @property {string} [warn] - the short message (hovered) + @property {number} [offset] - the label offset (Cf. field) + @property {any} [error] - the error description (in tooltip) + @property {full} [boolean] - full error message on error (no tooltip, default `false`) + @description + Display a warning badge with a tooltip when the `error` is not + undefined. Otherwize, renders nothing. +*/ +export const Warning = ({full,warn,offset,error,width}) => { + let msg = ERROR_MSG(error); + return msg ? ( + <div className='dome-xIcon dome-xForm-error' + style={{top: (offset-2)}} > + <SVG id='WARNING' size={11} title={full ? undefined : msg}/> + {(full + ? <span className='dome-xForm-warning' style={{width: 'max-content'}}>{msg}</span> + : <span className='dome-xForm-warning'>{warn}</span> + )} + </div> + ) : null ; +}; + +// -------------------------------------------------------------------------- +// --- Section Container +// -------------------------------------------------------------------------- + +const TITLE_ENABLED = 'dome-text-title' ; +const TITLE_DISABLED = 'dome-text-title dome-disabled' ; + +/** + @class + @summary Expandable Section sub-form + @property {string} label - Section title + @property {string} [title] - Tooltip text + @property {string} [path] - Fields selection + @property {string} [settings] - User's settings for making fold/unfold state persistent + @property {boolean} [unfold] - Default fold/unfold state (default is `false`) + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @property {React.children|function} [children] - Section field content + @description + Wraps some fields inside a foldable section. + When unfolded, the section fields are not visible but still rendered. +*/ + +export function Section(props) +{ + + let [ unfold, setUnfold ] = Dome.useState(props.settings,props.unfold); + + const onSwitch = () => setUnfold(!unfold); + + const { label, title, path, children, ...otherProps } = props ; + + return ( + <Select path={path} {...otherProps}> + {(context) => ( + <React.Fragment> + <div className='dome-xForm-section'> + <div className='dome-xForm-fold' onClick={onSwitch}> + <SVG id={unfold?'TRIANGLE.DOWN':'TRIANGLE.RIGHT'} size={11}/> + </div> + <label className={ (path && context.disabled) ? TITLE_DISABLED : TITLE_ENABLED } + title={title}> + {label} + </label> + { unfold && path && <Warning full error={context.error}/> } + </div> + { unfold && RENDER(children,context) } + { unfold && <div className='dome-xForm-hsep'/> } + </React.Fragment> + )} + </Select> + ); +} + +// -------------------------------------------------------------------------- +// --- Block Container +// -------------------------------------------------------------------------- + +/** + @class + @summary Full width form block + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @property {React.children|function} [children] - Block content + @description + Wraps its children inside the entire width of the form. +*/ + +export const Block = ({ children, ...props }) => ( + <Select {...props}> + {(context) => ( + <div className='dome-xForm-block'> + {RENDER(children,context)} + </div>)} + </Select> +); + +// -------------------------------------------------------------------------- +// --- Generic Fields +// -------------------------------------------------------------------------- + +let fid = 0 ; + +const LABEL_ENABLED = 'dome-xForm-label dome-text-label'; +const LABEL_DISABLED = 'dome-xForm-label dome-text-label dome-disabled'; +const FIELD_ENABLED = 'dome-xForm-field dome-text-label'; +const FIELD_DISABLED = 'dome-xForm-field dome-text-label dome-disabled'; + +/** + @class + @summary Generic Custom Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {number} [offset] - Vertical label offset (for baseline alignment) + @property {boolean|string} [warn] - Display errors (default: `true`) + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @property {React.children|function} [children] - Custom field content + @description + +Field layout inside a Form container. +The custom field component is positionned on the left of the label, right-aligned. +The label itself is left-aligned with the other fields. + +The Field component setup a [Select](module-dome_layout_forms.Select.html) +filter for your custom component. Additionnaly, if you use a custom function rendering, +the context is enriched with the `id` of the `<label/>` DOM element of the label, that +you can use with `<input htmlFor={id}/>` as custom field component. + +A warning badge is displayed on the right of your custom component, unless `warn:false` +is specified. When hovered, the badge displays `Error` or the specified `string`. When +hovered for a while, a full description of the error is displayed in a tooltip. +*/ + +export class Field extends React.Component +{ + + constructor(props) { + super(props); + this.id = props.id || 'DOME$' + (fid++) ; + } + + render() { + const id = this.id ; + const { label, title, offset=1, children, warn='Error', ...props } = this.props ; + return ( + <Select {...props}> + {(context) => ( + <React.Fragment> + <label className={context.disabled ? LABEL_DISABLED : LABEL_ENABLED} + style={{top: offset}} + htmlFor={id} + title={title}> + {label} + </label> + <div className={context.disabled ? FIELD_DISABLED : FIELD_ENABLED}> + {RENDER(children,Object.assign(context,{id}))} + {warn && <Warning offset={offset} warn={warn} error={context.error}/>} + </div> + </React.Fragment> + )} + </Select> + ); + } + +} + +// -------------------------------------------------------------------------- +// --- Field List Container +// -------------------------------------------------------------------------- + +/** + @class + @summary Field List Container + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {boolean} [warn] - Display errors (default: `false`) + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @property {React.children|function} [children] - List field content + @description + +Render its field children in a right-aligned list on the left of the label. +Typically designed for a list of checkboxes and radio buttons. + +Inside the field list, the field-label column no more exists. Hence, text field labels are +typically never displayed when placed in a field list. + +*/ +export const FieldList = ({ label, title, warn=false, children, ...props }) => ( + <Field label={label} title={title} warn={warn} {...props}> + <div className='dome-xForm-list'> + {children} + </div> + </Field> +); + +// -------------------------------------------------------------------------- +// --- Text Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Text Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [placeholder] - Input field place holder + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Text Input element. The default latency is set to 600ms. +*/ +export const FieldText = ({ className, style, latency=true, placeholder, ...props }) => ( + <Field offset={4} latency={latency} {...props}> + {({id,value,disabled,onChange}) => ( + <input id={id} + type='text' + value={value || ''} + className={CLASSES('dome-xForm-text-field',className)} + style={style} + disabled={disabled} + placeholder={placeholder} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- Code Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Monospaced Text Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [placeholder] - Input field place holder + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Text Input element. The default latency is set to 600ms. +*/ +export const FieldCode = ({ className, style, latency=true, placeholder, ...props }) => ( + <Field offset={4} latency={latency} {...props}> + {({id,value,disabled,onChange}) => ( + <input id={id} + type='text' + value={value || ''} + className={CLASSES('dome-xForm-text-field dome-text-code',className)} + style={style} + disabled={disabled} + placeholder={placeholder} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- TextArea Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Text Area Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [className] - Input field additional class + @property {string} [placeholder] - Input field place holder + @property {number} [cols] - Number of columns (default 35, min 5) + @property {number} [rows] - Number of lines (default 5, min 2) + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Text Input element. The default latency is set to 900ms. +*/ +export const FieldTextArea = ({ className, style, cols=35, rows=5, + placeholder, latency=900, ...props }) => ( + <Field offset={4} latency={latency} {...props}> + {({id, value, disabled, onChange }) => ( + <textarea id={id} + type='text' + className={CLASSES('dome-xForm-textarea-field',className)} style={style} + disabled={disabled} + wrap='off' spellchecker='true' + value={value || ''} + cols={Math.max(5,cols)} + rows={Math.max(1,rows-1)} + placeholder={placeholder} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- CodeArea Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Text Area Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [className] - Input field additional class + @property {string} [placeholder] - Input field place holder + @property {number} [cols] - Number of columns (default 35, min 5) + @property {number} [rows] - Number of lines (default 5, min 2) + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Text Input element. The default latency is set to 900ms. +*/ +export const FieldCodeArea = ({ className, style, cols=35, rows=5, + placeholder, latency=900, ...props }) => ( + <Field offset={4} latency={latency} {...props}> + {({id, value, disabled, onChange }) => ( + <textarea id={id} + ref={this.area} + type='text' + className={CLASSES('dome-xForm-textarea-field dome-text-code',className)} style={style} + disabled={disabled} + wrap='off' spellchecker='false' + value={value || ''} + cols={Math.max(5,cols)} + rows={Math.max(1,rows-1)} + placeholder={placeholder} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- Number Field +// -------------------------------------------------------------------------- + +const PARSE_NUMBER = (v,debug) => { + let n = parseFloat(v); + if (Number.isNaN(n)) { + let msg = "Invalid number format"; + if (debug) { + let txt = _.toString(v); + if (txt.length > 20) txt = txt.substring(0,19)+'…' ; + msg += ": «" + txt + "»" ; + } + throw msg ; + } + return n; +}; +const TEXT_OF_NUMBER = (v) => v===undefined ? '' : PARSE_NUMBER(v,true).toLocaleString('en'); +const NUMBER_OF_TEXT = (s) => s==='' ? undefined : PARSE_NUMBER(s.replace(/[ ,]/g,'')); + +/** + @class + @summary Number Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [placeholder] - Input field place holder + @property {string} [units] - Number units or currency + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field to edit number values with a Text Input element. + The default latency is set to 600ms. Numbers are rendered in the english locale, grouping thousands + with «,». The currency or units is displayed on the right of the field. The edited text + is converted back and forth to number values with `parseFloat`. +*/ +export const FieldNumber = + ({ className, style, latency=true, units, placeholder, ...props }) => ( + <Field latency={latency} + input={TEXT_OF_NUMBER} + output={NUMBER_OF_TEXT} + {...props}> + {({id,value,disabled,onChange}) => ( + <React.Fragment> + <input id={id} + type='text' + value={value || ''} + className={CLASSES('dome-xForm-number-field',className)} + style={style} + disabled={disabled} + placeholder={placeholder} + onChange={ONCHANGE(onChange)} + /> + {units && <label className='dome-text-label dome-xForm-units'>{units}</label>} + </React.Fragment> + )} + </Field> + ); + +// -------------------------------------------------------------------------- +// --- Spinner field +// -------------------------------------------------------------------------- + +const PARSE_INT = (v,debug) => { + let n = parseInt(v); + if (Number.isNaN(n)) { + let msg = "Invalid number format"; + if (debug) { + let txt = _.toString(v); + if (txt.length > 20) txt = txt.substring(0,19)+'…' ; + msg += ": «" + txt + "»" ; + } + throw msg ; + } + return n; +}; +const TEXT_OF_INT = (v) => v===undefined ? '' : PARSE_INT(v,true); +const INT_OF_TEXT = (s) => s==='' ? undefined : PARSE_INT(s); + +const INT_RANGE = (min,max,warning) => (v) => + (min <= v && v <= max) ? undefined : + warning || 'Range ' + min + '…' + max ; + +/** + @class + @summary Spinner Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [placeholder] - Input field place holder + @property {string} [units] - Number units or currency + @property {number} [min] - Minimum value (default: 0) + @property {number} [max] - Maximum value (default: 1000) + @property {number} [step] - Stepper increment + @property {string} [warning] - Out of bound message (default is explaining the range) + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field to edit integer numbers with a spinner element. + The default latency is set to 600ms. +*/ +export const FieldSpinner = + ({ className, style, latency=true, units, placeholder, min=0, max=1000, step, ...props }) => ( + <Field latency={latency} + input={TEXT_OF_INT} + output={INT_OF_TEXT} + validate={INT_RANGE(min,max)} + {...props}> + {({id,value,disabled,onChange}) => ( + <React.Fragment> + <input id={id} + type='number' + value={ value === undefined ? '' : value } + className={CLASSES('dome-xForm-spinner-field',className)} + style={style} + min={min} + max={max} + step={step} + disabled={disabled} + placeholder={placeholder} + onChange={ONCHANGE(onChange)} + /> + {units && <label className='dome-text-label dome-xForm-units'>{units}</label>} + </React.Fragment> + )} + </Field> + ); + +// -------------------------------------------------------------------------- +// --- Slider field +// -------------------------------------------------------------------------- + +const RESET_RANGE = (onChange,min,max) => + onChange && (() => onChange(Math.round( min + (max - min) / 2 ))); + +const SHOW_VALUE = (show,v) => { + if (typeof(show)==='function') + return show(v); + if (v>0) return '+' + v ; + if (v<0) return v ; + return undefined ; +}; + +const SLIDER_VALUE = 'dome-text-label dome-xForm-units dome-xForm-slider-value ' ; +const SHOW_SLIDER = SLIDER_VALUE + 'dome-xForm-slider-show' ; +const HIDE_SLIDER = SLIDER_VALUE + 'dome-xForm-slider-hide' ; + +class REVEAL extends React.Component { + + constructor(props) { + super(props); + this.state = { shown: false }; + this.fadeOut = _.debounce(this.fadeOut,PERIOD(props.latency)); + } + + componentDidUpdate(prevProps) { + if (prevProps.value !== this.props.value) { + this.fadeIn(); + this.fadeOut(); + } + } + + fadeIn() { + if (!this.state.shown) this.setState({ shown: true }); + } + + fadeOut() { + if (this.state.shown) this.setState({ shown: false }); + } + + render() { + const { show, value } = this.props ; + const { shown } = this.state ; + return ( + <label className={shown ? SHOW_SLIDER : HIDE_SLIDER}>{SHOW_VALUE(show,value)}</label> + ); + } + +} + + +/** + @class + @summary Slider Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {number} [min] - Minimum value (default: -24) + @property {number} [max] - Maximum value (default: 24) + @property {number} [step] - Stepper increment (default: 1) + @property {boolean} [reset] - Reset on double click (default is `true`) + @property {boolean|function} [show] - Display the selected value on the right (default is `true`) + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field to edit integer numbers with a spinner element. + The default latency is set to 600ms. Double click on the slider reset it + to its median value, unless `toreset` is specified. The `show` flag can be set to display + the actual value when the slider is dragged. Alternatively, a function can be provided + for computing the text to display for the dragged value. +*/ +export const FieldSlider = + ({ className, style, latency=true, min=-24, max=24, step=1, reset=true, show=true, ...props }) => ( + <Field latency={latency} + input={TEXT_OF_INT} + output={INT_OF_TEXT} + {...props}> + {({id,value,disabled,onChange}) => ( + <React.Fragment> + <input id={id} + type='range' + value={ value === undefined ? '' : value } + className={CLASSES('dome-xForm-slider-field',className)} + style={style} + min={min} + max={max} + step={step} + disabled={disabled} + onDoubleClick={reset ? RESET_RANGE(onChange,min,max) : undefined} + onChange={ONCHANGE(onChange)} + /> + {show && <REVEAL latency={latency} show={show} value={value}/>} + </React.Fragment> + )} + </Field> + ); + +// -------------------------------------------------------------------------- +// --- Date Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Date Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [min] - Minimum date (default to `undefined`) + @property {string} [max] - Maximum date (default to `undefined`) + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Date Input element. The default latency is set to 600ms. + The date is presented in english locale, with format `mm/dd/yyyy`, but the internal value + is a string compatible with javascript `Date('yyyy-dd-mm')` format. +*/ +export const FieldDate = ({ className, style, latency=true, min, max, ...props }) => ( + <Field latency={latency} {...props}> + {({id,value,disabled,onChange}) => ( + <input id={id} + type='date' + value={value || ''} min={min} max={max} + className={CLASSES('dome-xForm-date-field',className)} + style={style} + disabled={disabled} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- Time Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Time Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [min] - Minimum time (default to `undefined`) + @property {string} [max] - Maximum time (default to `undefined`) + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Time Input element. The default latency is set to 600ms. + The time is presented in english locale, but its internal value is a string 'hh:mm' + on 24h per day basis. This internal format can be used to form a valid javascript + `Date('yyyy-mm-ddThh:mm')` object. +*/ +export const FieldTime = ({ className, style, latency=true, min, max, ...props }) => ( + <Field latency={latency} {...props}> + {({id,value,disabled,onChange}) => ( + <input id={id} + type='time' + value={value || ''} min={min} max={max} + className={CLASSES('dome-xForm-time-field',className)} + style={style} + disabled={disabled} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- Date Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Color Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + Field with a Text Input element. The default latency is set to 600ms. +*/ +export const FieldColor = ({ className, style, latency=true, ...props }) => ( + <Field latency={latency} {...props}> + {({id,value,disabled,onChange}) => ( + <input id={id} + type='color' + value={value || '#ffffff'} + className={CLASSES('dome-xForm-color-field',className)} + style={style} + disabled={disabled} + onChange={ONCHANGE(onChange)} + /> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- Select Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Select Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {string} [placeholder] - Selector placeholder + @property {string} [className] - Input field additional class + @property {object} [style] - Input field additional style + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @property {option|optgroup} [children] - HTML options of the `<select>` element + @description + Field with a Select element. Children must be standard `<option>` and `<optgroup>` elements. + Typically: + + ``` + <FieldSelect placeholder='Choose a value'> + <option value='A'>Item A</option> + <option value='B'>Item B</option> + <option value='C'>Item C</option> + </FieldSelect> + ``` + +*/ +export const FieldSelect = ({ className, style, children, placeholder, ...props }) => ( + <Field {...props}> + {({id,value,disabled,onChange}) => ( + <Selector id={id} + className={className} + style={style} + placeholder={placeholder} + value={value} + onChange={onChange} > + {children} + </Selector> + )} + </Field> +); + +// -------------------------------------------------------------------------- +// --- CheckBox Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Checkbox Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {boolean} [inverted] - Inverted value (incompatible with `input` and `output` properties) + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + A check box field. +*/ + +export const FieldCheckbox = ({ label, title, inverted, ...props }) => { + let transform = inverted ? (v) => !v : (v) => !!v ; + return ( + <Select input={transform} output={transform} {...props}> + {({value,disabled,onChange}) => ( + <Checkbox className={disabled ? FIELD_DISABLED : FIELD_ENABLED} + label={label} title={title} + disabled={disabled} + value={value} onChange={onChange}/> + )} + </Select> + ); +}; + +// -------------------------------------------------------------------------- +// --- Radio Field +// -------------------------------------------------------------------------- + +/** + @class + @summary Radio Button Field + @property {string} [label] - Field label + @property {string} [title] - Field tooltip text + @property {any} [value] - Value associated with the radio button + @property {any} [...props] - [Select](module-dome_layout_forms.Select.html) properties + @description + A radio button field. + + <strong>Note:</strong> there is no need for using a radio group here, + since the selected value is taken from the context. +*/ + +export const FieldRadio = ({ label, title, value, ...props }) => { + return ( + <Select {...props}> + {({value:selection,disabled,onChange}) => ( + <Radio className={disabled ? FIELD_DISABLED : FIELD_ENABLED} + label={label} title={title} + disabled={disabled} + value={value} + selection={selection} + onSelection={onChange}/> + )} + </Select> + ); +}; + +// -------------------------------------------------------------------------- +// --- Exports +// -------------------------------------------------------------------------- + +export default { + Select, + Form, + Block, + Field, + Section, + FieldText, + FieldCode, + FieldTextArea, + FieldCodeArea, + FieldNumber, + FieldSpinner, + FieldSlider, + FieldDate, + FieldTime, + FieldColor, + FieldSelect, + FieldList, + FieldCheckbox, + FieldRadio +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/frames.js b/Ivette/src/dome/src/renderer/layout/frames.js new file mode 100644 index 00000000000..d16aa614cf7 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/frames.js @@ -0,0 +1,211 @@ +// -------------------------------------------------------------------------- +// --- Frames +// -------------------------------------------------------------------------- + +/** @module dome/layout/frames */ + +import React from 'react' ; +import Dome from 'dome' ; +import { dispatch } from 'dome/misc/register' ; +import { Vfill } from 'dome/layout/boxes' ; +import { SideBar } from 'dome/layout/sidebars' ; +import { ToolBar } from 'dome/layout/toolbars' ; +import { TabsBar , TabContent } from 'dome/layout/tabs' ; +import { Splitter } from 'dome/layout/splitters' ; + +const callbacks = (f,g) => (f ? (g ? (id) => { f(id); g(id); } : f ) : g ); + +// -------------------------------------------------------------------------- +// --- Frame Component +// -------------------------------------------------------------------------- + +/** + @class + @summary Main view with optional tabs, toolbar and sidebar. + @property {string} [settings] - User-setting base name for + persistent selection and customization + @property {string} [selectedTab] - Currently selected tab + @property {string} [selectedItem] - Currently selected sidebar item + @property {string} [defaultTab] - Default selected tab (see also default tab's property) + @property {string} [defaultItem] - Default selected item + @property {function} [onTabClose] - tab closing callback + @property {function} [onTabSelection] - tab selection callback + @property {function} [onItemSelection] - sidebar item selection callback + @property {boolean} [hideToolbar] - hide tool bar (default is `false`) + @property {boolean} [hideTabsbar] - hide tabs bar (default is `false`) + @description + + ##### Content + The Frame layout and its decorations are specified according to + the type of its children elements: + - [Tab](module-dome_layout_tabs.Tab.html), if any, will be rendered into an optional + [TabsBar](module-dome_layout_tabs.TabsBar.html) and the selected tab content + will be rendered into the main content of the frame. + - [Sidebar items](module-dome_layout_sidebars.html), if any, will be rendered + inside a sidebar on the left of the frame. + - [Toolbar items](module-dome_layout_toolbars.html), if any, + will be rendered inside a toolbar on top of the frame. + - The remaining elements will be rendered (inside a vertical box) into the + main content the frame, provided there is no defined tab. + + + ##### Callbacks + Both general callbacks and tab ones are invoked + when the user select or close a tab. The tab callbacks are invoked _before_ the + frame ones. + + + ##### Settings + When provided, user selection will be saved in user's settings + under the following keys (when relevant): + - `'<settings>.dome.tab'` tab selection + - `'<settings>.dome.item'` item selection + - `'<settings>.dome.sidebar'` position of side-bar splitter + - `'<settings>.dome.section'` visibility of side-bar sections +*/ + +export class Frame extends React.Component +{ + + constructor(props) + { + super(props); + const settings = props.settings ; + const derived = ( selected , user , def ) => + (selected || ( settings && Dome.getWindowSetting( settings + user ) ) || def) ; + var selectedTab = derived( props.selectedTab , '.dome.tab' , props.defaultTab ); + var selectedItem = derived( props.selectedItem , '.dome.item' , props.defaultItem ); + this.state = { selectedTab , selectedItem }; + this.handleSelectTab = this.handleSelectTab.bind(this); + this.handleSelectItem = this.handleSelectItem.bind(this); + } + + // -------------------------------------------------------------------------- + // --- Life Cycle + // -------------------------------------------------------------------------- + + componentWillMount() { + const onTabSelection = this.props.onTabSelection ; + if (onTabSelection) { + const stateId = this.state.selectedTab ; + const propsId = this.props.selectedTab ; + if (stateId !== propsId) setImmediate(() => onTabSelection( stateId )); + } + const onItemSelection = this.props.onItemSelection ; + if (onItemSelection) { + const stateId = this.state.selectedItem ; + const propsId = this.props.selectedItem ; + if (stateId !== propsId) setImmediate(() => onItemSelection( stateId )); + } + } + + componentDidUpdate() { + const tabid = this.props.selectedTab ; + if (tabid && this.state.selectedTab !== tabid) + this.setState( { selectedTab: tabid } ); + const itemid = this.props.selectedItem ; + if (itemid && this.state.selectedItem !== itemid) + this.setState( { selectedItem: itemid } ); + } + + // -------------------------------------------------------------------------- + // --- Update + // -------------------------------------------------------------------------- + + handleSelectTab(id) { + this.setState( { selectedTab: id } ); + const settings = this.props.settings ; + const onSelect = this.props.onTabSelection ; + settings && Dome.setWindowSetting( settings + '.dome.tab' , id ); + onSelect && onSelect( id ); + } + + handleSelectItem(id) { + this.setState( { selectedItem: id } ); + const settings = this.props.settings ; + const onSelect = this.props.onItemSelection ; + settings && Dome.setWindowSetting( settings + '.dome.item' , id ); + onSelect && onSelect( id ); + } + + // -------------------------------------------------------------------------- + // --- Rendering + // -------------------------------------------------------------------------- + + render() { + + const content = dispatch( this.props.children , { + tabsItems: 'DOME_TABSBAR_ITEM', + sideItems: 'DOME_SIDEBAR_ITEM', + toolItems: 'DOME_TOOLBAR_ITEM', + others: undefined + }); + + var selection = this.state.selectedTab ; + if (selection === undefined) + React.Children.forEach( content.tabsItems , (tab) => { + if (!selection && tab && tab.props.default) + selection = tab.props.ident ; + }); + + const makeTab = (tab) => { + const onSelection = callbacks( tab.props.onSelection , this.handleSelectTab ); + const onClose = callbacks( tab.props.onClose , this.props.onTabClose ); + const props = { selection , onSelection , onClose , content: false } ; + return React.cloneElement( tab , props , null ); + }; + + const makeContent = (tab) => { + const props = { + selection , + onSelection : undefined, + onClose : undefined, + content: true + }; + return React.cloneElement( tab , props ); + }; + + var tabs , main ; + const settings = this.props.settings ; + const tools = content.toolItems ; + + if (content.tabsItems) { + tabs = React.Children.map( content.tabsItems , (tab) => tab && makeTab(tab) ); + main = React.Children.map( content.tabsItems , (tab) => tab && makeContent(tab) ); + if (content.others) console.warn('Unexpected main content for Frame with Tabs'); + } else { + tabs = undefined ; + main = content.others ; + } + + if (content.sideItems) { + const sidebarOffset = settings && (settings + '.dome.sidebar'); + const sidebarSections = settings && (settings + '.dome.section'); + main = ( + <Splitter dir='LEFT' settings={sidebarOffset} > + { <SideBar + settings={sidebarSections} + selection={this.state.selectedItem} + onSelection={this.handleSelectItem} + >{content.sideItems}</SideBar> } + { main } + </Splitter> + ); + } + + return ( + <Vfill> + { !this.props.hideToolbar && tools && <ToolBar>{tools}</ToolBar> } + { !this.props.hideTabsbar && tabs && <TabsBar>{tabs}</TabsBar> } + { main } + </Vfill> + ); + } + +} + +// -------------------------------------------------------------------------- + +export default { Frame }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/grids.css b/Ivette/src/dome/src/renderer/layout/grids.css new file mode 100644 index 00000000000..25af9503850 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/grids.css @@ -0,0 +1,51 @@ +/* -------------------------------------------------------------------------- */ +/* --- GridLayout Styles --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xGridLayout { + flex: 1 1 auto ; + width: 100% ; + height: 100% ; + position: relative ; + overflow: auto ; +} + +.dome-xGridLayout-splitter { + z-index: 1 ; + position: absolute ; +} + +.dome-xGridLayout-hsplit { cursor: col-resize } +.dome-xGridLayout-hdrag { cursor: ew-resize } +.dome-xGridLayout-vsplit { cursor: row-resize } +.dome-xGridLayout-vdrag { cursor: ns-resize } + +.dome-xGridLayout-target { + z-index: 2 ; + position: absolute ; + border-radius: 12px ; + background: #64b4f0 ; + opacity: 0.5 ; +} + +.dome-xGridLayout-holder { + z-index: -1 ; + position: absolute ; + overflow: hidden ; + background: lightblue ; + opacity: 0.5 ; +} + +.dome-xGridLayout-item { + z-index: 0 ; + position: absolute ; + overflow: hidden ; + transition: all 0.1s ease-out ; +} + +.dome-xGridLayout-item.dome-dragging +{ + z-index: +1 ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/grids.js b/Ivette/src/dome/src/renderer/layout/grids.js new file mode 100644 index 00000000000..91f3882f40f --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/grids.js @@ -0,0 +1,1347 @@ +// -------------------------------------------------------------------------- +// --- Grid Layout +// -------------------------------------------------------------------------- + +/** @module dome/layout/grids */ + +import React from 'react' ; +import Dome from 'dome' ; +import { dispatchEvent, DnD, DragSource, DropTarget } from 'dome/dnd' ; +import { AutoSizer } from 'react-virtualized' ; +import { DraggableCore } from 'react-draggable' ; +import _ from 'lodash' ; +import './grids.css' ; + +// -------------------------------------------------------------------------- +// --- Grid Utilities +// -------------------------------------------------------------------------- + +function flatten( dir, gs ) +{ + const content = [] ; + gs && gs.forEach((g) => { + let kd = g && g.kind ; + if (kd) + if ( kd === dir ) { + if (g.content.length > 0) content.push( ...g.content ); + } else + content.push( g ); + }); + return content ; +} + +function iter( grid , fn ) +{ + function visit(g) { + if (!g) return; + if (g.kind === 'ITEM') fn(g); + else g.content.forEach(visit); + } + visit(grid); +} + +function get( g, id ) +{ + if (g) { + if (g.id === id) return g; + switch( g.kind ) { + case 'HBOX': + case 'VBOX': + const gs = g.content ; + var k = 0; + while (k < gs.length) { + let r = get(gs[k],id); + if (r) return r; + k++; + } + } + } + return undefined; +} + +/** + @summary Pretty-print shape. + */ + +export function stringOfShape( s ) +{ + if (!s) return "<>" ; + switch(s.kind) { + case 'ITEM': + if (s.switch || s.height) + return s.id + "(" + s.width + "x" + s.height + ")" ; + else + return s.id ; + case 'HBOX': return "H<" + s.content.map(stringOfShape).join(',') + ">" ; + case 'VBOX': return "V<" + s.content.map(stringOfShape).join(',') + ">" ; + default: return "<?" + s + "?>"; + } +} + +// -------------------------------------------------------------------------- +// --- Shape Utilities +// -------------------------------------------------------------------------- + +/** + @summary Iterates over items in a shape. + @parameter {Shape} shape - the shape to iter over + @parameter {function} job - the function to apply on each + @description + The iteree receives `job(id,width,height)` for each `ITEM` in the shape. + */ +export function iterShape( shape, job ) +{ + iter( shape , (item) => job(item.id,item.width,item.height) ); +} + +/** + @summary Returns the shape element of the given item identifier. + @parameter {Shape} shape - the shape to look into + @parameter {string} id - the item identifier + @return {object} the associated item object, or `undefined` + */ +export function getShapeItem( shape, id ) +{ + return get(shape,id); +} + +/** + @summary Remove an item or sub-grid from the shape. + @parameter {Shape} shape - the shape to filter + @parameter {string} id - the item or grid identifier to remove + @return {Shape} the filtered shape + */ +export function removeShapeItem( shape, id ) +{ + const visit = (s) => { + if (s && s.id !== id) { + switch(s.kind) { + case 'ITEM': + return s; + case 'HBOX': + case 'VBOX': + return makeShapeBox( s.kind , s.id, s.content.map(visit) ); + //otherwize continue + } + } + return null; + }; + return visit(shape); +} + + +// -------------------------------------------------------------------------- +// --- Dimensions +// -------------------------------------------------------------------------- + +function shareDim( d , ds ) +{ + d.min = 0; + d.size = 0; + d.next = 0; + d.ext = 0; + d.fill = false; + d.resize = false; + ds.forEach( (di) => { + d.min += di.min ; + d.size += di.size ; + if (di.resize) d.resize = true ; + if (di.fill) { + d.fill = true ; + d.ext += di.min ; + d.next ++ ; + } else + d.ext += di.size ; + }); +} + +function stackDim( d , ds ) +{ + d.min = 0; + d.size = 0; + d.fill = 0; + d.resize = 0; + ds.forEach( (di) => { + d.min = Math.max( d.min, di.min ); + d.size = Math.max( d.size, di.size ); + if (di.fill) d.fill = true ; + if (di.resize) d.resize = true ; + }); +} + + +// -------------------------------------------------------------------------- +// --- Sequence Layout +// -------------------------------------------------------------------------- + +/* Distributes extra available space w.r.t respective ratio. */ +function layoutShare( d0 , ds ) +{ + const d = d0.dim ; + const s = d0.size ; + const e = d0.ext ; + const m = d0.min ; + + let flayout ; + + if ( s <= d ) { + const K = d0.next ; + flayout = (di) => + di.fill ? di.size + ( d - s ) / K : di.size ; + } else if ( e <= d ) { + // Have e <= d < s, Hence e < s + const alpha = (d - e) / (s - e) ; + flayout = (di) => + di.fill ? di.min + alpha * (di.size - di.min) : di.size ; + } else if ( m <= d ) { + // Have m <= d < {e,s}, Hence m < e + const alpha = (d - m) / (e - m) ; + flayout = (di) => + !di.fill ? di.min + alpha * (di.size - di.min) : di.min ; + } else if ( m > 0 ) { + const alpha = d / m ; + flayout = (di) => alpha * di.min ; + } else { + flayout = (di) => 0 ; + } + + var p0 = d0.pos ; + var p1 = p0 ; + var ps = 0 ; + ds.forEach((di) => { + ps += di.drag ? di.drag : flayout(di) ; // Avoids cumulative rounding + let p2 = p0 + Math.round(ps) ; + di.pos = p1 ; + di.dim = p2-p1 ; + p1 = p2 ; + }); +} + +// -------------------------------------------------------------------------- +// --- Parallel Layout +// -------------------------------------------------------------------------- + +/* Apply available space to all elements */ + +function layoutStack( d0 , ds ) +{ + const p = d0.pos ; + const d = d0.dim ; + ds.forEach((di) => { + di.pos = p ; + di.dim = di.drag ? di.drag : (di.fill ? d : Math.min( d , di.size )) ; + di.room = d - di.dim ; + }); +} + +// -------------------------------------------------------------------------- +// --- Layout Grid +// -------------------------------------------------------------------------- + +function layoutGrid(grid,width,height) +{ + function visit(g) { + if (!g) return ; + switch( g.kind ) { + case 'ITEM': + break; + case 'HBOX': + layoutShare( g.dx , g.dxs ); + layoutStack( g.dy , g.dys ); + g.content.forEach(visit); + break; + case 'VBOX': + layoutStack( g.dx , g.dxs ); + layoutShare( g.dy , g.dys ); + g.content.forEach(visit); + break; + } + } + grid.dx.pos = 0; grid.dy.pos = 0; + grid.dx.dim = width; grid.dy.dim = height; + visit(grid); +} + +// -------------------------------------------------------------------------- +// --- Freezing +// -------------------------------------------------------------------------- + +function freezeGrid( g ) +{ + if (!g) return; + switch(g.kind) { + case 'ITEM': + g.dx.size = g.dx.dim ; + g.dy.size = g.dy.dim ; + break; + case 'HBOX': + g.content.forEach( freezeGrid ); + shareDim(g.dx,g.dxs); + stackDim(g.dy,g.dys); + break; + case 'VBOX': + g.content.forEach( freezeGrid ); + stackDim(g.dx,g.dxs); + shareDim(g.dy,g.dys); + break; + } +} + +function resizeGrid(g,dgx,dgy) +{ + if (!g) return; + switch(g.kind) { + case 'ITEM': + if (dgx && !g.dx.room) g.dx.drag = dgx ; + if (dgy && !g.dy.room) g.dy.drag = dgy ; + break; + case 'HBOX': + g.content.forEach( (g) => resizeGrid(g,g.dx.drag,dgy) ); + break; + case 'VBOX': + g.content.forEach( (g) => resizeGrid(g,dgx,g.dy.drag) ); + break; + } +} + +// -------------------------------------------------------------------------- +// --- Grid Constructors +// -------------------------------------------------------------------------- + +const BOXID = 'DOME$' ; +const MINDIM = 12 ; +const INSETS = 6 ; // For insertion borders + +function makeGridItem( content, width, height ) +{ + if (content.display !== undefined && !content.display) return undefined ; + const dimension = (d) => Math.max( d || 0 , MINDIM ); + const w = dimension(content.width) ; + const h = dimension(content.height); + const mw = dimension(content.minWidth); + const mh = dimension(content.minHeight); + const dx = { size: Math.max( mw , w ), min: Math.min( mw , w ), resize:false, fill:false }; + const dy = { size: Math.max( mh , h ), min: Math.min( mh , h ), resize:false, fill:false }; + switch( content && content.fill ) { + case 'both': dx.fill = true ; dy.fill = true ; break; + case 'horizontal': dx.fill = true ; break; + case 'vertical': dy.fill = true ; break; + } + switch( content && content.resize ) { + case undefined: dx.resize = dx.fill ; dy.resize = dy.fill; break; + case 'both': dx.resize = true ; dy.resize = true ; break; + case 'horizontal': dx.resize = true ; break; + case 'vertical': dy.resize = true ; break; + } + if (width && dx.resize && dx.min <= width) + dx.size = width ; + if (height && dy.resize && dy.min <= height) + dy.size = height ; + const id = content.id ; + return { kind: 'ITEM', dx, dy, id, content }; +} + +function makeGridHbox( id, gs ) +{ + const content = flatten( 'HBOX' , gs ); + switch(content.length) { + case 0: return null ; + case 1: return content[0]; + default: + const dxs = content.map((g) => g.dx); + const dys = content.map((g) => g.dy); + const dx = {} ; + const dy = {} ; + shareDim(dx,dxs); + stackDim(dy,dys); + return { kind: 'HBOX', id , dx, dxs, dy, dys, content }; + } +} + +function makeGridVbox( id, gs ) +{ + const content = flatten( 'VBOX' , gs ); + switch(content.length) { + case 0: return null ; + case 1: return content[0]; + default: + const dxs = content.map((g) => g.dx); + const dys = content.map((g) => g.dy); + const dx = {} ; + const dy = {} ; + stackDim(dx,dxs); + shareDim(dy,dys); + return { kind: 'VBOX', id, dx, dxs, dy, dys, content }; + } +} + +function makeGridDir( dir, id, gs ) +{ + switch( dir || 'vertical') { + case 'horizontal': + return makeGridHbox(id,gs); + case 'vertical': + return makeGridVbox(id,gs); + default: + return null; + } +} + +function makeShapeDir( dir, id, content ) +{ + switch( dir || 'vertical') { + case 'horizontal': + return makeShapeBox('HBOX',id,content); + case 'vertical': + return makeShapeBox('VBOX',id,content); + default: + return null; + } +} + +// -------------------------------------------------------------------------- +// --- Shapes +// -------------------------------------------------------------------------- + +function makeShapeBox( kind, id, gs ) +{ + const content = flatten( kind, gs ); + switch(content.length) { + case 0: return null ; + case 1: return content[0]; + default: return { kind, id, content }; + } +} + +function makeShapeOfGrid( g ) +{ + let kind = g && g.kind ; + switch( kind ) { + case 'HBOX': + case 'VBOX': + return { kind, id: g.id, content: g.content.map(makeShapeOfGrid) }; + case 'ITEM': + return { kind:'ITEM', id: g.id, width: g.dx.dim, height: g.dy.dim }; + default: + return null; + } +} + +const BOXINSERT = 'DOME$INSERT' ; +let insertId = 0 ; + +function makeShapeInsert( shape,at,dir,item ) +{ + const visit = (s) => { + if (!s || s.id === item.id) return null; + switch( s.kind ) { + case 'HBOX': + case 'VBOX': + s = makeShapeBox( s.kind , s.id, s.content.map(visit) ); + // then falls through + } + if (s.id === at) { + const id = BOXINSERT + (insertId++) ; + switch( dir ) { + case 'NORTH': return makeShapeBox('VBOX', id, [ item , s ]); + case 'SOUTH': return makeShapeBox('VBOX', id, [ s , item ]); + case 'EAST': return makeShapeBox('HBOX', id, [ s , item ]); + case 'WEST': return makeShapeBox('HBOX', id, [ item , s ]); + // otherwize falls through + } + } + return s ; + }; + return at === '*' ? item : at === item.id ? shape : visit(shape); +} + +// -------------------------------------------------------------------------- +// --- Insertions +// -------------------------------------------------------------------------- + +const quadrant = ( dx , dy , x , y ) => { + let dir, best = 10000 ; + const qdir = ( d , w ) => { if (0 <= w && w < best) { best = w ; dir = d; } }; + qdir( 'NORTH', y - dy.pos ); + qdir( 'SOUTH', dy.pos + dy.dim - y ); + qdir( 'EAST', dx.pos + dx.dim - x ); + qdir( 'WEST', x - dx.pos ); + return dir; +}; + +const isHead = (d,p) => ( d.pos <= p && p <= d.pos + INSETS ); +const isTrail = (d,p) => ( d.pos + d.dim - INSETS <= p && p <= d.pos + d.dim ) ; +const inside = (x,y) => (g) => { + const dx = g.dx ; + const dy = g.dy ; + return ( dx.pos < x && x < dx.pos + dx.dim && + dy.pos < y && y < dy.pos + dy.dim ); +} ; + +const targetAt = ( grid , x , y ) => { + if (!grid) return undefined; + const dx = grid.dx ; + const dy = grid.dy ; + let dir ; + switch( grid.kind ) { + case 'ITEM': + dir = quadrant(dx,dy,x,y); + break; + case 'HBOX': + if (isHead(dy,y)) { dir = 'NORTH'; break; } + if (isTrail(dy,y)) { dir = 'SOUTH'; break; } + return targetAt( grid.content.find(inside(x,y)), x , y ); + case 'VBOX': + if (isHead(dx,x)) { dir = 'WEST'; break; } + if (isTrail(dx,x)) { dir = 'EAST'; break; } + return targetAt( grid.content.find(inside(x,y)), x , y ); + } + return dir && Object.assign( { at:grid.id, dir } , makePosition(grid) ) ; +}; + +const TARGET_PLAIN = { at:'*', dir:'*', left:0, top:0 }; + +// -------------------------------------------------------------------------- +// --- Resizing Events +// -------------------------------------------------------------------------- + +const onResizeStart = ({ id,resizer,dp,dq }) => { + dp.root = dp.dim ; + dq.root = dq.dim ; + freezeGrid( resizer.grid ); + resizer.id = id ; + resizer.splitters = [resizer.splitters[id]] ; + resizer.element.setState({ resizer }); +}; + +const onResizeDrag = ({ id,resizer,dp,dq },offset) => { + offset = Math.max( dp.min - dp.root , offset ); + offset = Math.min( dq.root - dq.min , offset ); + resizer.offset = offset ; + dp.drag = dp.root + offset ; + dq.drag = dq.root - offset ; + resizeGrid( resizer.grid ); + resizer.element.forceUpdate(); +}; + +const onResizeStop = ({ resizer }) => { + let shape = makeShapeOfGrid( resizer.grid ); + resizer.element.setShape( shape ); +}; + +const onResizeReset = ({ resizer }) => { + resizer.element.setShape( undefined ); +}; + +// -------------------------------------------------------------------------- +// --- Splitters & Targets +// -------------------------------------------------------------------------- + +const ITEMCLASS = 'dome-xGridLayout-item dome-container' ; +const HDRAGZONE = 'dome-xGridLayout-splitter dome-xGridLayout-hsplit dome-color-dragzone' ; +const HDRAGGING = 'dome-xGridLayout-splitter dome-xGridLayout-hdrag dome-color-dragging' ; +const VDRAGZONE = 'dome-xGridLayout-splitter dome-xGridLayout-vsplit dome-color-dragzone' ; +const VDRAGGING = 'dome-xGridLayout-splitter dome-xGridLayout-vdrag dome-color-dragging' ; + +class HSPLIT extends React.Component { + render() { + let {x,y,width,height,...handler} = this.props ; + let id = handler.id ; + let { id:sid , offset=0 } = handler.resizer ; + return ( + <DraggableCore + onStart={() => { + onResizeStart(handler); + this.forceUpdate(); + }} + onDrag={(_evt,data) => { + onResizeDrag(handler,data.x - x + 2); + this.forceUpdate(); + }} + onStop={() => onResizeStop(handler)} + > + <div className={ id === sid ? HDRAGGING : HDRAGZONE } + onClick={(evt) => evt.altKey && onResizeReset(handler)} + style={{ top:y, height, left:x+offset-2, width:4 }} /> + </DraggableCore> + ); + } +} + +class VSPLIT extends React.Component { + render() { + let {x,y,width,height,...handler} = this.props ; + let id = handler.id ; + let { id:sid , offset=0 } = handler.resizer ; + return ( + <DraggableCore + onStart={() => { + onResizeStart(handler); + this.forceUpdate(); + }} + onDrag={(_evt,data) => { + onResizeDrag(handler,data.y - y + 2); + this.forceUpdate(); + }} + onStop={() => onResizeStop(handler)} + > + <div className={ id === sid ? VDRAGGING : VDRAGZONE } + onDoubleClick={(evt) => evt.altKey && onResizeReset(handler)} + style={{ top:y+offset-2, height:4, left:x, width }} /> + </DraggableCore> + ); + } +} + +const TARGET = ({target:{ dir,left,top,width,height }}) => { + switch(dir) { + case 'NORTH': + top = top - 3 ; height = 6 ; + break; + case 'SOUTH': + top = top + height - 3 ; height = 6 ; + break; + case 'WEST': + left = left -3 ; width = 6 ; + break; + case 'EAST': + left = left + width -3 ; width = 6 ; + break; + } + let style = { left, top, width, height }; + return <div className='dome-xGridLayout-target' style={style} />; +}; + +const HOLDER = ({position}) => ( + <div className='dome-xGridLayout-holder' style={position} /> +); + +const ELEMENT = ({id,className,style,children}) => ( + <div key={id} className={className} style={style}> + { children } + </div> +); + +// -------------------------------------------------------------------------- +// --- Grid Splitters +// -------------------------------------------------------------------------- + +function splitSequence( d,ds,fn ) +{ + const n = ds.length || 0 ; + if (n<=0) return; + const dt = ds[n-1] ; + const dn = { resize:false, dim:0, min:0 }; + const trail = d.room ; + if (trail > 0) { + dn.resize = true; dn.dim = trail; + let i,p,di ; + for (i = 0, p = -1; i < n; i++) { + di = ds[i]; + p = di.resize ? i : p ; + if (p>=0) { + fn(di.pos+di.dim,ds[p],dn); + } + } + } else { + const dr = ds.slice(1).concat(dn); + const ps = Array(n); + const qs = Array(n); + let i,k ; + for (i = 0, k = -1; i < n; i++) + k = ps[i] = ds[i].resize ? i : k ; + for (i = n-1, k = -1; 0 <= i; i--) + k = qs[i] = dr[i].resize ? i : k ; + ds.forEach((di,i) => { + var p = ps[i]; + var q = qs[i]; + if (p>=0 && q>=0) + fn(di.pos+di.dim,ds[p],dr[q]); + }); + } +} + +function extendItem( d , fn ) { + if (d.resize && d.room > 0) { + const df = { resize:true, dim:d.room, min:0 }; + fn(d.pos + d.dim,d,df); + } +}; + +function splitGrid( resizer,grid ) +{ + var SID = 0 ; + const splitters = resizer.splitters ; + const makeHsplit = (dy) => (x,dp,dq) => { + var id = SID++; + var s = ( + <HSPLIT id={id} key={id} resizer={resizer} + x={x} y={dy.pos} height={dy.dim} + dp={dp} dq={dq} + />) ; + splitters.push(s); + }; + const makeVsplit = (dx) => (y,dp,dq) => { + var id = SID++; + var s = ( + <VSPLIT id={id} key={id} resizer={resizer} + x={dx.pos} y={y} width={dx.dim} + dp={dp} dq={dq} + />) ; + splitters.push(s); + }; + function visit(g) { + if (!g) return; + switch(g.kind) { + case 'ITEM': + extendItem( g.dx , makeHsplit(g.dy) ); + extendItem( g.dy , makeVsplit(g.dx) ); + return; + case 'HBOX': + splitSequence( g.dx , g.dxs , makeHsplit(g.dy) ); + g.content.forEach(visit); + return; + case 'VBOX': + splitSequence( g.dy , g.dys , makeVsplit(g.dx) ); + g.content.forEach(visit); + return; + } + } + visit(grid); +} + +// -------------------------------------------------------------------------- +// --- Grid Elements +// -------------------------------------------------------------------------- + +const makePosition = ( {dx,dy}, padding=0 ) => ({ + left: dx.pos + padding, + top: dy.pos + padding, + width: dx.dim - padding, + height: dy.dim - padding +}); + +function makeElement( render = ELEMENT, item, padding ) +{ + if (!item) return null; + const { id, content:{className:itemClass,style:itemStyle,children,...itemProps} } = item; + const position = makePosition( item, padding ); + const className = itemClass ? ITEMCLASS + " " + itemClass : ITEMCLASS ; + const style = Object.assign( {}, itemStyle , position ); + return render({id,className,style,children,...itemProps}); +} + +function orderElements( e1 , e2 ) +{ + let a = e1.key ; + let b = e2.key ; + if (!a || a < b) return -1; + if (!b || a > b) return 1; + return 0; +} + +// -------------------------------------------------------------------------- +// --- GridItem +// -------------------------------------------------------------------------- + +/** + @class + @summary Elementary GridLayout Component + @property {string} id - Component identifier + @property {boolean} display - Whether to mount the component + @property {number} width - Desired component width + @property {number} height - Desired component height + @property {number} minWidth - Minimum component width + @property {number} minHeight - Minium component height + @property {directions} [fill] - Direction(s) the component fills in + @property {directions} [resize] - Direction(s) the component can be resized in + @property {directions} [shrink] - Direction(s) the component can be shrinked in + @property {string} [className] - Additional class of the component + @property {string} [handle] - class name of the handler for dragging the component + @property {object} [style] - Additional style of the component + @property {React.children} children - grid item content + @description + + The `id` property is mandatory for the GridLayout container + to property manage its different components. All items in the same GridLayout shall + have distinct identifiers. + + Direction properties (with type `directions`) can take the following values: + `'none'`, `'horizontal'`, `'vertical'` or `'both'`. + */ +export const GridItem = () => null; + +// -------------------------------------------------------------------------- +// --- Grid H/V Boxes +// -------------------------------------------------------------------------- + +/** + @class + @property {ident} [id] - the box identifier + @property {direction} dir - either `'horizontal'` or `'vertical'` + @property {GridContent} [children] - internal grid contents + @summary Layout its content in an horizontal or vertical box. + @description + +This container is a _fake_ component thats simply groups several +`GridItem`s or `GridBox`es horizontally or vertically. + +It can be used only as direct children of `GridLayout` +and other `GridBox` containers. + +See also: + - [GridLayout](module-dome_layout_grids.GridLayout.html) top-level container + - [GridItem](module-dome_layout_grids.GridItem.html) elementary component + - [GridHbox](module-dome_layout_grids.GridHbox.html) horizontal box + - [GridVbox](module-dome_layout_grids.GridVbox.html) vertical box +*/ +export const GridBox = () => null ; + +/** + @class + @summary Layout its content in an horizontal box. + @property {ident} [id] - the box identifier + @description + See [GridBox](module-dome_layout_grids.GridBox.html) +*/ +export const GridHbox = () => null ; + +/** + @class + @summary Layout its content in a vertical box. + @property {ident} [id] - the box identifier + @description + See [GridBox](module-dome_layout_grids.GridBox.html) +*/ +export const GridVbox = () => null ; + +// -------------------------------------------------------------------------- +// --- User Grid & Components Extraction +// -------------------------------------------------------------------------- + +import { register, classOf } from 'dome/misc/register' ; + +register(GridBox, 'DOME_GRIDLAYOUT_BOX'); +register(GridHbox, 'DOME_GRIDLAYOUT_HBOX'); +register(GridVbox, 'DOME_GRIDLAYOUT_VBOX'); +register(GridItem, 'DOME_GRIDLAYOUT_ITEM'); + +/** + @summary Extract shape from GridChildren. + @parameter {GridChildren} children - Grid items elements arranged in grids + @parameter {direction} [dir] - default direction + @return {Shape} the associated shape + @description + Converts a React JSX-based grid of items into a Shape object. + */ +export function makeChildrenShape( children, dir ) +{ + const makeEltShape = (elt) => { + let { id, width, height } = elt.props ; + return { kind: 'ITEM', id, width, height }; + }; + + const makeBoxShape = (dir,elt) => { + let { id, children } = elt.props ; + let gs = makeShapes(children); + return makeShapeDir(dir,id,gs); + }; + + const makeShapes = (children) => { + return React.Children.map(children,(elt) => { + if (!elt) return null; + switch( classOf(elt) ) { + case 'DOME_GRIDLAYOUT_ITEM': + return makeEltShape(elt); + case 'DOME_GRIDLAYOUT_HBOX': + return makeBoxShape('horizontal',elt); + case 'DOME_GRIDLAYOUT_VBOX': + return makeBoxShape('vertical',elt); + case 'DOME_GRIDLAYOUT_BOX': + return makeBoxShape(elt.props.dir,elt); + default: + console.warn('[Dome.GridLayout] Unknown grid box', elt); + return null; + } + }); + }; + + return makeShapeDir( dir, undefined, makeShapes(children) ); +} + +function makeChildrenGrid( dir, items, children, shape ) +{ + let kid = 0 ; + let index = {} ; + + const indexElt = (elt) => { + let { id } = elt.props ; + let props = index[id]; + if (!props) props = index[id] = {}; + Object.assign( props , elt.props ); + return props; + }; + + const makeGridElt = (elt) => makeGridItem(indexElt(elt)); + + const makeGridBox = (dir,elt) => { + let { id, children } = elt.props ; + if (!id) id = BOXID + (++kid) ; + return makeGridDir(dir,id,makeGrids(children)); + }; + + const makeGrids = (children) => { + return React.Children.map(children,(elt) => { + if (!elt) return null; + switch( classOf(elt) ) { + case 'DOME_GRIDLAYOUT_ITEM': + return makeGridElt(elt); + case 'DOME_GRIDLAYOUT_HBOX': + return makeGridBox('horizontal',elt); + case 'DOME_GRIDLAYOUT_VBOX': + return makeGridBox('vertical',elt); + case 'DOME_GRIDLAYOUT_BOX': + return makeGridBox(elt.props.dir,elt); + default: + console.warn('[Dome.GridLayout] Unknown grid box', elt); + return null; + } + }); + }; + + const makeShape = (s) => { + switch( s && s.kind ) { + case 'ITEM': + let props = index[ s.id ] ; + if (!props) return null; + index[ s.id ] = undefined ; + return makeGridItem( props, s.width, s.height ); + case 'HBOX': + return makeGridHbox( s.id, s.content.map(makeShape) ); + case 'VBOX': + return makeGridVbox( s.id, s.content.map(makeShape) ); + default: + return null; + } + }; + + items && items.forEach && items.forEach( indexElt ); + + if (shape) + return makeShape(shape); + else + return makeGridDir(dir,BOXID,makeGrids(children)); +} + +// -------------------------------------------------------------------------- +// --- GridLayout Core +// -------------------------------------------------------------------------- + +/** + @class + @summary Grid-based Flexible Container + @property {direction} [dir] - Default children layout (`'horizontal'` or `'vertical'`) + @property {number} [padding] - Padding between items + @property {Shape} [shape] - The desired shape (defaults to children grid) + @property {GridItem[]} [items] - A collection of items (defaults to children items) + @property {GridContent} [children] - Grid items arranged in box (used for default items and shape) + @property {ident} [dragged] - Dragged item to materialize + @property {object} [dragging] - Dragging event to localize with `onTarget()` + @property {object} [target] - Insertion target to materialze + @property {function} [onReshape] - Callback with the updated shape + @property {function} [onTarget] - Callback when dragging is a valid target + @property {function} [render] - Rendering function for items + @property {React.ref} [targetRef] - Reference for D&D drop target + @description + +Low-level GridLayout container, with only resizing capabilities. +Additional rendering options are available: + +- `dragged` : item being dragged, materialized with a dragging background; +- `dragging` : current [D&D](dome-module_dnd.html) event to notify `onTarget()` with; +- `target` : `{at,dir,left,top,width,height}` insertion position to materialize; +- `shape:Shape` : desired reshaping of the children grid; +- `onReshape(Shape)` : notified when grid content has been resized; +- `onTarget(Target)` : notified when `dragging` corresponds to a new target; +- `render({id,className,style,handle,children,...})` : rendering function for the provided item. + +The rendering function shall return a keyed React element or fragment. +It receives all properties of the associated item to render, with +class and style merged with the `dome-xGridLayout-item` base class +and the absolute coordinates of the item inside the container. + +*/ + +export class GridLayoutCore extends React.Component +{ + + constructor(props) { + super(props); + this.state = {}; + } + + setShape( newshape ) + { + const { onReshape, shape } = this.props ; + onReshape && onReshape(newshape); + this.setState({ resizer:undefined }); + } + + render() { + const { targetRef, padding=0 } = this.props ; + return ( + <div className='dome-xGridLayout' ref={targetRef}> + <AutoSizer key='grid'>{({width,height}) => this.renderSized(width-padding,height-padding)}</AutoSizer> + </div> + ); + } + + renderSized(width, height) + { + const { dragged } = this.props ; + const { resizer:resizing } = this.state ; + let grid,markers=[] ; + if (resizing) { + // When Resizing + grid = resizing.grid ; + markers = resizing.splitters ; + layoutGrid(grid,width,height); + } else { + const { + shape, dir, + dragging, onTarget, + items, children + } = this.props ; + // Compute Layout + grid = makeChildrenGrid( dir, items, children, shape ); + if (grid) layoutGrid(grid,width,height); + // Compute Dragging & notify Target + let targetted ; + if (dragging) { + if (grid) { + const r = dragging.targetClientRect ; + if (r) { + const x = dragging.clientX - r.left ; + const y = dragging.clientY - r.top ; + targetted = targetAt( grid, x, y ); + } + } else { + targetted = Object.assign( { width, height } , TARGET_PLAIN ) ; + } + } + if (onTarget) { + const { at,dir } = targetted || {} ; + const held = dragging ? dragging.held : false ; + if ( this.targetAt !== at || + this.targetDir !== dir || + this.targetHeld !== held ) + { + this.targetAt = at ; + this.targetDir = dir ; + this.targetHeld = held ; + if (targetted) targetted.shape = makeShapeOfGrid(grid); + setImmediate(() => onTarget(targetted)); + } + } + const { target } = this.props ; + if (target && target.at !== dragged) { + markers.push( <TARGET key='target' target={target}/> ); + } + if (grid && !dragging && !target) { + // Splitters + splitGrid( { grid,element:this,splitters:markers } ,grid ); + } + } + const elements = []; + const { render, padding } = this.props ; + iter(grid,(item) => { + let e = makeElement(render,item,padding); + if (e) elements.push(e); + if (dragged && dragged === item.id) + markers.push(<HOLDER key='holder' position={makePosition(item)}/>); + }); + return [ + (<React.Fragment key='items'>{elements.sort(orderElements)}</React.Fragment>), + (<React.Fragment key='markers'>{markers}</React.Fragment>) + ]; + }; +} + +// -------------------------------------------------------------------------- +// --- GridLayout Full +// -------------------------------------------------------------------------- + +const positionOfStyle = ({left,top,width,height}) => ({left,top,width,height}); + +const DRAGGABLEITEM = + (dnd,anchor,onSelfDrag,insert) => + ({id,className,style,handle,children}) => + ( id === insert + ? ( <HOLDER key='DOME$holder' position={positionOfStyle(style)}/> ) + : ( + <DragSource + key={id} + dnd={dnd} + handle={handle} + onStart={() => onSelfDrag(id,{x:style.left,y:style.top})} + > + {(dragging) => { + let theStyle = style ; + if (dragging && anchor) { + theStyle = Object.assign( {} , style ); + theStyle.left = anchor.x + dragging.deltaX ; + theStyle.top = anchor.y + dragging.deltaY ; + className += ' dome-dragging' ; + } + return (<div className={className} style={theStyle}>{children}</div>); + }} + </DragSource> + ) + ); + +/** + @class + @summary Grid Container + @property {direction} [dir] - Default children layout (`'horizontal'` or `'vertical'`) + @property {number} [padding] - Padding between items + @property {Shape} [shape] - The desired shape (defaults to children grid) + @property {GridItem[]} [items] - A collection of items (defaults to children items) + @property {Grid} [children] - Grid items arranged in box (used for default items and shape) + @property {string} [settings] - User-settings key for making the shape persistent + @property {DnD} [dnd] - Optional D&D controller to be used + @property {GridItem} [holding] - Dragged external element + @property {function} [onTarget] - Callback for dragged target proposal + @property {function} [onReshape] - Callback on reshaping self content + @property {function} [onInsert] - Callback on dropping the holding element + @property {function} [onDnd] - Callback on D&D events + @property {function} [onXxx] - Other D&D [callback events](module-dome_dnd.html) + @description + +Layout several components with nested vertical and horizontal boxes. + +Direct children of the container must be either: +- [GridBox](module-dome_layout_grids.GridBox.html) and its derivated +- [GridItem](module-dome_layout_grids.GridItem.html) for elementary component + +Top-level children are laidout vertically (default) or horizontally according +to the `dir` property. Nested boxes of same directions are flattened, +and singleton boxes simply lift-up their content into their parent box. + +You may dynamically change the box hierarchy, without causing unmounting +and re-monting the different items. Actually, the container renders all +the collected `GridItem` elements as a flat array ordered by keys. + +All item specifications are taken from the provided items. However, the grid +layout of the items is taken from the provided shape, the settings of the +children grix boxes, in this order of priority. Extra items or missing items are +simply ignored from the shape taken into account. + +GridLayout containers can be used as drop targets, both for re-arranging +internal grid items, or to insert external drag sources inside. +If you supply an external [DnD](module-dome_dnd.DnD.html) controller, +the GridLayout will register itself as a drop target. Otherwize, it will +use its own controller. + +The callbacks `onReshape` and `onTarget` are invoked on drag and drop operations: +- `onReshape(Shape)` is invoked when the grid elements are resized or rearranged; +- `onTarget(Target)` in invoked when a drag source targets an element of the grid; +- `onInsert(Shape,Target)` when a drag source is dropped inside the grid, at some +target position, possibly resulting in the given new shape. + +When dragging a source over the grid, the grid element specified by the `holding` +property of the grid is used to materialize the insertion of the dragged source +inside the grid. To decline a dragging operation, the `onTarget()` must return a +falsy value other than `undefined` (eg: `false`). + +A `Target` is a plain serialisable object with the following properties: +- `at:ident` the box or item identifier where to insert the target, +or `'*'` when targetting an empty shape; +- `dir:'NORTH'|'EAST'|'SOUTH'|'WEST'` the direction to insert the target item along, +or `'*'` when targetting an empty shape; +- `id:ident` the inserted item identifier. + +A `Shape` is a plain serializable object with the following properties: +- `{ kind:'HBOX', id, content: [Shape,…] }` for horizontal boxes, +- `{ kind:'VBOX', id, content: [Shape,…] }` for vertical boxes, +- `{ kind:'ITEM', id, height, width }` for leaf items. + +*/ +export class GridLayout extends React.Component +{ + + constructor(props) { + super(props); + this.state = {}; + this.dnd = this.props.dnd || new DnD(); + this.onReloadSettings = this.onReloadSettings.bind(this); + this.onReshape = this.onReshape.bind(this); + this.onTarget = this.onTarget.bind(this); + this.onSelfDrag = this.onSelfDrag.bind(this); + this.onDnd = this.onDnd.bind(this); + this.container = React.createRef(); + } + + componentDidMount() { + Dome.on('dome.defaults',this.onReloadSettings); + } + + componentWillUnmont() { + Dome.off('dome.defaults',this.onReloadSettings); + } + + computeTargetProposal(target) { + if (!target) return undefined; + const { at,dir } = target ; + const { dragged } = this.state ; + if (dragged) + return at === dragged ? undefined : { id:dragged,at,dir }; + else { + const { holding } = this.props ; + const id = holding && holding.props && holding.props.id ; + return at === id ? undefined : { id,at,dir }; + } + } + + computeNewShapeForTarget(target) { + if (!target) return []; + const { shape,at,dir } = target ; + const { holding } = this.props ; + const { dragged,inserted:oldInsert } = this.state ; + let item,inserted,newShape ; + if (dragged) { + item = get(shape,dragged); + newShape = makeShapeInsert( shape, at, dir, item ); + } + else if (holding && holding.props) { + const { id,width,height } = holding.props ; + if (at === id) { + inserted = oldInsert ; + newShape = shape ; + } else { + inserted = { at,dir,id } ; + item = { kind:'ITEM',id,width,height }; + newShape = makeShapeInsert( shape,at,dir,item ); + } + } + return [inserted,newShape]; + } + + onReloadSettings() { + const { settings, onReshape } = this.props ; + if (!settings) return; + const newShape = Dome.getWindowSetting( settings ); + this.setState({ shape: newShape }); + if (onReshape) onReshape( newShape ); + } + + onReshape(newShape) { + const { settings, shape:setShape, onReshape } = this.props ; + if (!setShape) this.setState({ shape: newShape }); + if (settings) Dome.setWindowSetting( settings, newShape ); + if (onReshape) onReshape( newShape ); + } + + onTarget(newTarget) { + const proposal = this.computeTargetProposal(newTarget); + if (!proposal) this.setState({target:undefined}); + else { + const { onTarget } = this.props ; + const { held } = this.state ; + const approval = onTarget && onTarget(proposal) ; + const valid = approval === undefined || approval ; + if (valid) { + if ( held ) { + const [inserted,holdedShape] = this.computeNewShapeForTarget(newTarget); + this.setState({held:false,target:undefined,inserted,holdedShape}); + } else + this.setState({target: newTarget}); + } else + this.setState({target: undefined}); + }; + } + + // Self dragged callback, see DRAGGABLEITEM + onSelfDrag(dragged,anchor) { + this.setState({ dragged, anchor }); + } + + // Generic D&D event + onDnd(dragging) { + dispatchEvent(dragging,this.props); + switch( dragging && dragging.move ) { + case 'HOLD': this.setState({held: true}); break; + case 'MOVE': this.setState({held: false}); break; + case 'DROP': + let { target, inserted, holdedShape:shape } = this.state ; + if (target) + [inserted,shape] = this.computeNewShapeForTarget(target); + if (inserted) { + const { onInsert } = this.props ; + const callback = onInsert || this.onReshape ; + callback && callback(shape,inserted); + } else { + shape && this.onReshape(shape); + } + // Continue on 'STOP' + case 'STOP': + this.setState({ + dragged: undefined, + anchor: undefined, + target: undefined, + held: undefined, + inserted: undefined, + holdedShape: undefined + }); + break; + } + } + + render() { + const { shape:setShape, dir, items, children, holding, padding, settings } = this.props ; + const { shape:newShape, target, dragged, anchor, holdedShape, inserted } = this.state ; + const insert = inserted ? inserted.id : undefined ; + const render = DRAGGABLEITEM(this.dnd,anchor,this.onSelfDrag,insert); + const shape = holdedShape || setShape || newShape || Dome.getWindowSetting(settings) ; + return ( + <DropTarget + dnd={this.dnd} + targetRef={this.container} + onDnd={this.onDnd} + > + {(dragging) => ( + <GridLayoutCore + targetRef={this.container} + dir={dir} + padding={padding} + shape={shape} + items={items} + dragging={dragging} + onReshape={this.onReshape} + onTarget={this.onTarget} + dragged={dragged} + target={target} + render={render} + > + {children} + {inserted ? holding : null} + </GridLayoutCore> + )} + </DropTarget> + ); + } +} + +// -------------------------------------------------------------------------- +// --- Defaults +// -------------------------------------------------------------------------- + +export default { + GridLayout, + GridLayoutCore, + GridItem, GridBox, GridHbox, GridVbox, + iterShape, getShapeItem, removeShapeItem, + stringOfShape, + makeChildrenShape +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/pages.css b/Ivette/src/dome/src/renderer/layout/pages.css new file mode 100644 index 00000000000..6d593e550c7 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/pages.css @@ -0,0 +1,81 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling Page --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xPages-note { + background: white ; + padding: 2px ; +} + +.dome-xPages-page { + flex: 1 1 auto ; + overflow: hidden ; +} + +.dome-xPages-sheet { + position: relative ; + width: calc(100% - 16px) ; + height: calc(100% - 16px) ; + margin: 8px ; + padding: 8px ; + background: white ; + border-radius: 2px ; + box-shadow: 2px 2px 6px 3px lightgray ; + overflow: auto ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Content --- */ +/* -------------------------------------------------------------------------- */ + +.dome-pages * { + user-select: text ; +} + +.dome-pages h1:first-child { + margin-top: 0px ; +} + +.dome-pages h1 { + margin-top: 24px ; + margin-bottom: 5px ; +} + +.dome-pages h2 { + margin-top: 16px ; + margin-bottom: 5px ; +} + +.dome-pages h3 { + margin-top: 10px ; + margin-bottom: 5px ; +} + +.dome-pages h4 { + margin-top: 6px ; + margin-bottom: 3px ; +} + +.dome-pages h5 { + margin-top: 3px ; + margin-bottom: 3px ; +} + +.dome-pages p +{ + margin-top: 3px ; + margin-bottom: 3px ; +} + +.dome-pages ul +{ + padding-left: 6px ; + margin-left: 16px ; +} + +.dome-pages li +{ + +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/pages.js b/Ivette/src/dome/src/renderer/layout/pages.js new file mode 100644 index 00000000000..bd7b1b6113c --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/pages.js @@ -0,0 +1,81 @@ +// -------------------------------------------------------------------------- +// --- Text Pages +// -------------------------------------------------------------------------- + +/** + @module dome/layout/pages + @description + A collection of text area and elements do render textual content. + + Inside such areas, all elements are styled like a classical web page. + All elements are encapsulated inside a `<div>` with `'dome-pages'` + class name, which can be used in your CSS selectors. + + All the textual parts are selectable inside the page, contrarily to + most other widget components. + + The behaviour of `<a href=...>` elements differs for local links and external URLs. + Local links trigger a ['dome.href'](dome_.html#~event:'dome.href') event, that + you can listen to from the originating renderer process, _eg. by using `Dome.useUpdate()` + custom hook. + + External links launch the user's default browser. + +*/ + +import React from 'react' ; +import { AutoSizer } from 'react-virtualized' ; +import './pages.css' ; + +// -------------------------------------------------------------------------- +// --- Page +// -------------------------------------------------------------------------- + +/** + @class + @property {object} [style] - additional style elements + @property {Elements} [children] - page content + @summary a blank HTML page + @description + + The page has insets and shadows and fills the entire available area. + Large content is crolled inside in both directions. +*/ + +export const Page = ({style,children}) => { + return ( + <div className='dome-xPages-page'> + <div className='dome-xPages-sheet dome-pages'> + {children} + </div> + </div> + ); +}; + +// -------------------------------------------------------------------------- +// --- Page +// -------------------------------------------------------------------------- + +/** + @class + @property {object} [style] - additional style elements + @property {Elements} [children] - page content + @summary a blank HTML textarea + @description + + The area has small padding and no margin, and does not scroll its content. +*/ + +export const Note = ({style,children}) => ( + <div className=' dome-xPages-note dome-pages' style={style}> + {children} + </div> +); + +// -------------------------------------------------------------------------- +// Export Default +// -------------------------------------------------------------------------- + +export default { Page, Note }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/sidebars.css b/Ivette/src/dome/src/renderer/layout/sidebars.css new file mode 100644 index 00000000000..ca419311215 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/sidebars.css @@ -0,0 +1,107 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling SideBars --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xSideBar { + width: 100% ; + height: 100% ; + overflow-x: hidden ; + overflow-y: auto ; + padding-top: 6px ; + padding-bottom: 6px ; +} + +.dome-window-active .dome-xSideBar.dome-color-frame { + background: #e3e8ec ; +} + +/* -------------------------------------------------------------------------- */ +/* --- SideBar Section --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xSideBarSection { + display: block ; + margin-top: 10px ; + margin-bottom: 10px ; +} + +.dome-xSideBarSection-title { + padding-left: 3px ; + padding-right: 2px ; + display: flex ; + flew-flow: row nowrap ; + align-items: center ; +} + +.dome-xSideBarSection-title > .dome-xLabel { + flex: 1 1 ; + overflow: hidden ; + text-overflow: ellipsis ; + font-weight: bold ; +} + +.dome-xSideBarSection-title > .dome-xBadge { + flex: 0 0 ; +} + +.dome-xSideBarSection-hideshow { + flex: 0 0 ; + margin: 1px ; + color: #aaa ; + width: 32px ; + font-weight: normal ; + display: inline ; + visibility: hidden ; +} + +.dome-xSideBarSection-title:hover .dome-xSideBarSection-hideshow { + visibility: visible ; +} + +.dome-xSideBarSection-content { + overflow: hidden ; + transition: max-height 250ms ease-in-out ; +} + + +/* -------------------------------------------------------------------------- */ +/* --- SideBar Items --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xSideBarItem { + padding-left: 2px ; + padding-right: 2px ; + display: flex ; + flex-flow: row nowrap ; + align-items: center ; +} + +.dome-window-active .dome-xSideBarItem.dome-active { + background: #ccc ; +} + +.dome-window-inactive .dome-xSideBarItem.dome-active { + background: #ddd ; +} + +.dome-xSideBarItem > .dome-xLabel { + flex: 1 1 ; + overflow: hidden ; + text-overflow: ellipsis ; + padding-left: 12px ; +} + +.dome-xSideBarItem.dome-disabled > .dome-xLabel { + color: #b0b0b0 ; + fill: #b0b0b0 ; +} + +.dome-xSideBarItem > .dome-xLabel:last-child { + margin-right: 20px ; +} + +.dome-xSideBarItem > .dome-xBadge { + flex: 0 0 ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/sidebars.js b/Ivette/src/dome/src/renderer/layout/sidebars.js new file mode 100644 index 00000000000..39f691c478a --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/sidebars.js @@ -0,0 +1,216 @@ +// -------------------------------------------------------------------------- +// --- SideBars +// -------------------------------------------------------------------------- + +/** @module dome/layout/sidebars */ + +import React from 'react' ; +import Dome from 'dome' ; +import { Badge } from 'dome/controls/icons' ; +import { Label } from 'dome/controls/labels' ; +import './sidebars.css' ; + +const SideBarContext = React.createContext(); + +// -------------------------------------------------------------------------- +// --- SideBar Container +// -------------------------------------------------------------------------- + +/** + @class + @summary Container for sidebar items + @property {Elements} [children] - Side bar items + @property {string} [settings] - Side bar items settings + @property {string} [selection] - Current item selection + @property {function} [onSelection] - Selection callback + @property {function} [onContextMenu] - Context Menu callback + @description + See also [Frame](module-dome_layout_frames.Frame.html) containers. + + When a base settings is set on the sidebar, all contained + sections and items are attributed derived settings based on their identifiers. + + The global selection state and callback are also propagated to the side bar items. + */ +export const SideBar = ({ children , ...props }) => ( + <div className="dome-xSideBar dome-color-frame"> + <SideBarContext.Provider value={props}> + {children} + </SideBarContext.Provider> + </div> +); + +const makeSettings = ( globalSettings, { settings, label, id } ) => { + if (settings) return settings ; + if (globalSettings) { + let localId = id || label ; + if (localId) + return globalSettings + '.' + localId ; + } + return undefined ; +}; + +// -------------------------------------------------------------------------- +// --- Badges Specifications +// -------------------------------------------------------------------------- + +const makeBadge = ((element) => { + switch(typeof(element)) { + case 'number': + case 'string': + return <Badge value={element}/>; + default: + return element ; + } +}); + +// -------------------------------------------------------------------------- +// --- SideBar Section Hide/Show Button +// -------------------------------------------------------------------------- + +const HideShow = (props) => ( + <label className='dome-xSideBarSection-hideshow dome-text-label' + onClick={props.onClick} > + {props.visible ? 'Hide' : 'Show'} + </label> +); + +// -------------------------------------------------------------------------- +// --- SideBar Section +// -------------------------------------------------------------------------- + +const disableAll = (children) => + React.Children.map( children , (elt) => React.cloneElement( elt , { disabled: true } ) ); + +/** + @class + @summary Sidebar Section. + @property {string} [id] - Section identifier (used for derived settings) + @property {string} label - **Section label** + @property {string} [title] - Section short description (label tooltip) + @property {boolean} [enabled] - Enabled section (by default) + @property {boolean} [disabled] - Disabled section (not by default) + @property {boolean} [unfold] - Fold/unfold local state (default to local state) + @property {string} [settings] - Fold/unfold window settings (local state) + @property {boolean} [defaultUnfold] - Fold/unfold default state (default is `true`) + @property {Badge} [summary] - Badge summary (when content is hidden) + @property {Item[]} children - Content items + @description + + Unless specified, sections can be hidden on click. When items in the section have badge(s) + it is highly recommended to provide a badge summary to be displayed + when the content is hidden. + + Sections with no items are not displayed. +*/ +export function Section(props) { + + const context = React.useContext( SideBarContext ); + const [ state=true, setState ] = Dome.useState( + makeSettings(context,props), + props.defaultUnfold + ); + const { enabled=true, disabled=false, unfold, children } = props ; + + if (React.Children.count(children) == 0) return null; + + const dimmed = context.disabled || disabled || !enabled ; + const foldable = unfold === undefined ; + const visible = foldable ? state : unfold ; + const onClick = foldable ? (() => setState(!state)) : undefined ; + const maxHeight = visible ? 2000 : 0 ; + const subContext = Object.assign( {}, context, { disabled: dimmed } ); + + return ( + <div className='dome-xSideBarSection'> + <div className='dome-xSideBarSection-title' title={props.label}> + <Label className={ dimmed ? 'dome-disabled' : '' } label={props.label} /> + {!visible && React.Children.map(props.summary,makeBadge)} + {foldable && <HideShow visible={visible} onClick={onClick}/>} + </div> + <div className='dome-xSideBarSection-content' style={{ maxHeight }}> + <SideBarContext.Provider value={subContext}> + {children} + </SideBarContext.Provider> + </div> + </div> + ); +} + +// -------------------------------------------------------------------------- +// --- SideBar Items +// -------------------------------------------------------------------------- + +/** + @class + @property {string} [id] - Item identifier + @property {string} [label] - **Item label** + @property {string} [icon] - Item icon + @property {string} [title] - Item tooltip + @property {boolean} [enabled] - Enabled item (default is `true`) + @property {boolean} [disabled] - Disabled item (default is `false`) + @property {boolean} [selected] - Item selection state (default is `SideBar` selection) + @property {function} [onSelection] - Selection callback + @property {function} [onContextMenu] - Context Menu callback + @property {Badge} [badge] - Badge element(s) + @property {React.Children} [children] - Item additional content + @summary Sidebar Section Items + @description + + The item will be highlighted if selected _via_ the `selection` property of the + englobing sidebar. The `onSelection` and `onContextMenu` callbacks are invoked with the item identifier. + Context menu callback also triggers the selection callback (first). + In case callbacks are defined from the englobing sidebar, both are invoked. + + Badges can be single or multiple [Badge](module-dome_controls_icons.Badge.html) values. + They are displayed stacked on the right edge of the item. + +**/ +export function Item(props) +{ + const { selection, + disabled: disabledSection, + onSelection: ctxtOnSelect, + onContextMenu: ctxtOnPopup + } = React.useContext(SideBarContext); + const { id, selected, + disabled=false, enabled=true, + onSelection:itemOnSelect, + onContextMenu:itemOnPopup + } = props ; + const isDisabled = disabled || !enabled || disabled ; + const isSelected = selected !== undefined ? selected : (selection && id && (selection === id)) ; + const onClick = isDisabled ? undefined : () => { + itemOnSelect && itemOnSelect(id); + ctxtOnSelect && ctxtOnSelect(id); + }; + const onContextMenu = isDisabled ? undefined : () => { + onClick(); + itemOnPopup && itemOnPopup(id); + ctxtOnPopup && ctxtOnPopup(id); + }; + const classes = 'dome-xSideBarItem' + + ( isSelected ? ' dome-active' : ' dome-inactive' ) + + ( isDisabled ? ' dome-disabled' : '' ); + return ( + <div className={classes} title={props.title} + onContextMenu={onContextMenu} + onClick={onClick}> + <Label icon={props.icon} label={props.label} /> + {props.children} + {React.Children.map(props.badge,makeBadge)} + </div> + ); +} + +// -------------------------------------------------------------------------- + +import { register } from 'dome/misc/register' ; + +register( SideBar, 'DOME_SIDEBAR' ); +register( Section, 'DOME_SIDEBAR_ITEM' ); +register( Item, 'DOME_SIDEBAR_ITEM' ); + +export default { SideBar, Section, Item } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/splitters.css b/Ivette/src/dome/src/renderer/layout/splitters.css new file mode 100644 index 00000000000..0b1e80e4413 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/splitters.css @@ -0,0 +1,51 @@ +/* -------------------------------------------------------------------------- */ +/* --- XSplitter Style Sheet --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xSplitter-container { + position: relative ; + width: 100% ; + height: 100% ; +} + +.dome-xSplitPane { + position: relative ; +} + +.dome-xSplitter-grab { + z-index: 1 ; + position: relative ; + border: 0 ; +} + +.dome-xSplitter-h { + left: -1px ; + width: 3px ; + height: 100% ; + cursor: col-resize ; +} + +.dome-xSplitter-v { + top: -1px ; + height: 3px ; + width: 100% ; + cursor: row-resize ; +} + +.dome-xSplitter-no-cursor { } +.dome-xSplitter-h-cursor { cursor: col-resize ; } +.dome-xSplitter-v-cursor { cursor: row-resize ; } + +.dome-window-active .dome-xSplitLine { + background: #afafaf ; +} + +.dome-window-inactive .dome-xSplitLine { + background: #d6d6d6 ; +} + +.dome-xSplitPane, .dome-xSplitLine { + transition: all 0.1s ease-out ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/splitters.js b/Ivette/src/dome/src/renderer/layout/splitters.js new file mode 100644 index 00000000000..18007cfbbfc --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/splitters.js @@ -0,0 +1,389 @@ +// -------------------------------------------------------------------------- +// --- Splitters +// -------------------------------------------------------------------------- + +/** @module dome/layout/splitters */ + +import React from 'react' ; +import Props from 'prop-types' ; +import Dome from 'dome' ; +import { Layout } from 'dome/misc/events' ; +import './splitters.css' ; +import _ from 'lodash' ; + +// -------------------------------------------------------------------------- +// --- Splitter Layout +// -------------------------------------------------------------------------- + +const SUBVIEW = { overflow: 'hidden' }; + +const LAYOUT = { + // Container Class + hcursor: 'dome-xSplitter-h-cursor', + vcursor: 'dome-xSplitter-v-cursor', + nocursor: 'dome-xSplitter-no-cursor', + // Grab Class + hgrab: 'dome-xSplitter-grab dome-xSplitter-h dome-color-dragzone', + vgrab: 'dome-xSplitter-grab dome-xSplitter-v dome-color-dragzone', + hdrag: 'dome-xSplitter-grab dome-xSplitter-h dome-color-dragging', + vdrag: 'dome-xSplitter-grab dome-xSplitter-v dome-color-dragging', + // Non-Positionned Splitter Styles + hsplitter: { width:1, height: '100%' }, + vsplitter: { height:1, width: '100%' }, + // Hidden style + hide: { display: 'none' }, + // Non-Positionned Pane Styles + fixH: { flex: 'none', height: 'auto', width: '100%' }, + extH: { flex: 'auto', minHeight: 30, width: '100%' }, + fixW: { flex: 'none', width: 'auto', height: '100%' }, + extW: { flex: 'auto', minWidth: 10, height: '100%' }, + // Non-Positionned Contailer Styles + horizontal: { + display:'flex', flexFlow: 'row nowrap' + }, + vertical: { + display:'flex', flexFlow: 'column nowrap' + }, + // Positionned Container Style + container: { + display:'block' + } +}; + +const subview = ( primary,secondary ) => + Object.assign( {} , SUBVIEW , { primary,secondary } ); + +// Tabulated flex-box styles +const FLEX = { + 'HORIZONTAL': subview( LAYOUT.extW, LAYOUT.extW ), + 'LEFT': subview( LAYOUT.fixW, LAYOUT.extW ), + 'RIGHT': subview( LAYOUT.extW, LAYOUT.fixW ), + 'VERTICAL': subview( LAYOUT.extH, LAYOUT.extH ), + 'TOP': subview( LAYOUT.fixH, LAYOUT.extH ), + 'BOTTOM': subview( LAYOUT.extH, LAYOUT.fixH ) +}; + +// Tabulated hidden styles +const HIDDEN = { + 'HORIZONTAL': subview( LAYOUT.hide, LAYOUT.extW ), + 'LEFT': subview( LAYOUT.hide, LAYOUT.extW ), + 'RIGHT': subview( LAYOUT.extW, LAYOUT.hide ), + 'VERTICAL': subview( LAYOUT.hide, LAYOUT.extH ), + 'TOP': subview( LAYOUT.hide, LAYOUT.extH ), + 'BOTTOM': subview( LAYOUT.extH, LAYOUT.hide ) +}; + +// Horizontal / Vertical mode +const LR = { + 'HORIZONTAL': true, + 'LEFT': true, + 'RIGHT': true, + 'VERTICAL': false, + 'TOP': false, + 'BOTTOM': false +}; + +// -------------------------------------------------------------------------- +// --- Splitter Component +// -------------------------------------------------------------------------- + +/** + @class + @summary Draggable split pane + @property {Direction} [dir] - Layout and dimensionning strategy + @property {string} [settings] - User-settings key for persistent splitter position + @property {number} [margin] - Minimal margin from container edges + @property {boolean} [unfold] - whether to display or not the slider component (by default) + @description + Layout two panels horizontally or vertically with a draggable splitter. + Clicking the splitter bar with any modifier key restore its natural position. + + The visibility of the slider component (the fixed size one, or the primary one) can + be defined by the `unfold` property. + + ##### Direction + + | Tag | Description + |:-------------------:|------------------------------------------------- + | `'HORIZONTAL'` | Horizontal layout (default) + | `'LEFT'`, `'RIGHT'` | Horizontal layout with _fixed_ left or right component + | `'VERTICAL'` | Vertical layout + | `'TOP'`, `'BOTTOM'` | Vertical layout with _fixed_ top or bottom component + + When resizing the entire component, free available space is distributed among both children + except when one is _fixed_ by the `dir` property. + Typically, if your component has a left side-bar, you would provide a `LEFT` direction + to the splitter. + + + ##### Children + + The component is designed for two children. If no-children is given, the + component returns `undefined`. If only one children is provided, it is + rendered as is-it, without any additional decoration. Extra chidren after the + 2nd are simply not rendered. + + + ##### Borders & Margin + + Primary and secondary components are laidout within positionned div elements with hidden overflows. + If your components have borders, you should adjust their CSS box-sizing property to `'border-box'`. + Margin with `'100%'` height or width should be avoided and replaced by padding, otherwize + the left and bottom sides of the views are likely to be cropped. + +*/ + +export class Splitter extends React.Component { + + // -------------------------------------------------------------------------- + // --- Life Cycle + // -------------------------------------------------------------------------- + + constructor(props) { + super(props); + this.handleReset = this.handleReset.bind(this); + this.handleClick = this.handleClick.bind(this); + this.handleResize = this.handleResize.bind(this); + this.handleDragInit = this.handleDragInit.bind(this); + this.handleDragMove = this.handleDragMove.bind(this); + this.handleDragStop = this.handleDragStop.bind(this); + this.doDragMove = _.throttle( this.doDragMove , 100 ); + this.lr = LR[ this.props.dir ]; + this.margin = Math.max( 32 , this.props.margin || 0 ); + this.state = { + dragging: false, // Splitter is currently dragging + absolute: false, // Splitter is positionned with offset + anchor: 0, // Invariant: anchor == mouse position - offset + offset: 0 // Position of splitter edge from container edge + }; + } + + // -------------------------------------------------------------------------- + // --- Mounting + // -------------------------------------------------------------------------- + + componentDidMount() { + if (this.refs.container && this.refs.splitter) { + const container = this.refs.container.getBoundingClientRect() ; + const dimension = this.lr ? container.width : container.height ; + this.range = dimension - this.margin ; + const settings = this.props.settings ; + if (settings) { + const offset = Dome.getWindowSetting(settings,-1); + if (this.margin <= offset && offset <= this.range) + this.setState({ absolute: true, offset }); + } + } + Dome.on( 'dome.defaults', this.handleReset ); + } + + componentWillUnmount() { + Dome.off( 'dome.defaults', this.handleReset ); + } + + componentDidUpdate() { + this.lr = LR[ this.props.dir ]; + this.margin = Math.max( 32 , this.props.margin || 0 ); + } + + // -------------------------------------------------------------------------- + // --- Reset Offset + // -------------------------------------------------------------------------- + + handleReset() { + this.setState({ absolute: false, dragging: false, anchor: 0, offset: 0 }); + Dome.setWindowSetting(this.props.settings, -1); + } + + handleClick(event) { + if (event.altKey || event.ctrlKey || event.cmdKey || event.shiftKey) + this.handleReset(); + } + + // -------------------------------------------------------------------------- + // --- Resizing Handler + // -------------------------------------------------------------------------- + + handleResize() { + // Defensive + if (this.refs.container && this.refs.splitter && this.state.absolute) { + let container = this.refs.container.getBoundingClientRect() ; + let dimension = this.lr ? container.width : container.height ; + if (dimension == 0) return; + let newrange = dimension - this.margin ; + let newoffset ; + switch(this.props.dir) { + case 'LEFT': + case 'TOP': + newoffset = this.state.offset ; + break; + case 'RIGHT': + case 'BOTTOM': + newoffset = this.state.offset + newrange - this.range ; + break; + default: + newoffset = this.state.offset + (newrange - this.range) / 2 ; + break; + } + this.range = newrange ; + if ( this.margin <= this.range) { + if (newoffset > this.range) newoffset = this.range ; + if (newoffset < this.margin) newoffset = this.margin ; + } else { + newoffset = dimension / 2 ; + } + this.setState( { offset: newoffset } ); + } + } + + // -------------------------------------------------------------------------- + // --- Init Drag + // -------------------------------------------------------------------------- + + handleDragInit(evt) { + evt.preventDefault(); + // Invariant: offset == position - anchor + let position = this.lr ? evt.clientX : evt.clientY ; + // Defensive + if (this.refs.splitter && this.refs.container) { + let splitter = this.refs.splitter.getBoundingClientRect() ; + let container = this.refs.container.getBoundingClientRect() ; + let dimension = this.lr ? container.width : container.height ; + let offset = this.lr + ? splitter.left - container.left + : splitter.top - container.top ; + this.range = dimension - this.margin ; + if (this.margin <= offset && offset <= this.range) { + let anchor = position - offset ; + this.setState( { dragging: true, absolute: true, + anchor: anchor, offset: offset } ); + } + } + } + + // -------------------------------------------------------------------------- + // --- Move Drag + // -------------------------------------------------------------------------- + + // Throttled 100ms + doDragMove(client) { + // Invariant: offset == position - anchor + let offset = client - this.state.anchor ; + if (this.margin <= offset && offset <= this.range) + this.setState( { offset: offset, absolute: true } ); + } + + // Not throttled (non-persistent event) + handleDragMove(evt) { + this.doDragMove(this.lr ? evt.clientX : evt.clientY); + } + + // -------------------------------------------------------------------------- + // --- Stop Drag + // -------------------------------------------------------------------------- + + handleDragStop(evt) { + Dome.setWindowSetting( this.props.settings, this.state.offset ); + this.setState({ dragging: false }); + } + + // -------------------------------------------------------------------------- + // --- Rendering + // -------------------------------------------------------------------------- + + render() { + const children = this.props.children ; + switch(children.length) { + case 0: + return undefined; + case 1: + return children[0]; + default: + let dir = this.props.dir; + let dragging = this.state.dragging; + let offset = this.state.offset; + let cursor = dragging + ? (this.lr ? LAYOUT.hcursor : LAYOUT.vcursor) + : LAYOUT.nocursor ; + let grab = this.state.dragging + ? (this.lr ? LAYOUT.hdrag : LAYOUT.vdrag ) + : (this.lr ? LAYOUT.hgrab : LAYOUT.vgrab ) ; + let container, splitter, primary, secondary ; + let { unfold=true } = this.props ; + let absolute = this.state.absolute ; + if (!unfold) + { + container = LAYOUT.container ; + splitter = LAYOUT.hide ; + let hidden = HIDDEN[dir] ; + primary = hidden.primary ; + secondary = hidden.secondary ; + } + else if (!absolute) + { + container = this.lr ? LAYOUT.horizontal : LAYOUT.vertical ; + splitter = this.lr ? LAYOUT.hsplitter : LAYOUT.vsplitter ; + let flex = FLEX[dir]; + primary = flex.primary ; + secondary = flex.secondary ; + } + else + { + container = LAYOUT.container ; + if (this.lr) { + primary = { position: 'absolute', left: 0, width: offset, height: '100%' }; + splitter = { position: 'absolute', left: offset, width: 1, height: '100%' }; + secondary = { position: 'absolute', left: offset+1, right: 0, height: '100%' }; + } else { + primary = { position: 'absolute', top: 0, height: offset, width: '100%' }; + splitter = { position: 'absolute', top: offset, height: 1, width: '100%' }; + secondary = { position: 'absolute', top: offset+1, bottom: 0, width: '100%' }; + } + Object.assign( primary , SUBVIEW ); + Object.assign( secondary , SUBVIEW ); + } + return ( + <div ref="container" + onMouseUp={dragging ? this.handleDragStop : undefined} + onMouseMove={dragging ? this.handleDragMove : undefined} + className={'dome-xSplitter-container ' + cursor} + style={container}> + <div ref="primary" style={primary} className='dome-xSplitPane dome-container'> + {children[0]} + </div> + <div ref="splitter" style={splitter} className='dome-xSplitLine'> + <div className={grab} + onMouseDown={this.handleDragInit} + onClick={absolute ? this.handleClick : undefined} /> + </div> + <div ref="secondary" style={secondary} className='dome-xSplitPane dome-container'> + {children[1]} + </div> + <Layout onResize={this.handleResize} /> + </div> + ); + } + } + +} + +// -------------------------------------------------------------------------- +// --- Props & Defaults +// -------------------------------------------------------------------------- + +Splitter.propTypes = { + dir: Props.oneOf(['HORIZONTAL','VERTICAL','LEFT','RIGHT','TOP','BOTTOM']), + settings: Props.string, + margin: Props.number +}; + +Splitter.defaultProps = { + dir: 'HORIZONTAL', + margin: 32 +}; + +// -------------------------------------------------------------------------- + +export default { Splitter }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/tabs.css b/Ivette/src/dome/src/renderer/layout/tabs.css new file mode 100644 index 00000000000..f604114d0a7 --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/tabs.css @@ -0,0 +1,98 @@ +/* -------------------------------------------------------------------------- */ +/* --- Tabs & Tab Style Sheet --- */ +/* -------------------------------------------------------------------------- */ + +/* Tabs Bar */ + +.dome-xTabsBar { + flex: 0 1 auto ; + position: relative ; + height: 20px ; + width: calc( 100% + 1px ); /* hides last border */ + display: flex ; + flex: row wrap ; + border-width: 1px ; + border-bottom-style: solid ; +} + +/* Tab Content */ + +.dome-xTab-content { + width: 100% ; + height: 100% ; +} + +/* Tab Item */ + +.dome-xTab { + flex: 1 1 150px ; + position: relative ; + font-size: 10px ; + text-align: center ; + padding: 4px 20px 4px 20px ; + border-color: inherit ; + border-width: 1px ; + border-top-style: none ; + border-bottom-style: none ; + border-left-style: none ; + border-right-style: solid ; +} + +.dome-window-inactive .dome-xTab.dome-inactive { + color: #606060 ; + border-color: inherit ; +} + +.dome-xTab.dome-inactive:hover { + background: #bababa ; +} + +.dome-xTab.dome-inactive { + color: #606060 ; + border-color: #9c9c9c ; + background: #b4b4b4 ; +} + +.dome-window-inactive .dome-xTab.dome-inactive { + color: #b0b0b0 ; + background: #e6e6e6 ; +} + +/* Closing Tab button */ + +.dome-xTab-closing { + display: inline ; + border-radius: 4px ; + position: absolute ; + width: 12px ; + height: 12px ; + padding: 2px ; + top: 2px ; + opacity: 0 ; + transition: opacity .1s linear 0.1s , background .1s linear 0.1s ; +} + +.dome-platform-darwin .dome-xTab-closing { + right: initial ; + left: 5px ; +} + +.dome-xTab-closing { + right: 5px ; + left: initial ; +} + +.dome-active .dome-xTab-closing:hover { + background: #c0c0c0 ; +} + +.dome-inactive .dome-xTab-closing:hover { + background: #a0a0a0 ; +} + +.dome-xTab:hover .dome-xTab-closing , .dome-xTab:hover .dome-xTab-closing +{ + opacity: 1 ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/tabs.js b/Ivette/src/dome/src/renderer/layout/tabs.js new file mode 100644 index 00000000000..19987a0948c --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/tabs.js @@ -0,0 +1,123 @@ +import React from 'react' ; +import { Icon } from 'dome/controls/icons' ; +import './tabs.css' ; + +/** @module dome/layout/tabs */ + +// -------------------------------------------------------------------------- +// --- Tabs Bar +// -------------------------------------------------------------------------- + +/** + @class + @summary Pure Container for tab buttons. + @description + Shall contains [Tab](module-dome_layout_tabs.Tab.html) instances. +*/ + +export function TabsBar(props) { + return ( + <div className='dome-xTabsBar dome-color-frame'> + {props.children} + </div> + ); +} + +// -------------------------------------------------------------------------- +// --- Single Tab +// -------------------------------------------------------------------------- + +const VISIBLE = { display: 'block' }; +const HIDDEN = { display: 'none' }; + +/** + @class + @summary Pure Component for rendering a tab button. + @property {string} [id] - tab's identifier + @property {component} [label] - tab's label + @property {string} [title] - tab's tooltip + @property {string} [closing] - closing button's tooltip (defaults to `"Close Tab"`) + @property {string} [selection] - Currently selected tab identifier + @property {function} [onSelection] - selection callcack, feed with value + @property {function} [onClose] - selection callcack, feed with value + @property {boolean} [default] - if `true`, selected tab by default + @property {boolean} [content] - render content instead of tab + @description + A single tab selector. Shall only be used as a children + of [TabsBar](module-dome_layout_tabs.TabsBar.html) + or [Frame](module-dome_layout_frames.Frame.html). + + When `content` is positionned, the component renders + its content children instead of the tab button. In such a case, content + is displayed only when selected. + + __Remark__: on Mac OSX, the close button appears on the left-side of the tab. +*/ + +export function Tab(props) { + const selected = props.id === props.selection ; + if (props.content) { + //--- Content Rendering + const style = selected ? VISIBLE : HIDDEN ; + return ( + <div className='dome-xTab-content dome-container' style={style}> + {props.children} + </div> + ); + } else { + //--- Tab Rendering + const onClick = props.onSelection && (() => props.onSelection(props.id)); + const onClose = props.onClose && (() => props.onClose(props.id)); + var closing = onClose ? ( + <Icon className="dome-xTab-closing" + title={props.closing || "Close Tab"} + name="CROSS" onClick={onClose} /> + ) : undefined ; + const classes = 'dome-xTab' + ( selected ? ' dome-active' : ' dome-inactive' ) ; + return ( + <label + className={classes} title={props.title} onClick={onClick}> + {props.label} + {closing} + </label> + ); + } +} + +// -------------------------------------------------------------------------- +// --- TabsPane +// -------------------------------------------------------------------------- + +/** + @class + @summary Pure Container for tab contents. + @property {string} selection - tab identifier to render + @property {Tab[]} children - tabs (content) to render + @description + Shall contains [Tab](module-dome_layout_tabs.Tab.html) instances. + Only the selected tab identifier will be displayed, although all tab + contents remains properly mounted. If no tab is selected, + no content is displayed. +*/ + +export function TabsPane({ selection, children }) { + const showTab = (elt) => React.cloneElement(elt, { content: true, selection }); + return ( + <React.Fragment> + {React.Children.map(children , showTab)} + </React.Fragment> + ); +} + +// -------------------------------------------------------------------------- +// --- Dome Class (private) +// -------------------------------------------------------------------------- + +import { register } from 'dome/misc/register' ; + +register(TabsBar, 'DOME_TABSBAR'); +register(Tab, 'DOME_TABSBAR_ITEM'); + +export default { Tab , TabsBar , TabsPane } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/layout/toolbars.css b/Ivette/src/dome/src/renderer/layout/toolbars.css new file mode 100644 index 00000000000..453fe172fbe --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/toolbars.css @@ -0,0 +1,228 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling ToolBars --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xToolBar { + flex: 0 0 auto ; + width: 100% ; + display: flex ; + flex-direction: row ; + flex-wrap: wrap ; + align-items: baseline ; + border-width: 1px ; + border-bottom-style: solid ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling ToolBar Spaces --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xToolBar-inset { + flex: 0 1 5px ; +} + +.dome-xToolBar-space { + flex: 0 1 20px ; +} + +.dome-xToolBar-filler { + flex: 1 1 20px ; +} + +.dome-xToolBar-separator + .dome-xToolBar-separator { + display: none ; +} + +.dome-xToolBar-separator { + flex: 0 0 10px ; + align-self: center ; +} + +.dome-xToolBar-vrule { + width: 2px ; + position: relative ; + left: 4px ; + height: 18px ; +} + +.dome-window-active .dome-xToolBar-vrule { + background: #aaa ; +} + +.dome-window-inactive .dome-xToolBar-vrule { + background: #ddd ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling ToolBar Buttons --- */ +/* -------------------------------------------------------------------------- */ + +/* Layout */ + +.dome-xToolBar-Control { + flex: 0 0 auto ; + height: 26px ; + margin: 6px 5px 6px 5px ; + padding: 2px 8px 2px 8px ; + box-shadow: 0 1px 1px rgba(0, 0, 0, .06); + border: 1px solid transparent; + border-radius: 4px; + outline: none ; +} + +.dome-xToolBar-Control svg { + position: relative ; +} + +.dome-xToolBar-Control svg + label { + margin-left: 4px ; +} + +/* Background */ + +.dome-window-active .dome-xToolBar-Control { + background-image: linear-gradient(to bottom, #e8e8e8 0, #f1f1f1 100%); +} + +.dome-window-active .dome-xToolBar-Control:hover:not(:disabled) { + background-color: #ffffff ; + background-image: none ; +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-positive:not(:disabled) { + background-image: linear-gradient(to bottom, #34ff52 0%, #48fd64 100%); +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-positive:hover:not(:disabled) { + background-color: #00ff00 ; + background-image: none ; +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-negative:not(:disabled) { + color: #ccc ; + fill: #ccc ; + background-image: linear-gradient(to bottom, #ec453e 0%, #ff4c47 100%); +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-negative:hover:not(:disabled) { + background-color: red ; + background-image: none ; +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-warning:not(:disabled) { + background-image: linear-gradient(to bottom, #fece72 0%, #fcaa0e 100%); +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-warning:hover:not(:disabled) { + background-color: orange ; + background-image: none ; +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-cancel:not(:disabled) { + background-color: #c2c0c2 ; + background-image: none ; +} + +.dome-window-active .dome-xToolBar-Control.dome-xToolBar-cancel:hover:not(:disabled) { + background-image: linear-gradient(to bottom, #e8e8e8 0, #f1f1f1 100%); +} + +.dome-window-inactive .dome-xToolBar-Control { + box-shadow: none ; + background-image: none ; +} + +/* Activated */ + +.dome-window-active .dome-xToolBar-Control:active:not(:disabled) { + fill: #ddd ; + color: #ddd ; + background-color: gray ; + background-image: none ; +} + +/* Disabled */ + +.dome-window-active .dome-xToolBar-Control:disabled { + fill: #ccc ; + color: #ccc ; + box-shadow: none ; + border-color: #bbb ; +} + +.dome-window-inactive .dome-xToolBar-Control:disabled { + fill: #ccc ; + color: #ccc ; +} + +/* Selected */ + +.dome-window-active .dome-xToolBar-Control.dome-selected { + fill: #fff; + color: #fff; + border: 1px solid transparent ; + background-color: #7f7f7f ; + background-image: none ; +} + +.dome-window-active .dome-xToolBar-Control.dome-selected:hover { + background-color: #888 ; + background-image: none ; +} + +.dome-window-inactive .dome-xToolBar-Control.dome-selected { + fill: #eee; + color: #eee; + background-color: #ccc ; +} + +/* Selected & Disabled */ + +.dome-window-active .dome-xToolBar-Control.dome-selected:disabled { + fill: #ccc ; + color: #ccc ; + border: 1px solid #bbb ; + background-color: #eee ; +} + +.dome-window-inactive .dome-xToolBar-Control.dome-selected:disabled { + fill: #ccc ; + color: #ccc ; + border-color: #ddd ; + background-color: #eee ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling ToolBar Button Group --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xToolBar-Group { + display: flex ; + flex-direction: row ; + flex-wrap: nowrap ; + margin: 6px 5px 6px 5px ; +} + +.dome-xToolBar-Group .dome-xToolBar-Control { + margin: 0 ; +} + +.dome-xToolBar-Group .dome-xToolBar-Control:not(:first-child) { + border-left: 0 ; +} + +.dome-xToolBar-Group > .dome-xToolBar-Control:first-child { + border-top-right-radius: 0 ; + border-bottom-right-radius: 0 ; +} + +.dome-xToolBar-Group > .dome-xToolBar-Control:last-child { + border-top-left-radius: 0 ; + border-bottom-left-radius: 0 ; +} + +.dome-xToolBar-Group > .dome-xToolBar-Control:not(:first-child):not(:last-child) { + border-radius: 0 ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/layout/toolbars.js b/Ivette/src/dome/src/renderer/layout/toolbars.js new file mode 100644 index 00000000000..0aa477f44ff --- /dev/null +++ b/Ivette/src/dome/src/renderer/layout/toolbars.js @@ -0,0 +1,198 @@ +// -------------------------------------------------------------------------- +// --- ToolBars +// -------------------------------------------------------------------------- + +/** @module dome/layout/toolbars */ + +import React from 'react' ; +import './toolbars.css' ; + +// -------------------------------------------------------------------------- +// --- ToolBar Container +// -------------------------------------------------------------------------- + +/** + @class + @summary Container for toolbar items + @description + See also [Frame](module-dome_layout_frames.Frame.html) containers. + */ +export class ToolBar extends React.Component { + + constructor(props) { + super(props); + } + + render() { + const children = this.props.children ; + return React.Children.count(children) > 0 && ( + <div className='dome-xToolBar dome-color-frame'> + <div className='dome-xToolBar-inset'/> + {children} + <div className='dome-xToolBar-inset'/> + </div> + ); + } + +} + +// -------------------------------------------------------------------------- +// --- ToolBar Spaces +// -------------------------------------------------------------------------- + +/** + @class + @summary Fixed (tiny) space +*/ +export const Inset = (() => <div className='dome-xToolBar-inset'/>); + +/** + @class + @summary Fixed space +*/ +export const Space = (() => <div className='dome-xToolBar-space'/>); + +/** + @class + @summary Extensible space (can be used to right-align controls) +*/ +export const Filler = (() => <div className='dome-xToolBar-filler'/>); + +/** + @class + @summary Vertical rule +*/ +export const Separator = () => ( + <div className='dome-xToolBar-separator'> + <div className='dome-xToolBar-vrule'/> + </div> +); + +// -------------------------------------------------------------------------- +// --- ToolBar Button +// -------------------------------------------------------------------------- + +import { SVG } from 'dome/controls/icons' ; + +const SELECT = 'dome-xToolBar-Control dome-selected' ; +const BUTTON = 'dome-xToolBar-Control dome-color-frame' ; +const KIND = (kind) => kind ? ' dome-xToolBar-' + kind : ''; + +const isSelected = ( { selected , selection , value } ) => ( + selected !== undefined ? selected : ( value !== undefined && value === selection ) +); + +const isDisabled = ( { enabled=true, disabled=false } ) => (disabled || !enabled) ; +const onClick = ( { onClick , value } ) => onClick ? (() => onClick(value)) : undefined ; + +/** + @class + @property {string} [icon] - Button icon name (See [gallery](gallery-icons.html)) + @property {string} [label] - Button label + @property {string} [title] - Button tooltip + @property {string} [kind] - Styled button (see below) + @property {boolean} [selected] - Selected button (default: `false`) + @property {boolean} [disabled] - Disabled button (default: `false`) + @property {boolean} [enabled] - Enabled button (default: `true`) + @property {any} [value] - button's value + @property {any} [selection] - Currently selected value + @property {function} [onClick] - Button callback (receives the current value) + @summary toolbar button + @description + + By default, the propery `selected` is computed from properties `value` + and `selection`, when provided. + + The callback is given the `value` property, if any. + + The different available kinds for styling a (non-selected) button are: + - `'default'`: normal button; + - `'cancel'`: normal button, in dark grey; + - `'warning'`: warning button, in orange; + - `'positive'`: positive button, in green; + - `'negative'`: negative button, in red. + +*/ +export const Button = ( props ) => ( + <button + disabled={isDisabled(props)} + className={isSelected(props) ? SELECT : (BUTTON + KIND(props.kind))} + onClick={onClick(props)} + title={props.title} + > + {props.icon && <SVG id={props.icon} />} + {props.label && <label>{props.label}</label>} + </button> +); + +// -------------------------------------------------------------------------- +// --- ToolBar Button Group +// -------------------------------------------------------------------------- + +/** + @class + @property {Button[]} children - Buttons in the group + @property {any} [value] - Passed to children as `selection` property + @property {any} [onChange] - Passed to children as `onClick` property + @property {any} [...props] - Properties passed to all children + @summary toolbar button group +*/ +export const ButtonGroup = + ({ children, value, onChange, ...props }) => + { + if (value !== undefined ) props.selection = value ; + if (onChange !== undefined ) props.onClick = onChange ; + return ( + <div className='dome-xToolBar-Group'> + {React.Children.map(children,(elt) => React.cloneElement(elt,props))} + </div> + ); + }; + +// -------------------------------------------------------------------------- +// --- ToolBar Menu +// -------------------------------------------------------------------------- + +/** + @class + @property {any} [value] - selected option's value + @property {function} [onChange] - selection callback (receives option value) + @property {boolean} [disabled] - disable the selector (default: `false`) + @property {boolean} [enabled] - enable the selector (default: `true`) + @property {option[]} children - Array of menu options + @summary Toolbar selector menu + @description + + Behaves likes a standard `<select>` element, except that callback directly + receives the select value, not the entire event. + + The list of options shall be given with standard `<option value={...} label={...}>` + elements. + +*/ +export const Select = (props) => ( + <select className='dome-xToolBar-Control dome-color-frame' + value={props.value} + disabled={isDisabled(props)} + onChange={(props.onChange && ((evt) => props.onChange(evt.target.value)))} + > + {props.children} + </select> +); + +// -------------------------------------------------------------------------- +// --- Export & Registration +// -------------------------------------------------------------------------- + +import { register } from 'dome/misc/register' ; + +register( ToolBar, 'DOME_TOOLBAR' ); +register( Inset , 'DOME_TOOLBAR_ITEM' ); +register( Space , 'DOME_TOOLBAR_ITEM' ); +register( Separator , 'DOME_TOOLBAR_ITEM' ); +register( Filler , 'DOME_TOOLBAR_ITEM' ); +register( Button , 'DOME_TOOLBAR_ITEM' ); + +export default { ToolBar , Space , Inset, Separator, Filler, Button, ButtonGroup, Select }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/table/arrays.js b/Ivette/src/dome/src/renderer/table/arrays.js new file mode 100644 index 00000000000..9663577ff45 --- /dev/null +++ b/Ivette/src/dome/src/renderer/table/arrays.js @@ -0,0 +1,489 @@ +// -------------------------------------------------------------------------- +// --- Table Models +// -------------------------------------------------------------------------- + +/** @module dome/table/arrays */ + +import { Model, ASC, DESC } from 'dome/table/models' ; + +// -------------------------------------------------------------------------- +// --- Ordering +// -------------------------------------------------------------------------- + +// Compute the value of an item +const getValueWith = + ( item , value ) => + ( item === undefined ? undefined : + typeof(value) === 'function' ? value(item) : + item[value] ); + +// Compute the primary ordering function +const comparisonWith = (sorting) => { + switch(typeof(sorting)) { + + case 'function': + return sorting ; + + case 'string': + return (a,b) => { + if ( a === b ) return 0 ; + if ( a === undefined ) return 1 ; + if ( b === undefined ) return -1 ; + const va = a[sorting]; + const vb = b[sorting]; + if ( va === vb ) return 0; + if ( va === undefined ) return 1 ; + if ( vb === undefined ) return -1 ; + if ( va < vb ) return -1; + if ( va > vb ) return 1; + return 0; + }; + + case 'object': + const { sortBy, sortDirection=ASC } = sorting ; + return (a,b) => { + if ( a === b ) return 0 ; + if ( a === undefined ) return 1 ; + if ( b === undefined ) return -1 ; + const isFun = typeof(sortBy)==='function' ; + const va = isFun ? sortBy(a) : a[sortBy] ; + const vb = isFun ? sortBy(b) : b[sortBy] ; + if ( va === vb ) return 0; + if ( va === undefined ) return 1 ; + if ( vb === undefined ) return -1 ; + switch(sortDirection) { + case ASC: + if (va < vb) return -1; + if (va > vb) return 1; + break; + case DESC: + if (va < vb) return 1; + if (va > vb) return -1; + break; + } + return 0; + }; + + default: + return () => 0; + + } +}; + +// Make a chainable order +const chainableOrder = ( order ) => { + + const compare = (a,b) => { + for (var k = 0; k < order.length ; k++) { + const cmp = (order[k])(a,b); + if (cmp) return cmp; + } + return 0; + }; + + compare.thenWith = (sorting) => + sorting ? + chainableOrder( order.slice().push(comparisonWith(sorting)) ) + : compare ; + + return compare ; +}; + +/** + @summary Comparison helper. + @method + @param {any} sorting - the sorting properties + @return {function} the corresponding comparison function + @description + +This function is a helper for comparing items, by comparing +values extracted from them with chaining. It returns +a comparison function that you can use, for instance, +in `Array.sort` fort sorting arrays. + +##### Comparison + +The comparison order is defined according the `sorting` parameter +provided to the helper: + +If `sorting` is a function, it is used as the primary comparison function. +When items compare equal, chained comparisons are used to refine the +ordering (see Chaining below). + +If `sorting` is a property name (a string), items `a` and `b` are ordered +by comparing their respective values `a[sorting]` and `b[sorting]` for +this property. + +If `sorting` as an object, it shall provides `{ sortBy, sortDirection }` +properties and the comparison function is defined as follows: +- `sortBy` can be a function or a property name. +If a function is given, items `a` and `b` are ordered by comparing +values `sortBy(a)` and `sortBy(b)`. Otherwize, they are ordered by +comparing `a[sortBy]` and `b[sortBy]`. +- `sortDirection` can be either `ASC` for normal comparison or `DESC` +for reversing the comparison. +If no direction is given (or any other value) `ASC` is assumed. + +When computing comparison, `undefined` values are _always_ rejected to the +end of the ordering, whatever the specified direction. + +##### Chaining + +The returned comparison function can be chained with a secondary +comparison function, which will be used when two items compare equal. + +You can chain as many comparison functions you want by using +`.thenWith(sorting)` like in the example below. Each call to `.thenWith` returns +a different comparison function that can be safely forked with subsequent calls +to `.thenWith` as illustrated in the second example. + +Remark than `compareWith` and `.thenWith` also accept undefined or null values, which +are considered neutral. + +@example +// Chaining Comparison +items.sort( + compareWith({sortBy:'name',sortDirection: ASC}) + .thenWith( (a,b) => a.priority - b.priority ) + .thenWith({sortBy:'age',sortDirection: DESC}) +); + +@example +// Forking Comparison +const primary = compareWith( (a,b) => a.priority - b.prioroty ); +const byName = primary.thenWith('name'); +const byAge = primary.thenWith('age'); + +*/ +export const compareWith = + ( sorting ) => + ( sorting ? chainableOrder([ comparisonWith(sorting) ]) : () => 0 ); + +// -------------------------------------------------------------------------- +// --- Comparison Ring +// -------------------------------------------------------------------------- + +/** + @class + @summary Helper for column comparison. + @description +A comparison ring can be used to implement column ordering, where each +column selection _refines_ the previous ordering. + +Hence, the ring holds the current comparison order and it is well suited +for being used in conjunction with [Table](module-dome_table_views.Table.html) +components. + +A comparison specification can be a property name or a function. +See [compareWith](module-dome_table_arrays.html#compareWith) for more details. +By default, the ring uses the column identifier as a property name for comparing. + +Initially, the ordering is _natural_. +*/ +export class ComparisonRing { + + /** + @param {id|function} [natural] - default (natural) order + */ + + constructor(natural) { + this.columns = {} ; + this.natural = natural && comparisonWith(natural) ; + this.compare = this.compare.bind(this); + this.ring = [] ; + this.sort = undefined ; + } + + /** + @summary Current order comparison. + @description + Returns the comparison function corresponding to the current order. + The comparison function is _chainable_, see + [compareWith](module-dome_table_arrays.html#compareWith) for more details. + */ + compareWith() + { + if (!this.sort) { + const ordering = this.ring.map( + ({sortBy,sortDirection}) => + comparisonWith({ + sortBy: this.columns[sortBy] || sortBy , + sortDirection + }) + ); + if (this.natural) ordering.push(this.natural); + this.sort = chainableOrder(ordering); + } + return this.sort; + } + + /** + @summary Refine current order comparison. + @description + Short cut for `this.compareWith().thenWith(sorting)` + */ + thenWith(sorting) { + return this.compareWith().thenWith(sorting); + } + + /** + @summary Get value for ordering a column. + @param {any} item - the item to compare with + @param {string} column - the column identifier + @return {any} item's value for the column + Returns the value used to order an item within a given column. + */ + getValue(item,column) { + return getValueWith(item,this.columns[column] || column); + } + + /** + @summary Set value to order a column. + @param {string} column - column identifier + @param {string|function} [value] - value accessor (defaults to `column`) + @description + Set the sorting specification (property name or function) for the given column. + */ + setValue( column , value ) { + this.columns[column] = value ; + } + + /** Sets natural ordering (property name or value accessor) */ + setNatural( natural ) { + this.natural = natural ; + } + + /** @summary Compare two items with respect to the current ordering. + @description + You can use `this.compare` as a closure to the current comparison function + (no need for `this.compare.bind(this)`). + */ + compare(a,b) { + return this.order()(a,b); + } + + /** @summary Return current ordering. + @return {object} ordering specification + @description + Return the last `{ sortBy, sortDirection }` ordering. + Shall be used for the Table view. */ + getOrdering() { + return this.ring[0] ; + } + + /** + @summary Specify current ordering. + @param {object} sorting - the new ordering + @description + Use the specified `{ sortBy, sortDirection }` ordering, and refine it with + the previous one. + + If `sorting` is undefined, reset the ring to the natural ordering. + */ + setOrdering( sorting ) { + if (sorting) { + const key = sorting.sortBy ; + this.ring = this.ring.filter( (s) => s.sortBy !== key ); + this.ring.unshift( sorting ); + } else { + this.ring = [] ; + } + this.sort = undefined ; + } + +} + +// -------------------------------------------------------------------------- +// --- Unsorted Model +// -------------------------------------------------------------------------- + +/** + @summary A table Model for unsorted datasets. + @description + + This class implements a simple [Model](module-dome_table_models.Model.html) + where item's are identified by their index. Such a model is not adapted to + re-ordering and filtering, because table views will have no way to synchronize + the selected index before and after re-ordering, hence the name. + +*/ + +export class UnsortedModel extends Model { + + /** + @param {number} [count] - the initial size (default `0`) + */ + constructor(count=0) { + super(); + this.count = count < 0 ? 0 : count ; + } + + /** + @summary Set the number of items. + @param {number} n - the number of items + @param {boolean} [reload] - force reloading (false by default) + @description + Triggers a reload if the item count has changed, + unless you force it. + */ + setItemCount(n,reload=false) { + if (n<0) n=0; + if ( reload || n != this.count ) { + this.count = n ; + this.reload(); + } + } + + getItemCount() { return this.count; } + + /** Identity, or `undefined` when out of range. */ + getItemAt(k) { + return 0 <= k && k < this.count ? k : undefined ; + } + + /** Identity, or `-1` when out of range. */ + getIndexOf(k) { + return 0 <= k && k < this.count ? k : -1 ; + } + +} + +// -------------------------------------------------------------------------- +// --- Array Model +// -------------------------------------------------------------------------- + +/** + @summary A table Model based on array. + @description + + This class implements a simple [Model](module-dome_table_models.Model.html) + implementation where item's are stored in an array. The model supports built-in + ordering thanks with a + [ComparisonRing](module-dome_table_arrays.ComparisonRing.html) + with additional filtering capabilities. + + The model keep items in sync with their ordered & filtered index by + injecting an `index` property in them each time the collection is re-ordered. + You shall not use `index` property for your own needs. + + Item objects can be modified in place, but you shall call `model.updateItem(item)` + or `model.reload()` to re-renderer the associated (visible) cells. + */ +export class ArrayModel extends Model { + + /** Initially empty model */ + constructor() { + super(); + this.ring = new ComparisonRing('index'); // Used for stable sorting + this.data = []; // Array of item elements + } + + /** Remove all items (and reload) */ + clear() { + this.data = [] ; + this.reload(); + } + + /** Add one or more items (and reload) */ + add( ...items ) { + this.data.push(...items); + this.reload(); + } + + /** + @summary Model items array. + @description +Returns the internal item array holding _all_ the items in the model. + +This array is _not_ sortered and filtered. You can obtain the current index of an item in +table views by accessing its `item.index` property, which is `undefined` if the item has been +filtered out. + +If you modify the internal item array, don't forget to call `reload()` after modifications +in order to keep views in sync. + */ + getData() { return this.data; } + + /** Replace the entire collection of items */ + setData(data) { + this.data = data || [] ; + this.reload(); + } + + _order() { + if (!this.order) { + const filter = this.filtering ; + const compare = this.ring.compareWith(); + const ordered = this.data.filter((item,index) => { + const ok = filter ? filter(item) : true ; + // Index inside initial collection is used for stable sort + item.index = ok ? index : undefined ; + return ok ; + }).sort(compare); + // Now set index in filtered & sorted collection + ordered.forEach((item,index) => item.index = index); + this.order = ordered ; + } + return this.order ; + } + + /** Return a _copy_ of the visible items */ + getItems() { return this._order().slice(); } + + /** Returns the number of visible items */ + getItemCount() { return (this._order()).length; } + + /** Returns the visible item at the given index */ + getItemAt(index) { return (this._order())[index] ; } + + /** Returns the index of an item */ + getIndexOf(item) { return item && item.index ; } + + /** @summary Current filtering function. + @return {function} `undefined` means no filtering + */ + getFiltering() { return this.filtering ; } + + /** Current ordering (see `ComparisonRing`) */ + getOrdering() { return this.ring.getOrdering(); } + + /** Set the filtering function */ + setFiltering(filter) { + this.filtering = filter ; + this.reload(); + } + + /** Set ordering (see `ComparisonRing`) */ + setOrdering(order) { + if (order === undefined || order.sortBy !== 'index') + { + this.ring.setOrdering(order); + this.reload(); + } + } + + /** Get the value of an item for the given column */ + getValue( item , column ) { + return this.ring.getValue( item , column ); + } + + /** Set the value-getter for the given column */ + setValue( column , value ) { + this.ring.setValue(column,value); + this.reload(); + } + + /** Re-order the items collection and re-render the table */ + reload() { + this.order = undefined ; + super.reload(); + } +} + +// -------------------------------------------------------------------------- +// --- Exports +// -------------------------------------------------------------------------- + +export default { compareWith , ComparisonRing , UnsortedModel } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/table/models.js b/Ivette/src/dome/src/renderer/table/models.js new file mode 100644 index 00000000000..f0f53312345 --- /dev/null +++ b/Ivette/src/dome/src/renderer/table/models.js @@ -0,0 +1,255 @@ +// -------------------------------------------------------------------------- +// --- Models +// -------------------------------------------------------------------------- + +/** @module dome/table/models */ + +import _ from 'lodash' ; +import { SortDirection } from 'react-virtualized' ; + +// -------------------------------------------------------------------------- +// --- Sorting +// -------------------------------------------------------------------------- + +/** Ascending Order (SortDirection) */ +export const ASC = SortDirection.ASC ; + +/** Descending Order (SortDirection) */ +export const DESC = SortDirection.DESC ; + +// -------------------------------------------------------------------------- +// --- Collection Model +// -------------------------------------------------------------------------- + +/** + @class + @summary Data Listener. + @description + + A Model is responsible for keeping the tables and lists views in sync + with their associated data sets. The model listens for updates, retrieves + items from their index, and re-render the views when necessary. + + + Model could be part of the global _Application State_, or part of a + statefull React Component, depending on your need as described in + the [Application Design](tutorial-application.html) tutorial. + + + Several tables may connect to the same table model, but they will share the + same number and ordering of items. However, each connected table will only + render its own range of items and will re-renderer only when impacted by + individual updates. + + + A Model instance may not hold the data directly. A table or list component + uses the model only as a _proxy_ reponsible for fetching the items with respect to + some current filtering and ordering selection. The model also serves as + a proxy for triggering table re-rendering when table data is updated. + + + To design your data model, you shall extends the base `Model` class and + override the public methods to fit your needs. + + - `getItemCount() -> number` (the number of items) + - `getItemAt(number) -> item` (the item at the given index) + - `getIndexOf(item) -> number` (the index of an item in the current orderer) + - `getValue(item,column) -> any` (the value associated to some item in a column) + + + To implement sorting, you shall also override the following methods: + + - `getOrdering() -> { sortBy, sortDirection }` + - `setOrdering({ sortBy, sortDirection }) -> ()` + + + Whenever data is added, removed, updated or re-ordered, the `Model` shall be + informed by calling one of the following methods: + + - `updateItem(item);` when an individual item shall be re-rendered (if ever visible) + - `updateIndex(index[,index]);` when an item or a range of items shall be re-rendered + - `reload();` for all other modifications of the collection, including filtering and re-ordering + + + Items count and items indices shall be consistent with the current filter(s) + and order(s) selected by the user. Tables are equipped with + callbacks on table headers that can be used to trigger re-ordering of your data, but + you can implement your own controls or use menus to do that. + + Items can be represented by any javascript values (string, integers, objects...). + Default table cell renderers expect items to be object with one property per column, but you + can override those default. The default `getValue` implementation simply returns the + item property corresponding to the column identifier. + + When some data is updated, selection and scrolling of the views will be + preserved based on item's value. Table and List views will + keep each rendered item in sync with their index thanks to methods `getItemAt` + and `getIndexOf` that you provide with the Model. + + Hence, items implementation shall contains enough information to uniquely identify them, + whatever their current index. + + ##### Model Helpers + + The module [dome/table/arrays](module-dome_table_arrays.html) provides you with + usefull helpers to implement Models with filtering and ordering features. + +*/ +export class Model { + + constructor() { + this._dome_clients = {} ; + this._dome_clientId = 0 ; + } + + /** + @summary Items count. + @abstract + @return {number} number of items + @description + Shall return the number of items to be displayed by the table. + Negative values are considered as zero. + Default implementation returns zero. + */ + getItemCount() { return 0; } + + /** + @summary Item at given index. + @abstract + @param {number} index - item's ordering index + @return {any} the item's value + @description + Shall return the item at a given index in the table with respect to + current filtering and ordering (if appropriate). + <p> + Default implementation returns `undefined`. + */ + getItemAt() { return undefined; } + + /** + @summary Index of an item. + @abstract + @param {any} item - the item + @return {number} index of the item in the filtered and ordered collection + @description + Shall return the index of a given item inside the table with respect to + current filtering and ordering, or `undefined` if no such item exists. + <p> + Default implementation returns `undefined`. + */ + getIndexOf() { return undefined; } + + /** + @summary Item value in a column. + @param {any} item - an item + @param {string} column - a column identifier + @return {any} the value associated to the item for the given column. + @description + Defaults to accessing the column property of the item (ie. `item[column]`). + This method can be overriden by custom models and also table columns. + */ + getValue(item,column) { return item[column]; } + + /** + @summary Re-render an item. + @param {any} item - the updated item + @description + Signal that a given item has been updated and need to be re-rendered if visible. + */ + updateItem(item) { + const k = this.getIndexOf(item); + if ( 0 <= k ) this.updateIndex(k); + } + + /** + @summary Re-render a range of items. + @param {number} first - the first updated item index + @param {number} [last] - the last updated item index (defaults to `first`) + @description + Signal that a range of items have been updated and need to be re-rendered if visible. + */ + updateIndex(a,b=a) { + _.forOwn(this._dome_clients,({ lower,upper,trigger }) => { + if ( a <= upper && lower <= b ) trigger(); + }); + } + + /** Re-render all items */ + reload() { _.forOwn(this._dome_clients,({trigger})=> trigger()); } + + /** + @summary Current ordering. + @return {object} current sorting order + @description + Shall return the current ordering `{ sortBy, sortDirection }` + for user feedback in table headers, and `undefined` for natural ordering + or no ordering at all. + <p> + Default implementation returns `undefined`. + */ + getOrdering() { return undefined; } + + /** + @summary Change ordering of the model. + @param {object} [sort] - sorting order + @description + Callback to user clicks on table headers. This method receives + the new `{ sortBy, sortDirection }` ordering requested by the user action, + of `undefined` to reset initial, natural ordering of items. + You can also invoke this method on your own, away from any table view. + <p> + The method shall eventually reorder the items internally, and finally + signal completion with a call to `Model.reload()` in order to sync the views. + If re-ordering can take a while, this shall be performed asynchronously. + <p> + Default implementation does nothing. + */ + setOrdering() { } + + /** + @summary Connect a trigger to the model. + @protected + @param {Function} trigger - callback to force table update + @return {ClientID} client identifier + @description + Returns a _client_ identifier for removing and watching. + The trigger function is called for each update watched by the _client_. + Initially, the watching range is empty. + */ + _bind(trigger) { + const client = "#" + this._dome_clientId++ ; + this._dome_clients[client] = { lower:0, upper:0, trigger }; + return client; + } + + /** + @summary Disconnect the _client_ from the model. + @protected + @param {ClientID} client - the identifier of the client to disconnect + */ + _remove(client) { + delete this._dome_clients[client]; + } + + /** + @summary Set the current range of items watched by the _client_. + @protected + @param {ClientID} client - the identifier of the client to disconnect + @param {number} first - first index of the range + @param {number} last - last index of the range + @description + Data updates tha fall outside this range will _not_ trigger + re-rendering of the client. + */ + _watch(client,a,b) { + const listener = this._dome_clients[client]; + if (listener) { listener.lower = a ; listener.upper = b; } + } + +} + +// -------------------------------------------------------------------------- + +export default { Model , ASC , DESC } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/table/tables.css b/Ivette/src/dome/src/renderer/table/tables.css new file mode 100644 index 00000000000..bf732426f38 --- /dev/null +++ b/Ivette/src/dome/src/renderer/table/tables.css @@ -0,0 +1,121 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling Dome Tables --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xTable { + flex: 1 1 auto ; + width: 100% ; + height: 100% ; +} + +.dome-xTable * { + outline: none ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Table Headers --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xTable .ReactVirtualized__Table__headerRow { + display: flex ; + align-items: stretch ; + background: #eee ; + color: #555 ; + fill: #777 ; +} + +.dome-xTable .ReactVirtualized__Table__headerColumn { + overflow: hidden ; + padding-left: 4px ; + padding-right: 4px ; + margin: 0px ; /* Necessary for column alignement */ + border-color: #cfcfcf ; + border-bottom-width: 1px ; + border-bottom-style: solid ; +} + +.dome-xTable .ReactVirtualized__Table__headerColumn:not(:last-child) { + border-right-width: 1px ; + border-right-style: solid ; +} + +.dome-xTable-header { + /* flex: is inlined by react-virtualized */ + /* height: must be kept in sync with table.js */ + display: flex ; + height: 22px ; + flex-flow: row no-wrap ; + align-items: center ; +} + +.dome-xTable-header-icon { + flex: 0 0 auto ; + margin-left: 3px ; + margin-right: 3px ; +} + +.dome-xTable-header-label { + flex: 1 1 auto ; + overflow: hidden ; + margin-left: 3px ; + margin-right: 3px ; +} + +.dome-xTable-header-sorter { + flex: 0 0 auto ; + margin-right: 2px ; +} + +.dome-xTable-resizer { + position: absolute ; + cursor: col-resize ; + width: 3px ; + top: 0px ; + bottom: 0px ; + z-index: 1 ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Table Rows --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xTable .ReactVirtualized__Table__row { + display: flex ; + align-items: stretch ; +} + +.dome-xTable .ReactVirtualized__Table__rowColumn { + /* flex: is inlined by react-virtualized */ + /* height: must be kept in sync with table.js */ + display: block ; + position: relative ; + margin: 0 ; /* Necessary for column alignement */ + padding-top: 3px ; + padding-left: 4px ; + padding-right: 4px ; + vertical-align: baseline ; +} + +.dome-xTable-odd { + background: #fdfdfd ; +} + +.dome-xTable-even { + background: #efefef ; +} + +.ReactVirtualized__Table__row.dome-color-selected { + border-bottom-style: solid ; + border-bottom-width: 1px ; +} + +/* -------------------------------------------------------------------------- */ +/* --- Styling Table Cells --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xTable-cell { + display: block ; + position: relative ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/table/views.js b/Ivette/src/dome/src/renderer/table/views.js new file mode 100644 index 00000000000..637add9f45e --- /dev/null +++ b/Ivette/src/dome/src/renderer/table/views.js @@ -0,0 +1,552 @@ +// -------------------------------------------------------------------------- +// --- Tables +// -------------------------------------------------------------------------- + +/** @module dome/table/views */ + +import React from 'react' ; +import { DraggableCore } from 'react-draggable'; +import { SVG } from 'dome/controls/icons' ; +import { + AutoSizer, + SortDirection, + Table as VTable, + Column as VColumn +} from 'react-virtualized' ; +import _ from 'lodash' ; +import './tables.css' ; + +// -------------------------------------------------------------------------- +// --- Header Renderer +// -------------------------------------------------------------------------- + +const headerRowRenderer = + (onDoubleClick) => + // Borrowed from react-virtualized Table.defaultHeaderRowRenderer + ({ + className, + columns, + style + }) => ( + <div role="row" + className={className} + style={style} + onDoubleClick={onDoubleClick} > + {columns} + </div> + ); + +const headerIcon = (icon) => ( + icon && <div className='dome-xTable-header-icon'><SVG id={icon}/></div> +); + +const headerLabel = (label) => ( + label && <label className='dome-xTable-header-label dome-text-label'> + {label} + </label> +); + +const makeSorter = (id) => ( + <div className='dome-xTable-header-sorter'> + <SVG id={id} size={8}/> + </div> +); + +const headerSorter = {} ; +headerSorter[ SortDirection.ASC ] = makeSorter('ANGLE.UP'); +headerSorter[ SortDirection.DESC ] = makeSorter('ANGLE.DOWN'); + +const headerRenderer = + ({ + columnData: { label, icon, title, headerRef }, + dataKey, + sortBy, + sortDirection + }) => { + const sorting = dataKey === sortBy ; + const tooltip = title || label ; + const onRef = (elt) => headerRef(dataKey,elt) ; + return ( + <div className='dome-xTable-header' title={tooltip} ref={onRef} + > + { headerIcon(icon) } + { headerLabel(label) } + { sorting && headerSorter[sortDirection] } + </div> + ); + }; + +// -------------------------------------------------------------------------- +// --- Cell Renderer +// -------------------------------------------------------------------------- + +const cellDataGetter = + (getValue) => + ({ rowData:{ model , item }, dataKey:id }) => + ( item == undefined ? undefined : + getValue ? getValue(item) : + model.getValue(item,id) + ); + +const cellRenderer = + (renderValue) => + ({ cellData: data }) => + ( + data === undefined ? undefined : + renderValue ? renderValue(data) : + (<div className='dome-xTable-cell dome-text-data'>{data}</div>) + ); + +// -------------------------------------------------------------------------- +// --- Column Resizer +// -------------------------------------------------------------------------- + +const DRAGGING = 'dome-xTable-resizer dome-color-dragging' ; +const DRAGZONE = 'dome-xTable-resizer dome-color-dragzone' ; + +const Resizer = (props) => ( + <DraggableCore + onStart={props.onStart} + onStop={props.onStop} + onDrag={(_elt,data)=> props.onDrag(props.left,props.right,data.x - props.offset)} + > + <div + className={ props.id === props.dragging ? DRAGGING : DRAGZONE } + style={{ left: props.offset-2 }} + /> + </DraggableCore> +); + +const computeWidth = (elt) => { + const parent = elt && elt.parentElement ; + return parent && parent.getBoundingClientRect().width ; +}; + +// -------------------------------------------------------------------------- +// --- Table Columns +// -------------------------------------------------------------------------- + +/** + @class + @summary Table Column. + @property {string} id - Column unique identifier (required) + @property {string} [icon] - Header icon + @property {string} [label] - Header label + @property {string} [title] - Header tooltip + @property {string} [align] - Column alignment (`'left'`, `'center'`, `'right'`) + @property {number} [width] - Column base width (in pixels, default `60`) + @property {boolean} [fill] - Extensible column (not by default) + @property {boolean} [fixed] - Non-resizable column (not by default) + @property {boolean} [disableSort] - Do not trigger sorting callback for this column + @property {function} [getValue] - Obtain an item's value for this column + @property {function} [renderValue] - Render item's value in each table cell + @description + + Each column displays a specific value derived from the item displayed in a + row. Column properties enforce a separation between how to extract the value + from an item and how to render it in the cell. + + - `getValue(item) : any` shall returns the value to render for the _item_ + - `renderValue(any) : Element` shall returns the (React) element to display the item + + + By default, values are obtained from the underlying model by invoking + [Model.getValue](module-dome_table_models.Model.html#getValue) with the column + identifier. + + The default `renderValue` renders the item's value + packed in a `<label>` with class `dome-text-data` as described in the + [Styling Component](tutorial-styling.html) tutorial. + + This separation of concerns allows for defining + Column types, where for instance the renderer is already defined and you only need to + know how to extract the expected value of items. + See [DefineColumn](module-dome_table_views.DefineColumn.html) + for more informations and examples. + + A table should have at least one extensible column to occupy the available width. + If no column in the table is explicitely declared to be extensible, the last + one would be implicitely set to fill. + +*/ +export const Column = () => null; +// Fake component only used to store props. +// Virtualized column is rendered with function below: +const vColumn = (columnResize,headerRef,hasFill,lastElt) => (elt) => { + const defaults = elt.type._DOME_COLUMN_DEFAULTS || {} ; + const forcers = !hasFill && elt == lastElt ? { fill:true } : {} ; + const { id,label,title,icon,align,width,fill,disableSort,getValue,renderValue } + = Object.assign( defaults , elt.props , forcers ) ; + return ( + <VColumn + displayName='React-Virtualized-Column' + width={columnResize[id] || width || 60} + flexGrow={ fill ? 1 : 0 } + dataKey={id} + columnData={{label,title,icon,headerRef}} + headerRenderer={headerRenderer} + cellRenderer={cellRenderer(renderValue)} + cellDataGetter={cellDataGetter(getValue)} + headerStyle={{ textAlign: align }} + disableSort={disableSort} + style={{ textAlign: align }} + /> + ); +}; + +// -------------------------------------------------------------------------- +// --- Specific Columns +// -------------------------------------------------------------------------- + +/** + @class + @summary Define specific Column instances. + @param {Object} properties - default Column properties + @return {Column} a new Column class of Component + @description + + Allow to define specialized instances of + [Column](module-dome_table_views.Column.html) + + @example // Example of column type + import { DefineColumn } from 'dome/table/views' ; + export const ColumnCheck = DefineColumn({ + align: 'center', + renderValue: (ok) => <Icon id={ok ? 'CHECK' : 'CROSS'}/> + }); + + @example // Usage in a Table + <Table ...> + <Column id='name' label='Name' fill /> + <ColumnCheck id='check' label='Checked' /> + </Table> + + */ +export const DefineColumn = (DEFAULTS) => { + const Component = () => null; + Component._DOME_COLUMN_DEFAULTS = DEFAULTS ; + return Component ; +}; + +// -------------------------------------------------------------------------- +// --- Table Rows +// -------------------------------------------------------------------------- + +const rowClassName = + (multipleSelection,selected) => + ({index}) => + (multipleSelection + ? 0 <= _.sortedIndexOf( selected , index ) + : (index === selected)) + ? 'dome-color-selected' : + index & 1 ? 'dome-xTable-even' : 'dome-xTable-odd' ; + +// -------------------------------------------------------------------------- +// --- Table View +// -------------------------------------------------------------------------- + +// Must be kept in sync with table.css +const CSS_HEADER_HEIGHT = 22 ; +const CSS_ROW_HEIGHT = 20 ; + +/** + @class + @summary Table View. + @property {Model} model - table data proxy (required) + @property {Column[]} children - one or more table columns (required) + @property {any} [selection] - current selection (depends on `multipleSelection`) + @property {function} [onSelection] - callback to selection changes (depends on `multipleSelection`) + @property {boolean} [multipleSelection] - select single or multiple selection + @property {any} [scrollToItem] - ensures the item is visible + @property {function} [renderEmpty] - callback to render an empty table + @description + + This component is base on [React-Virtualized + Tables](https://bvaughn.github.io/react-virtualized/#/components/Table), + offering a lazy, super-optimized rendering process that scales on huge + datasets. + + A table shall be connected to an instance of + [Model](module-dome_table_models.Model.html) class to retrieve the data and + get informed of data updates. + + The table columns shall be instances of + [Column](module-dome_table_views.Column.html) class. + + Clicking on table headers trigger re-ordering callback on the model with the + expected column and direction, unless disabled _via_ the column + specification. However, actual sorting (and corresponding feedback on table + headers) would only take place if the model supports re-ordering and + eventually triggers a reload. Double clicking the table headers resets + re-ordering to natural order, with the same considerations. + + Tables do not control item selection state. Instead, you shall supply the selection + state and callback _via_ properties, like any other controlled React components. + + Item selection can be based either on single-row or multiple-row. In case of + single-row selection (`multipleSelection:false`, the default), selection state + must be a single item or `undefined`, and the `onSelection` callback is called + with the same type of values. + + In case of multiple-row selection (`multipleSelection:true`), the selection state + shall be an _array_ of items, and `onSelection` callback also. Single items are _not_ + accepted, but `undefined` selection can be used in place of an empty array. + + Clicking on a row triggers the `onSelection` callback with the updated selection. + In single-selection mode, the clicked item is sent to the callback. In + multiple-selection mode, key modifiers are taken into account for determining the new + slection. By default, the new selection only contains the clicked item. If the `Shift` + modifier has been pressed, the current selection is extended with a range of items + from the last selected one, to the newly selected one. If the `CtrlOrCmd` modifier + has been pressed, the selection is extended with the newly clicked item. + Clicking an already selected item with the `CtrlOrCmd` modifier removes it from + the current selection. + + */ +export class Table extends React.Component { + + constructor(props) + { + super(props); + + // Table Reload + this.tableRef = undefined ; + this.setTableRef = (ref) => this.tableRef = ref ; + this.reloadTable = () => { + this.reloaded = true ; + this.forceUpdate(); + const ref = this.tableRef ; + ref && ref.forceUpdateGrid(); + }; + + // Model Watching + this.watchModel = ({startIndex,stopIndex}) => { + this.props.model._watch( this.client , startIndex , stopIndex ); + }; + + // Header Double Click + this.resetOrdering = () => this.props.model.setOrdering() ; + + // Header Column References + this.columnSize = {} ; + this.headerRef = (id,elt) => { + const old = this.columnSize[id]; + const fixed = this.columnResize[id]; + const width = computeWidth(elt); + if (elt && old !== width) { + this.columnSize[id] = width ; + this.forceUpdate(); + } + }; + + // Column Resizing + this.columnResize = {} ; + this.resizeColumns = (lcol,rcol,delta) => { + const wl = this.columnSize[lcol] + delta ; + const wr = this.columnSize[rcol] - delta ; + if (wl > 40 && wr > 40) { + this.columnResize[lcol] = wl ; + this.columnResize[rcol] = wr ; + this.forceUpdate(); + } + }; + + // Selection + this.selectRow = this.selectRow.bind(this); + + } + + // --- Life Cycle (binding to model) + + componentDidMount() + { + this.client = this.props.model._bind(this.reloadTable); + } + + componentWillUnmont() + { + this.props.model._remove(this.client); + } + + // --- Column Resizers + + computeResizers() { + // Insert a resizer on each side of non-fixed columns, + // provided there also exists some non-fixed column on both side. + const columns = React.Children.toArray(this.props.children); + if (columns.length < 2) return null; + const resizing = columns.map( ({props:{id,fixed}}) => ({id,fixed}) ); + var k, cid ; + for (cid = undefined, k = 0; k < columns.length; k++) { + const r = resizing[k]; + r.left = cid ; + if (!r.fixed) cid = r.id ; + } + for (cid = undefined, k = columns.length-1; 0 <= k ; k--) { + const r = resizing[k]; + r.right = cid ; + if (!r.fixed) cid = r.id ; + } + var offset = 0 , resizers = [] ; + for (k = 0; k < columns.length - 1 ; k++) { + const width = this.columnSize[resizing[k].id] ; + if (!width) return null; + offset += width ; + const a = resizing[k]; + const b = resizing[k+1]; + if ((!a.fixed || !b.fixed) && a.right && b.left) { + const id = k ; + const onStart = () => { this.dragging = id ; this.forceUpdate(); }; + const onStop = () => { this.dragging = undefined ; this.forceUpdate(); }; + const resizer = ( + <Resizer key={id} + id={id} + dragging={this.dragging} + onStart={onStart} + onStop={onStop} + onDrag={this.resizeColumns} + offset={offset} + left={b.left} + right={a.right} /> + ); + resizers.push(resizer); + } + } + return resizers ; + } + + // --- Row Selection + + selectRow({event, index, rowData:{item}}) { + this.focus = item ; + window.getSelection().empty(); + if (item) { + const { model, multipleSelection , selection, onSelection } = this.props ; + if (multipleSelection) { + const selectedItems = + selection === undefined ? [] : + Array.isArray(selection) ? selection : + [selection] ; + if (event.metaKey || event.ctrlKey) { + var s, a ; + const isClicked = (e) => model.getIndexOf(e) === index ; + if (_.find( selectedItems , isClicked )) { + s = _.filter( selectedItems, (e) => model.getIndexOf(e) !== index ); + } else { + s = selectedItems.slice(); + s.push(item); + a = index ; + } + this.anchor = a ; + this.anchored = undefined ; + onSelection(s); + } + else if (event.shiftKey && this.anchor) { + var old = this.anchored || (this.anchored = selection) ; + var updated = old.slice(); + var anchor = this.anchor ; + var k ; + if (anchor < index) + for (k = anchor ; k <= index ; k++) { + updated.push(model.getItemAt(k)); + } + else + for (k = anchor ; index <= k ; k--) { + updated.push(model.getItemAt(k)); + } + // No anchor modification + onSelection(_.uniqBy(updated, model.getIndexOf.bind(model))); + } + else { + this.anchor = index ; + this.anchored = undefined ; + onSelection([item]); + } + } else { + onSelection(item); + } + } + } + + // --- Rendering + + render() { + + const { + model, children, renderEmpty, + multipleSelection, selection, onSelection, + scrollToItem + } = this.props ; + + const itemCount = model.getItemCount(); + const ordering = model.getOrdering(); + var selected = undefined ; + if (selection) + if (multipleSelection && Array.isArray(selection)) { + selected = selection.map((elt) => { + var k = model.getIndexOf(elt); + return Number.isInteger(k) ? k : -1 ; + }).sort((a,b) => a-b); + } else + selected = model.getIndexOf(selection); + + const rowGetter = ({index}) => ({ + model , item: (index < itemCount ? model.getItemAt(index) : undefined) + }) ; + + var hasFill = false ; + var lastElt = undefined ; + React.Children.forEach(this.props.children,(elt) => { + if (elt.props.fill) hasFill = true ; else lastElt = elt ; + }); + const SizedTable = ({ height, width }) => { + const tableHeight = CSS_HEADER_HEIGHT + CSS_ROW_HEIGHT * itemCount ; + const smallHeight = itemCount > 0 && tableHeight < height ; + const rowCount = ( smallHeight ? itemCount + 1 : itemCount) ; + const reloaded = this.reloaded ; + if (reloaded) this.reloaded = false ; + const scrollToIndex = + scrollToItem ? model.getIndexOf(scrollToItem) : + reloaded && this.focus ? model.getIndexOf(this.focus) : undefined ; + const resizers = this.computeResizers(); + return ( + <React.Fragment> + <VTable + key='table' + displayName='React-Virtualized-Table' + width={width} + height={height} + rowCount={rowCount} + noRowsRenderer={renderEmpty} + rowGetter={rowGetter} + rowClassName={rowClassName(multipleSelection,selected)} + rowHeight={CSS_ROW_HEIGHT} + headerHeight={CSS_HEADER_HEIGHT} + headerRowRenderer={headerRowRenderer(this.resetOrdering)} + onRowsRendered={this.watchModel} + onRowClick={onSelection && this.selectRow} + sortBy={ordering && ordering.sortBy} + sortDirection={ordering && ordering.sortDirection} + sort={model.setOrdering.bind(model)} + scrollToIndex={ scrollToIndex } + scrollToAlignment='center' + > + {React.Children.map(children,vColumn(this.columnResize,this.headerRef,hasFill,lastElt))} + </VTable> + {resizers} + </React.Fragment> + ); + }; + return ( + <div className='dome-xTable'> + <AutoSizer key='table'>{SizedTable}</AutoSizer> + </div> + ); + } +} + +// -------------------------------------------------------------------------- + +export default { Table, Column, DefineColumn }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/text/buffers.js b/Ivette/src/dome/src/renderer/text/buffers.js new file mode 100644 index 00000000000..be2324b3248 --- /dev/null +++ b/Ivette/src/dome/src/renderer/text/buffers.js @@ -0,0 +1,446 @@ +// -------------------------------------------------------------------------- +// --- Text Documents +// -------------------------------------------------------------------------- + +/** @module dome/text/buffers */ + +import Emitter from 'events' ; +import CodeMirror from 'codemirror/lib/codemirror.js' ; + +const combineClass = (a,b) => a ? (b ? (a + " " + b) : a) : b ; + +// -------------------------------------------------------------------------- +// --- Marker Proxy +// -------------------------------------------------------------------------- + +class Proxy { + + clear() { this.marker && this.marker.clear(); } + changed() { this.marker && this.marker.changed(); } + find() { return this.marker && this.marker.find(); } + _link(marker) { this.marker = marker ; } + +} + +// -------------------------------------------------------------------------- +// --- Buffer +// -------------------------------------------------------------------------- + +/** + @summary Rich Text Content and State. + @description + + A buffer encapsulate a CodeMirror document instance inside an standard + Node event emitter. CodeMirror signals are automatically linked back to + the event emitter (on a lazy basis). + + The `maxlines` will control the maximum number of lines kept in the buffer. + By default, it is set to `10000`, but you can use `null`, `0` or any negative + value to disable this behavior. See also `this.setMaxlines()` method. + + Additionnaly, a Buffer maintains an _edited_ state internally that can + be manually updated, and that is automatically set to `true` when the + underlying CodeMirror document is changed. It is associated to an `'edited'` + event of the buffer, and can be used to manage the « Saved » / « Not-Saved » + state of an editor, for instance. + + Typically, a sequence of changed events would fire a unique `'edited'` buffer + event, untill `setEdited(false)` is invoked. The `clear()` method also resets + the _edited_ state to `false`, but sill emit an `'edited'` event if the + buffer was not empty. + + Buffers can also be updated programmatically by various methods. In addition to + specified CodeMirror modes, you can also attach text markers programmatically with + a push/pop API. + + Text markers can be associated with an identifier, that can be used for + dynamic highlighting, called Decorations. Decorations are class names that + add styling attributes upon the current mode. Typically, consider only using + background colors, underlines and/or strike-through for decorations, since + font styles and colors are likely to be managed by CodeMirror modes, unless + you know exactly what your are doing. + + The `setDecorator` method can be used to set or update + the highlighting function that computes the decoration of a text marker + from its identifier. When the decorations may have change, you shall either + set again the highlighting function with a call to `setDecorator()` or call + the `updateDecorations()` method. This also triggers the `'decorated'` event. + + */ + +export class Buffer extends Emitter { + + /** + @param {object} [props] - Constructor properties (see below) + @param {string | object} [props.mode] - CodeMirror [mode](https://codemirror.net/mode/index.html) specification + @param {number} [props.maxlines] - Maximum number of lines in the buffer + */ + constructor(props = {}) { + super(); + const { mode , maxlines } = props ; + this._doc = new CodeMirror.Doc('',mode); + this._stacked = [] ; + this._edited = false ; + this._focused = false ; + this._markid = 0 ; + this._markers = {} ; + this._decorator = undefined ; + this.setMaxlines(maxlines); + this.setEdited = this.setEdited.bind(this); + this.setFocused = this.setFocused.bind(this); + this.clear = this.clear.bind(this); + this.append = this.append.bind(this); + this.log = this.log.bind(this); + this._doc.on('change', ( _target , { origin } ) => { + if (origin !== 'buffer') this.setEdited(true); + }); + } + + /** + @summary CodeMirror document instance. + @return {CodeMirror.Doc} internal [document](https://codemirror.net/doc/manual.html#api_doc) + @description + Returns the `CodeMirror.Doc` instance holding the buffer contents. + This can be used for further customization. + <p> + This document will never be bound to a `CodeMirror` instance. Instead, `Text` views + will use _linked_ documents to the buffer one. This allows for several views to + share the same document (and history). + */ + getDoc() { return this._doc; } + + // -------------------------------------------------------------------------- + // --- Buffer Manipulation + // -------------------------------------------------------------------------- + + /** Clear buffer contents and resets _edited_ state. */ + clear() { + this._doc.setValue(''); + this._edited = false; + this._stacked = [] ; + this._focused = false ; + this._markid = 0 ; + this._markers = {} ; + } + + /** + @summary Writes in the buffer. + @param {any} [value] - content to append in the buffer + @description + Appends textual contents to the end of the buffer. + All parameters are converted to string and joined with spaces. + The generated change event has origin `'buffer'` and it does not + modifies the _edited_ internal state. + */ + append(...value) { + if (value.length > 0) { + const doc = this._doc ; + const from = doc.posFromIndex(Infinity); + const text = value.join(' '); + doc.replaceRange(text,from,undefined,'buffer'); + this.shrink(); + } + } + + /** + @summary Appends with newline and auto-scrolling. + @param {any} [value] - content to append in the buffer + @description + This is a short-cut to `append(...value)`, followed by + `append('\n')` and `scroll()`. + */ + log(...value) { + this.append(...value); + this.append('\n'); + this.scroll(); + } + + /** + @summary Opens a text marker. + @param {object} options - CodeMirror + [text marker](https://codemirror.net/doc/manual.html#api_marker) options + @return {CodeMirror.TextMarker} the associated + [text marker](https://codemirror.net/doc/manual.html#api_marker) (proxy) + @description +Opens a text marker at the current (end) position in the buffer. + +The text marker is stacked and would be actually created on the +matching `closeTextMarker()` call. It will be applied to the full range of text +inserted between its associated `openTextMarker()` and `closeTextMarker()` calls. + +The returned text marker is actually a _proxy_ to the text marker that +will be eventually created by `closeTextMarker()`. Its methods (`find`, `clear` and `changed`) +are automatically forwarded to the actual `CodeMirror.TextMarker` instance, once created. +Hence, you can safely invoke these methods on either the _proxy_ or the _final_ +text marker at your convenience. + +Additionnaly to standard `CodeMirror.TextMarker` options, you may also the +following Dome specific ones: +- `id: string` assigns an identifier to the marker (expected to be unique) ; +- `hover: boolean` makes the text-marker highlighted on mouse-hover ; this is compatible with + _nested_ markers, which is not possible with CSS `:hover` pseudo selectors ; defaults to `true` for + identified text markers and `false` otherwize. +*/ + + openTextMarker( { id , hover, className, ...options } ) { + const from = this._doc.posFromIndex(Infinity); + const proxy = new Proxy(); + this._stacked.push( { from , id , hover, className, options , proxy } ); + return proxy ; + } + + /** + @summary Close last opened marker. + @return {CodeMirror.TextMarker} the (actual) + [text marker](https://codemirror.net/doc/manual.html#api_marker) + @description + Closes the lastly opened text marker with `openTextMarker()`. + The method returns the _actual_ + text marker ; the _proxy_ text marker provided by the corresponding + call to `openTextMarker()` is automatically bound to the actual one. + */ + closeTextMarker() { + const tag = this._stacked.pop(); + if (tag) { + const { id, hover, from } = tag ; + const to = this._doc.posFromIndex(Infinity); + var classNameWithId ; + var tagid ; + if ( id || hover ) { + const mhover = hover !== undefined ? hover : (id !== undefined) ; + const cid = id ? 'dome-xMark-' + id : ('dome-xHover-' + (++this._markid)) ; + const p = this._doc.indexFromPos(from); + const q = this._doc.indexFromPos(to); + const m = this._markers[cid]; + if (m) console.warn('[Dome.text.buffers] duplicate marker',id); + tagid = this._markers[cid] = { id, hover:mhover, classNameId:cid, length: q-p } ; + classNameWithId = id ? "dome-xMarked " + cid : cid ; + } + const className = combineClass( tag.className, classNameWithId ); + const options = Object.assign( { shared:true, className } , tag.options ); + const marker = this._doc.markText( from , to , options ); + tag.proxy._link(marker); + if (tagid) tagid.marker = marker ; + this.shrink(); + return marker ; + } else + return undefined ; + } + + /** + @description Lookup a text marker + @param {string} id - requested identifier + @return {CodeMirror.TextMarker} the identified text marker, or `undefined` if not found. + */ + findTextMarker(id) { + if (id) { + const m = this._markers['dome-xMark-' + id] ; + if (m) return m.marker ; + } + return undefined; + } + + /** + @summary Lookup a hover class. + @param {string} className - a class name, possibly identifying a hover element + @return {hover} the associated hovered element `{id, classNameId, length}`, or + `undefined` if the provided `className` does not identify any such element. + */ + findHover(name) { return this._markers[name]; } + + // -------------------------------------------------------------------------- + // --- Highlighter + // -------------------------------------------------------------------------- + + /** + @summary Define highlighter. + @param {function} highlighter - the function that computes + the decoration class of a marker id. + */ + setDecorator(f) { this._decorator = f ; this.emit('decorated'); } + + /** + @summary Current highlighter. + @return {function} the current highlighting function + */ + getDecorator() { return this._decorator ; } + + /** + @summary Rehighlight document. + @description + Emits the `'decorated'` event to make editors + updating the decorations of identified text markers. + */ + updateDecorations() { this.emit('decorated'); } + + // -------------------------------------------------------------------------- + // --- Edited State + // -------------------------------------------------------------------------- + + /** + @summary Set edited state. + @param {boolean} [state] - the new edited state (defaults to `true`). + @description + +Set the _edited_ internal state. The method is automatically invoked by editor +views when the user actually edit the document. The state is _not_ modified +when modifying the document from buffer's own methods, _eg._ `append()` and +`clear()`. + +The method fires the `'edited'` event on modifications. This method is bound to +`this`, hence `this.setEdited` can be used as a valid callback function. + */ + setEdited(state = true) { + if ( state !== this._edited ) { + this._edited = state ; + this.emit('edited',state); + } + } + + /** + @summary Set focused state. + @param {boolean} [focus] - the new focused state (defaults to `true`). + @description + +Set the _focused_ internal state. The method is automatically invoked by editor +views when they gain or lose focus or when the user actually interact with the +view, eg. mouse-scrolling, edition, cursor move, etc. The escape key `ESC` +explicitly relax the _focused_ state, although the editor view might actually +keep the _focus_. + +When a buffer is _focused_, shrinking and scrolling are temporarily deactivated +to avoid confusing user's experience. + +The method fires `'focused'` events on modifications. This method is bound to +`this`, hence `this.setEdited` can be used as a valid callback function. + */ + setFocused(state = true) { + if ( state !== this._focused ) { + this._focused = state ; + this.emit('focused',state); + this.shrink(); + } + } + + /** Returns the current _edited_ state. */ + isEdited() { return this._edited; } + + /** Returns the current _focused_ state. */ + isFocused() { return this._focused; } + + // -------------------------------------------------------------------------- + // --- Document Scrolling + // -------------------------------------------------------------------------- + + /** + @summary Set (or unset) the maximum number of lines. + @param {number} [maxlines] - maximum number of lines + @description + +By default, the maximum number of lines is set to `10,000` to avoid +unwanted memory leaks. Setting `null`, `0` of any negative value cancel +the management of maximum number of lines. + +Although CodeMirror is powerfull enough to manage huge buffers, +you should turn this limit _off_ with care. + */ + setMaxlines(maxlines=10000) { + this._maxlines = maxlines > 0 ? 1 + maxlines : 0 ; + this.shrink(); + } + + /** + @summary Remove head lines to fits into maximum lines. + @description + +Shrinking is activated when `maxlines` property is set to a strictly +positive number. When the number of lines in the buffer is larger than +the max, buffer is trimmed by removing extra _heading_ lines. + +When the buffer if _focused_ or when there are still opened text marks pending, +shrinking is automatically postponed until focus is lost and all pending marks +have been closed. + */ + shrink() + { + if (!this._focused && this._maxlines > 0 && this._stacked.length == 0) { + const lines = this._doc.lineCount(); + if (lines > this._maxlines) { + const p = this._doc.firstLine(); + const q = p + lines - this._maxlines ; + this._doc.replaceRange('',{line:p,ch:0},{line:q,ch:0},'buffer'); + } + } + } + + /** + @summary Requires all connected views to scroll to the specified position in the buffer. + @param {...any} [args] - the position or range to be made visible + @description +Typical usage: + - `scroll()` to the end of buffer + - `scroll(id)` to identified marked `id`; + - `scroll(p)` a position: line number or `{line,ch?}` CodeMirror position; + - `scroll(p,q)` a range of two positions (like above); + - `scroll({from,to})` an object range of two positions (like above). + +When the buffer is _focused_, programmatic scrolling is blocked. + */ + scroll(a,b) { + if (this._focused) return; + switch(typeof(a)) { + case 'undefined': + this.emit('scroll',{line:this._doc.lastLine(),ch:0}); + break; + case 'string': + const tm = this.findTextMarker(a); + const rg = tm.find(); + if (rg) this.emit('scroll',rg); + break; + default: + const isLineCh = (a) => ( + a && Number.isInteger(a.line) + && (a.ch === undefined || Number.isInteger(a.ch)) + ); + const getPos = (a) => ( + Number.isInteger(a) ? { line: a, ch:0 } : + isLineCh(a) ? a : console.warn('[Dome.text.buffers] can not scroll to',a) + ); + var from,to ; + if (a && a.from && a.to) { + from = getPos(a.from); + to = getPos(a.to); + } else { + from = getPos(a); + to = b && getPos(b); + } + if (from && to) this.emit('scroll',{from,to}); + else if (from) this.emit('scroll',from); + } + } + + // -------------------------------------------------------------------------- + // --- Document Linking + // -------------------------------------------------------------------------- + + /** + @summary Linked CodeMirror document. + @description + Returns a CodeMirror document linked to this buffer (with shared history). + */ + linkedDoc() { return this._doc.linkedDoc( { sharedHist: true } ); } + + /** + @summary Release a linked CodeMirror document. + @description + Unlinks a CodeMirror document obtained by `linkedDoc()`. + */ + unlinkDoc(doc) { this._doc.unlinkDoc( doc ); } + +} + +// -------------------------------------------------------------------------- + +export default { Buffer }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/src/renderer/text/editors.css b/Ivette/src/dome/src/renderer/text/editors.css new file mode 100644 index 00000000000..3a15484d39d --- /dev/null +++ b/Ivette/src/dome/src/renderer/text/editors.css @@ -0,0 +1,28 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling Code Editors --- */ +/* -------------------------------------------------------------------------- */ + +.dome-xText { + flex: 1 1 auto ; + overflow: hidden ; + position: relative ; +} + +.dome-xText .CodeMirror { + width: 100% ; + height: 100% ; +} + +.dome-xText-hover { + background: lightgreen ; +} + +.dome-xText-select { + background: #ffda95 !important ; +} + +.dome-xText-select.dome-xText-hover { + background: orange !important ; +} + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/src/dome/src/renderer/text/editors.js b/Ivette/src/dome/src/renderer/text/editors.js new file mode 100644 index 00000000000..415c3a442bb --- /dev/null +++ b/Ivette/src/dome/src/renderer/text/editors.js @@ -0,0 +1,375 @@ +// -------------------------------------------------------------------------- +// --- Text Documents +// -------------------------------------------------------------------------- + +/** @module dome/text/editors */ + +import React from 'react' ; +import Dome from 'dome' ; +import CodeMirror from 'codemirror/lib/codemirror.js' ; +import 'codemirror/lib/codemirror.css' ; +import './editors.css' ; +import _ from 'lodash' ; + +const CSS_HOVERED = 'dome-xText-hover' ; +const CSS_SELECTED = 'dome-xText-select' ; + +// -------------------------------------------------------------------------- +// --- Text View +// -------------------------------------------------------------------------- + +/** + @class + @summary Rich Text Editor. + @property {Buffer} buffer - + associated [Buffer](module-dome_text_buffers.Buffer.html) holding the text content + @property {string} selection - currently selected markder identifier + @property {function} onSelection - callback used when an identified marker is clicked + @property {object} [...options] - additional CodeMirror + [configuration](https://codemirror.net/doc/manual.html#config) properties + @description + + A component rendering the content of a text buffer, that shall be instances + of the [Buffer](module-dome_text_buffers.Buffer.html) base class. + + The view is based on a [CodeMirror](https://codemirror.net) component linked with + the internal Code Mirror Document from the associated buffer. + + Multiple views might share the same buffer as source content. The buffer will be + kept in sync with all its linked views. + + The Text component never update its mounted NODE element, however, all property + modifications (including buffer) are propagated to the internal CodeMirror instance. + Undefined properties are set (or reset) to the CodeMirror defaults. + + ##### Themes + + The CodeMirror `theme` option allow you to style your document, + especially when using modes. + Themes are only accessible if you load the associated CSS style sheet. + For instance, to use the `'ambiance'` theme provided with CodeMirror, you shall + import `'codemirror/theme/ambiance.css'` somewhere in your application. + + ##### Modes & Adds-On + + You can install modes and adds-on provided by the CodeMirror distribution by + simply importing (once, before being used) the associated modules in your + application. For instance, to use the `'javascript'` mode option, you shall + import `'codemirror/mode/javascript/javascript.js'` file in your application. + + ##### Further Customization + + You can register your own extensions directly into the global `CodeMirror` + class instance. However, the correct instance must be retrieved by using + `import CodeMirror from 'codemirror/lib/codemirror.js'` ; using `from + 'codemirror'` returns a different instance of `CodeMirror` class and will + not work. + + */ + +export class Text extends React.Component { + + constructor(props) { + super(props); + this.mountPoint = this.mountPoint.bind(this); + this.refresh = this.refresh.bind(this); + this.autoRefresh = this.autoRefresh.bind(this); + this.onBlur = this.onBlur.bind(this); + this.onFocus = this.onFocus.bind(this); + this.onScroll = this.onScroll.bind(this); + this.onClick = this.onClick.bind(this); + this.onMouseMove = this.onMouseMove.bind(this); + this.handleKey = this.handleKey.bind(this); + this.handleUpdate = this.handleUpdate.bind(this); + this.handleHover = _.throttle(this.handleHover,50); + this.handleScrollTo = this.handleScrollTo.bind(this); + this.rootElement = undefined ; + this.decorations = {} ; + this.hover = undefined ; + } + + // -------------------------------------------------------------------------- + // --- Mounting + // -------------------------------------------------------------------------- + + mountPoint(elt) { + this.rootElement = elt ; + if (elt) { + // Mounting... + const { buffer , ...config } = this.props ; + const value = buffer ? buffer.linkedDoc() : "" ; + const cm = this.codeMirror = new CodeMirror(elt, { value }); + // Passing all options to constructor does not work (Cf. CodeMirror's BTS) + for (var opt in config) cm.setOption( opt , config[opt] ); + cm.on('update',this.handleUpdate); + cm.on('keyHandled',this.handleKey); + buffer.on('decorated',this.handleUpdate); + buffer.on('scroll',this.handleScrollTo); + Dome.on('dome.update',this.refresh); + this.refreshPolling = setInterval( this.autoRefresh, 250 ); + this.handleUpdate(); + } else { + // Unmounting... + const polling = this.refreshPolling ; + if (polling) { + clearInterval( polling ); + this.refreshPolling = undefined ; + } + const cm = this.codeMirror ; + Dome.off('dome.update',this.refresh); + const { buffer } = this.props ; + if (cm && buffer) { + buffer.unlinkDoc(cm.getDoc()); + buffer.off('decorated',this.handleUpdate); + buffer.off('scroll',this.handleScrollTo); + } + this.codeMirror = undefined ; + } + } + + // -------------------------------------------------------------------------- + // --- Auto Refresh + // -------------------------------------------------------------------------- + + refresh() { + const elt = this.rootElement ; + const cm = this.codeMirror ; + if (cm && elt) { + this.currentWidth = elt.offsetWidth ; + this.currentHeight = elt.offsetHeight ; + this.currentParent = elt.offsetParent ; + cm.refresh(); + } + } + + // Polled every 250ms + autoRefresh() { + const elt = this.rootElement ; + const cm = this.codeMirror ; + if (cm && elt) { + const eltW = elt.offsetWidth ; + const eltH = elt.offsetHeight ; + const eltP = elt.offsetParent ; + if (eltW !== this.currentWidth || + eltH !== this.currentHeight || + eltP !== this.currentParent) + { + this.currentWidth = eltW ; + this.currentHeight = eltH ; + this.currentParent = eltP ; + cm.refresh(); + } + } + } + + // -------------------------------------------------------------------------- + // --- Hover + // -------------------------------------------------------------------------- + + _findHover(elt) { + const buffer = this.props.buffer ; + var best = undefined ; + elt.classList.forEach((name) => { + const hover = buffer.findHover(name); + if (hover && (!best || hover.length < best.length )) best = hover ; + }); + return best; + } + + _findDecoration(classes,buffer,decorator) + { + var best_hover = undefined ; + var best_decor = undefined ; + var best_decoration = undefined ; + classes.forEach((name) => { + + const hover = buffer.findHover(name); + var decoration = hover && hover.id && decorator(hover.id); + + if (hover && (!best_hover || hover.length < best_hover.length)) + best_hover = hover ; + + if (decoration && (!best_decor || hover.length < best_decor.length)) { + best_decor = hover ; + best_decoration = decoration ; + } + + }); + return best_hover && { classNameId: best_hover.classNameId , decoration: best_decoration } ; + } + + _markElementsWith(classNameId,className) { + const root = this.rootElement ; + const tohover = root && root.getElementsByClassName(classNameId); + const n = tohover ? tohover.length : 0 ; + for (var k = 0; k < n; k++) tohover[k].classList.add(className); + } + + _unmarkElementsWith(className) { + const root = this.rootElement ; + const hovered = root && root.getElementsByClassName(className); + const n = hovered ? hovered.length : 0 ; + if (n==0) return ; + const elts = new Array(n); ; + for (var k = 0; k < n; k++) elts[k] = hovered[k]; + elts.forEach((elt) => elt.classList.remove(className)); + } + + handleHover(target) { + // Throttled (see constructor) + const older = this.hover ; + const hover = this._findHover(target); + if (older !== hover) { + if (older) this._unmarkElementsWith( CSS_HOVERED ); + if (hover && hover.hover) this._markElementsWith( hover.classNameId, CSS_HOVERED ); + this.hover = hover ; + } + } + + handleUpdate() { + const root = this.rootElement ; + const marked = root && root.getElementsByClassName('dome-xMarked'); + const n = marked ? marked.length : 0 ; + if (n==0) return; + const hover = this.hover ; + const hovered = hover && hover.hover && hover.classNameId ; + const selection = this.props.selection ; + const selected = selection && ('dome-xMark-' + selection) ; + const buffer = this.props.buffer; + const decorator = buffer.getDecorator(); + if ( !hovered && !selection && !decorator ) return; + const actual = {} ; + for (var k = 0; k < n; k++) { + const elt = marked[k]; + const classes = elt.classList ; + if (hovered && classes.contains(hovered)) classes.add( CSS_HOVERED ); + if (selected && classes.contains(selected)) classes.add( CSS_SELECTED ); + if (decorator) { + const hover = this._findDecoration(classes,buffer,decorator,hovered,selected); + if (hover) { + const prev = this.decorations[ hover.classNameId ]; + const curr = hover.decoration ; + if (prev !== curr && prev) classes.remove(prev); + if (curr) { classes.add(curr); actual[ hover.classNameId ] = curr ; } + } + } + } + this.decorations = actual ; + } + + onMouseMove(evt) { + // Not throttled (can not leak Synthetic Events) + this.handleHover( evt.target ); + } + + onClick(evt) { + // No need for throttling + const target = evt.target ; + const onSelection = this.props.onSelection ; + if ( target && onSelection ) { + const hover = this._findHover(target); + if ( hover && hover.id ) onSelection( hover.id ); + } + this.props.buffer.setFocused(true); + } + + // -------------------------------------------------------------------------- + // --- Scrolling + // -------------------------------------------------------------------------- + + handleScrollTo(position) { + try { + const cm = this.codeMirror; + cm && cm.scrollIntoView(position); + } catch(_error) { } // Out of range + } + + // -------------------------------------------------------------------------- + // --- Focus + // -------------------------------------------------------------------------- + + handleKey(cm,key,_evt) { + switch(key) { + case 'Esc': + this.props.buffer.setFocused(false); + break; + default: + this.props.buffer.setFocused(true); + break; + } + } + + onFocus() { this.props.buffer.setFocused(true); } + onBlur() { this.props.buffer.setFocused(false); } + onScroll() { + const cm = this.codeMirror; + if (cm) { + const rect = cm.getScrollInfo(); + const delta = rect.height-rect.top-rect.clientHeight; + const buffer = this.props.buffer; + buffer.setFocused(delta > 0); + } + } + + // -------------------------------------------------------------------------- + // --- Rendering + // -------------------------------------------------------------------------- + + shouldComponentUpdate(newProps) { + const cm = this.codeMirror ; + if (cm) { + // Swap documents if necessary + const { buffer:oldBuffer, + selection:oldSelect, + ...oldConfig } = this.props ; + const { buffer:newBuffer, + selection:newSelect, + ...newConfig } = newProps ; + if (oldBuffer !== newBuffer) { + const newDoc = newBuffer.linkedDoc(); + const oldDoc = cm.swapDoc( newDoc ); + oldBuffer.unlinkDoc( oldDoc ); + } + // Incremental update options + var opt ; + for ( opt in oldConfig ) if (!(opt in newConfig)) { + const defValue = CodeMirror.defaults[opt]; + if (defValue) + cm.setOption( opt , defValue ); + } + for ( opt in newConfig ) { + const oldValue = oldConfig[opt]; + const newValue = newConfig[opt]; + if (newValue !== oldValue) { + cm.setOption( opt , newValue ); + } + } + // Update selection + if ( oldSelect !== newSelect ) { + if (oldSelect) this._unmarkElementsWith( CSS_SELECTED ); + if (newSelect) this._markElementsWith( 'dome-xMark-' + newSelect, CSS_SELECTED ); + } + } + // Keep mounted node unchanged + return false; + } + + render() { + return ( + <div className='dome-xText' + ref={this.mountPoint} + onClick={this.onClick} + onBlur={this.onBlur} + onFocus={this.onFocus} + onScroll={this.onScroll} + onMouseMove={this.onMouseMove} + />); + } + +} + +// -------------------------------------------------------------------------- + +export default { Text }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/Application.js b/Ivette/src/dome/template/Application.js new file mode 100644 index 00000000000..f7720a2a81f --- /dev/null +++ b/Ivette/src/dome/template/Application.js @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------- +// --- Main React Component rendered by './index.js' +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/Application.js + + This module shall export a React Component that + will be rendered (with empty props and children) + in the main window of your application. + +*/ + +import React from 'react' ; +import Dome from 'dome' ; +import 'dome/misc/exports' ; + +export default (() => ( + <h1 className='dome-text-title' style={{margin: 24}}> + Hello World! + </h1> +)); diff --git a/Ivette/src/dome/template/Preferences.js b/Ivette/src/dome/template/Preferences.js new file mode 100644 index 00000000000..542d1d7c97a --- /dev/null +++ b/Ivette/src/dome/template/Preferences.js @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------- +// --- Main React Component rendered by './index.js' +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/Settings.js + + This module shall export a React Component that + will be rendered (with empty props and children) + in the settings window of your application. + +*/ + +import React from 'react' ; + +export default (() => ( + <h1 className='dome-text-title' style={{margin: 24}}> + Settings (none) + </h1> +)); diff --git a/Ivette/src/dome/template/babelrc.json b/Ivette/src/dome/template/babelrc.json new file mode 100644 index 00000000000..3e895f0c581 --- /dev/null +++ b/Ivette/src/dome/template/babelrc.json @@ -0,0 +1,21 @@ +// -------------------------------------------------------------------------- +// --- Template .babelrc configuration file for Dome +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/babelrc.json + + This configuration is a necessary extension to electron-webpack + for enabling react-hot-reloading. +*/ + +{ + "presets": [ + [ "@babel/env", { "modules": false } ], + [ "@babel/react" ] + ], + "plugins": [ + "@babel/plugin-proposal-object-rest-spread", + "react-hot-loader/babel" + ] +} diff --git a/Ivette/src/dome/template/electron-webpack.json b/Ivette/src/dome/template/electron-webpack.json new file mode 100644 index 00000000000..048484644ed --- /dev/null +++ b/Ivette/src/dome/template/electron-webpack.json @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------- +// --- Electron-webpack configuration file for Dome +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/electron-webpack.json + + This configuration file makes electron-webpack loading + webpack extensions to resolve Dome packages differently + for electron main-process and renderer-process. + + You may configure further electron-webpack to your convenience. +*/ + +{ + "main": { + "webpackConfig": "webpack.main.js" + }, + "renderer": { + "webpackConfig": "webpack.renderer.js" + } +} diff --git a/Ivette/src/dome/template/export.sh b/Ivette/src/dome/template/export.sh new file mode 100755 index 00000000000..ea5dc39d5fe --- /dev/null +++ b/Ivette/src/dome/template/export.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- +# --- Export Dome API +# -------------------------------------------------------------------------- + +DOME=$1 +COND='' +COND+=' -not -path "*/demo/*"' +COND+=' -not -name "Application.js"' +COND+=' -not -name "Preferences.js"' +COND+=' -not -name "dome.js"' +COND+=' -not -name "index.js"' + +FILES=`cd $DOME/src ; find renderer -name "*.js" $COND` + +echo "{ let m = require('react'); register('react',m); }" +echo "{ let m = require('dome'); register('dome',m); }" +echo "{ let m = require('dome/system'); register('dome/system',m); }" +for f in $FILES +do + j=${f/renderer/dome} + m=${j/.js/} + echo "{ let m = require('$m'); register('$m',m); }" +done + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/git-ignore b/Ivette/src/dome/template/git-ignore new file mode 100644 index 00000000000..ba1bdcdb1d9 --- /dev/null +++ b/Ivette/src/dome/template/git-ignore @@ -0,0 +1,14 @@ +# -------------------------------------------------------------------------- +# --- Template .gitignore file for Dome +# -------------------------------------------------------------------------- + +.dome-*.stamp +.dome-*.back +node_modules +yarn.lock +yarn-error.log +/bin +/dist +/html + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/main.js b/Ivette/src/dome/template/main.js new file mode 100644 index 00000000000..d102caa8c34 --- /dev/null +++ b/Ivette/src/dome/template/main.js @@ -0,0 +1,17 @@ +// -------------------------------------------------------------------------- +// --- Electron main-process entry-point for Dome. +// -------------------------------------------------------------------------- + +/* + Template of ./src/main/index.js + Imported from $(DOME)/template/main.js + + The call to Dome.start() will initialize the Dome application + and create the main window that will run the renderer process + from `src/renderer/index.js`. + + You may add your own code to be run in the Electron main-process + before or after the call to `Dome.start()`. +*/ + +import Dome from 'dome' ; diff --git a/Ivette/src/dome/template/makefile b/Ivette/src/dome/template/makefile new file mode 100644 index 00000000000..461cb2a1f84 --- /dev/null +++ b/Ivette/src/dome/template/makefile @@ -0,0 +1,369 @@ +# -------------------------------------------------------------------------- +# --- Main Makefile for building Dome applications +# -------------------------------------------------------------------------- + +# DOMEMK_ reserved for makefile derived variables + +APP?=$(shell basename $(PWD)) +COPYRIGHT?="CEA Tech" + +DOME?=dome +DOME_ARGS?= +DOME_EXPORTS?= +DOME_PLUGINS?= +DOME_DOC?=html/dome +DOME_APP_CLI?=bin/$(shell echo $(APP) | tr [:upper:] [:lower:]) +DOME_APP_DOC?=html/$(shell echo $(APP) | tr [:upper:] [:lower:]) +DOME_APP_SRC?=src/renderer + +# -------------------------------------------------------------------------- +# --- Makefile Help +# -------------------------------------------------------------------------- + +.PHONY: dome-help + +dome-help: + @echo + @echo "[Dome] Builtin Targets:" + @echo " make dome-help This help" + @echo " make dome-dev Run application in development mode" + @echo " make dome-app Compile application" + @echo " make dome-dist Package application for production" + @echo " make dome-doc Generate Dome documentation" + @echo " make dome-api Generate Application documentation" + @echo " make dome-pkg Install development packages" + @echo " make dome-templ Update templates" + @echo " make dome-reboot Rebuild templates from scratch" + @echo " make dome-clean Remove dome temporary files" + @echo " make dome-plugins Package plugins for distribution" + @echo + @echo "[Dome] Development Variables:" + @echo " Dome framework DOME = '$(DOME)'" + @echo " Arguments (dev) DOME_ARGS = '$(DOME_ARGS)'" + @echo " Export modules DOME_EXPORTS = '$(DOME_EXPORTS)'" + @echo " Plugin modules DOME_PLUGINS = '$(DOME_PLUGINS)'" + @echo " Local command DOME_APP_CLI = '$(DOME_APP_CLI)'" + @echo + @echo "[Dome] Documentation Variables:" + @echo " Application APP = '$(APP)'" + @echo " Copyright COPYRIGHT = '$(COPYRIGHT)'" + @echo " Dome framework DOME_DOC = '$(DOME_DOC)'" + @echo " App. framework DOME_APP_DOC = '$(DOME_APP_DOC)'" + @echo " App. Sources DOME_APP_SRC = '$(DOME_APP_SRC)'" + @echo + +# -------------------------------------------------------------------------- +# --- Application Cleaning +# -------------------------------------------------------------------------- + +.PHONY: dome-clean + +dome-clean: + @echo "[Dome] remove temporary files" + @rm -fr dist .dome-*.stamp + +# -------------------------------------------------------------------------- +# --- Development Packages Init & Installation +# -------------------------------------------------------------------------- + +.PHONY: dome-pkg + +include $(DOME)/template/makefile.packages + +DOME_MK_BIN=$(PWD)/node_modules/.bin +DOME_MK_PKG= \ + package.json node_modules \ + $(DOME)/template/makefile.packages \ + $(DOME)/template/package.sh + +node_modules: + mkdir $@ + +dome-pkg: .dome-pkg.stamp +.dome-pkg.stamp: $(DOME_MK_PKG) + @echo "[Dome] ----------------------------------------------------------------" + @echo "[Dome] installing development packages" + @echo "[Dome] ----------------------------------------------------------------" + @$(DOME)/template/package.sh --dev $(DOME_DEV_PACKAGES) + @echo "[Dome] ----------------------------------------------------------------" + @echo "[Dome] installing application packages" + @echo "[Dome] ----------------------------------------------------------------" + @$(DOME)/template/package.sh --app $(DOME_APP_PACKAGES) + @echo "[Dome] ----------------------------------------------------------------" + @echo "[Dome] building application dependencies" + @echo "[Dome] ----------------------------------------------------------------" + yarn install + yarn run electron-builder install-app-deps + @touch $@ + +package.json: + yarn init + +# -------------------------------------------------------------------------- +# --- Application Templating +# -------------------------------------------------------------------------- + +.PHONY: dome-templ dome-reboot + +DOME_MK_TEMPLATES= \ + .gitignore \ + .babelrc \ + webpack.main.js \ + webpack.plugin.js \ + webpack.renderer.js \ + electron-webpack.json \ + src/main/index.js \ + src/renderer/index.js + +dome-templ: $(DOME_MK_TEMPLATES) +dome-reboot: + echo "[Dome] Backup templates" + @for f in $(DOME_MK_TEMPLATES) ; do mv -fv $$f $$f.backup ; done + $(MAKE) dome-templ dome-pkg + +# Templated files + +ifeq ("$(DOME)",".") +.gitignore: + @cp -f $(DOME)/template/git-ignore $@ +else +.gitignore: $(DOME)/template/update.sh $(DOME)/template/git-ignore + @((tail -r $(DOME)/template/git-ignore | tail -n +3 | tail -r) || head -n -3 $(DOME)/template/git-ignore) > $(DOME)/template/git-ignore.local + @echo "/$(DOME)" >> $(DOME)/template/git-ignore.local + @tail -2 $(DOME)/template/git-ignore >> $(DOME)/template/git-ignore.local + @$^.local $@ + @rm -f $(DOME)/template/git-ignore.local +endif + +.babelrc: $(DOME)/template/update.sh $(DOME)/template/babelrc.json + @$^ $@ + +webpack.main.js: $(DOME)/template/update.sh $(DOME)/template/webpack.main.js + @$^ $@ + +webpack.renderer.js: $(DOME)/template/update.sh $(DOME)/template/webpack.renderer.js + @$^ $@ + +webpack.plugin.js: $(DOME)/template/update.sh $(DOME)/template/webpack.plugin.js + @$^ $@ + +electron-webpack.json: $(DOME)/template/update.sh $(DOME)/template/electron-webpack.json + @$^ $@ + +src/renderer/index.js: $(DOME)/template/update.sh $(DOME)/template/renderer.js + @$^ $@ + +src/main/index.js: $(DOME)/template/update.sh $(DOME)/template/main.js + @cp $(DOME)/template/main.js $(DOME)/template/main.js.local + @echo "Dome.setName('$(APP)');" >> $(DOME)/template/main.js.local + @echo "Dome.start();" >> $(DOME)/template/main.js.local + @$^.local $@ + @rm -f $(DOME)/template/main.js.local + +# -------------------------------------------------------------------------- +# --- Custom Entry Points +# -------------------------------------------------------------------------- + +ifndef DOME_CUSTOM_ENTRIES + +dome-templ: src/renderer/Application.js +src/renderer/Application.js: + @echo "[Dome] creating $@ from template" + @mkdir -p src/renderer + @cp -f $(DOME)/template/Application.js $@ + +dome-templ: src/renderer/Preferences.js +src/renderer/Preferences.js: + @echo "[Dome] creating $@ from template" + @mkdir -p src/renderer + @cp -f $(DOME)/template/Preferences.js $@ + +endif + +# -------------------------------------------------------------------------- +# --- Exported API for Plugins +# -------------------------------------------------------------------------- + +.PHONY: dome-export-dev dome-export-app + +DOME_MK_EXPORTS_JS=$(DOME)/src/misc/exports.js + +# -------------------------------------------------------------------------- + +dome-export-dev: + @rm -f $(DOME_MK_EXPORTS_JS) + @echo "// Static Plugins Loader" > $(DOME_MK_EXPORTS_JS) + @for m in $(DOME_EXPORTS) ;\ + do \ + echo "[Dome] installing '$$m'" ;\ + echo "import '$$m';" \ + >> $(DOME_MK_EXPORTS_JS) ;\ + done + @for m in $(DOME_PLUGINS) ;\ + do \ + echo "[Dome] loading plugin $$m" ;\ + echo "import '@plugins/$$m';" >> $(DOME_MK_EXPORTS_JS) ;\ + done + @chmod a-w $(DOME_MK_EXPORTS_JS) + +# -------------------------------------------------------------------------- + +dome-export-app: + @rm -f $(DOME_MK_EXPORTS_JS) + @echo "// Static Loader (Generated by Dome)" > $(DOME_MK_EXPORTS_JS) + @echo "import { register } from 'dome/misc/plugins' ;" >> $(DOME_MK_EXPORTS_JS) ; + @echo "[Dome] export 'dome'" ; + @$(DOME)/template/export.sh $(DOME) >> $(DOME_MK_EXPORTS_JS) + @for m in $(DOME_EXPORTS) ;\ + do \ + echo "[Dome] export '$$m'" ;\ + echo "{ let m = require('$$m'); register('$$m',m); }" \ + >> $(DOME_MK_EXPORTS_JS) ;\ + done + @for m in $(DOME_PLUGINS) ;\ + do \ + echo "[Dome] install '@plugins/$$m'" ;\ + echo "{ let m = require('@plugins/$$m'); register('@plugins/$$m',m); }" \ + >> $(DOME_MK_EXPORTS_JS) ;\ + done + @chmod a-w $(DOME_MK_EXPORTS_JS) + +# -------------------------------------------------------------------------- +# --- Packaging Plugins +# -------------------------------------------------------------------------- + +.PHONY: dome-plugins dome-plugin-% + +DOME_MK_PLUGINS_TARGET=$(addprefix dome-plugin-, $(DOME_PLUGINS)) +DOME_MK_PLUGINS_SOURCE=$(addprefix src/plugins/, $(DOME_PLUGINS)) +DOME_MK_PLUGINS_CONFIG=$(addsuffix /package.json, $(DOME_MK_PLUGINS_SOURCE)) + +dome-plugins: $(DOME_MK_PLUGINS_CONFIG) $(DOME_MK_PLUGINS_TARGET) + +dome-plugin-%: src/plugins/%/package.json webpack.plugin.js + @echo "[Dome] building plugin '$*'" + @rm -fr dist/plugins/$* + @mkdir -p dist/plugins/$* + @node $(DOME)/template/packplugin.js '$*' + DOME=$(DOME) DOME_PLUGIN='$*' yarn run webpack -p --config webpack.plugin.js + @echo "[Dome] plugin packaged in ./dist/plugins/$*" + +src/plugins/%/package.json: + @echo "[Dome] creating package.json for plugin '$*'" + @echo '{' > $@ + @echo ' "name": "$*",' >> $@ + @echo ' "version": "0.1",' >> $@ + @echo ' "license": "UNLICENSED"' >> $@ + @echo '}' >> $@ + +# -------------------------------------------------------------------------- +# --- Application Development +# -------------------------------------------------------------------------- + +DOME_MK_CLIDIR=$(dir $(DOME_APP_CLI)) + +.PHONY: dome-dev + +dome-dev: dome-pkg dome-templ dome-export-dev + @echo "[Dome] linking $(DOME_APP_CLI)" + @mkdir -p $(DOME_MK_CLIDIR) + @rm -f $(DOME_APP_CLI) + @echo "#!/bin/sh" >> $(DOME_APP_CLI) + @echo "export DOME='$(DOME)'" >> $(DOME_APP_CLI) + @echo "export DOME_ENV='dev'" >> $(DOME_APP_CLI) + @echo 'exec $(DOME_MK_BIN)/electron-webpack dev "$$@"' >> $(DOME_APP_CLI) + @chmod 555 $(DOME_APP_CLI) + @echo "[Dome] running application (development)" + @$(DOME_APP_CLI) $(DOME_ARGS) + +# -------------------------------------------------------------------------- +# --- Application Building +# -------------------------------------------------------------------------- + +.PHONY: dome-app + +dome-app: dome-pkg dome-templ dome-export-app + @echo "[Dome] compiling application (production)" + DOME=$(DOME) DOME_ENV='app' yarn run electron-webpack app + @echo "[Dome] linking $(DOME_APP_CLI)" + @mkdir -p $(DOME_MK_CLIDIR) + @rm -f $(DOME_APP_CLI) + @echo "#!/bin/sh" >> $(DOME_APP_CLI) + @echo "export DOME_LOCAL=true" >> $(DOME_APP_CLI) + @echo 'exec $(DOME_MK_BIN)/electron $(PWD)/dist/main/main.js "$$@"' >> $(DOME_APP_CLI) + @chmod 555 $(DOME_APP_CLI) + +# -------------------------------------------------------------------------- +# --- Application Packaging +# -------------------------------------------------------------------------- + +.PHONY: dome-dist + +dome-dist: dome-app + @echo "[Dome] packaging application (production)" + DOME=$(DOME) yarn run electron-builder --dir -c.compression=store -c.mac.identity=null + @echo "[Dome] application packaged in ./dist" + +# -------------------------------------------------------------------------- +# --- Application JSdoc +# -------------------------------------------------------------------------- + +DOME_MK_API_DOC=$(PWD)/$(DOME_APP_DOC) +DOME_MK_API_SRC=$(PWD)/$(DOME_APP_SRC) $(addprefix $(PWD)/src/plugins/, $(DOME_PLUGINS)) + +dome-api: $(DOME_MK_BIN)/jsdoc + @echo "[Dome] generating $(APP) documentation" + @mkdir -p $(DOME_APP_DOC) + @rm -f $(DOME_APP_DOC)/*.html + @rm -f $(DOME_APP_DOC)/*.png + @rm -f $(DOME_APP_DOC)/*.css + @rm -fr $(DOME_APP_DOC)/fonts + @rm -fr $(DOME_APP_DOC)/styles + @(cd $(DOME) && DOME='.' DOME_PWD=$(PWD) APP=$(APP) COPYRIGHT=$(COPYRIGHT) \ + $(DOME_MK_BIN)/jsdoc -c ./doc/app.json $(DOME_MK_API_SRC) -d $(DOME_MK_API_DOC)) + @echo "[Dome] $(DOME_APP_DOC)/index.html" + +# -------------------------------------------------------------------------- +# --- Icon gallery +# -------------------------------------------------------------------------- + +DOME_MK_ICON_MAKE=$(DOME)/doc/icons.js +DOME_MK_ICON_DATA=$(DOME)/src/renderer/controls/icons.json +DOME_MK_ICON_HTML=$(DOME)/doc/template/gallery-icons.html + +$(DOME_MK_ICON_HTML): $(DOME_MK_ICON_MAKE) $(DOME_MK_ICON_DATA) + @echo "[Dome] generating icons gallery" + @node $(DOME_MK_ICON_MAKE) $(DOME_MK_ICON_DATA) > $(DOME_MK_ICON_HTML) + +# -------------------------------------------------------------------------- +# --- Dome Documentation +# -------------------------------------------------------------------------- + +DOME_MK_DOC_OUT=$(addprefix $(PWD)/, $(DOME_DOC)) + +dome-doc: $(DOME_MK_BIN)/jsdoc $(DOME_MK_ICON_HTML) + @echo "[Dome] generating Dome documentation" + @mkdir -p $(DOME_DOC) + @rm -f $(DOME_DOC)/*.html + @rm -f $(DOME_DOC)/*.png + @rm -f $(DOME_DOC)/*.css + @rm -fr $(DOME_DOC)/fonts + @rm -fr $(DOME_DOC)/styles + @(cd $(DOME) && DOME="." DOME_PWD=$(PWD) COPYRIGHT='CEA Tech' \ + $(DOME_MK_BIN)/jsdoc -c ./doc/config.json -d $(DOME_MK_DOC_OUT)) + @cp -f $(DOME)/doc/gallery.css $(DOME_DOC)/styles/ + @cp -f $(DOME)/doc/tutorials/*.png $(DOME_DOC)/ + @cat \ + $(DOME)/doc/template/gallery-head.html \ + $(DOME)/doc/template/gallery-icons.html \ + $(DOME)/doc/template/gallery-tail.html \ + > $(DOME_DOC)/gallery-icons.html + @echo "[Dome] $(DOME_DOC)/index.html" + +# --- Doc binaries --------------------------------------------------------- + +$(DOME_MK_BIN)/jsdoc: + @echo "[Dome] installing jsdoc" + @yarn add -D jsdoc + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/makefile.app.packages b/Ivette/src/dome/template/makefile.app.packages new file mode 100644 index 00000000000..58aa6a3ad51 --- /dev/null +++ b/Ivette/src/dome/template/makefile.app.packages @@ -0,0 +1,15 @@ +# -------------------------------------------------------------------------- +# --- Package Template Definitions +# -------------------------------------------------------------------------- + +# Additional development yarn package specifications: + +DOME_PKG_DEV= + +# -------------------------------------------------------------------------- + +# Additional production yarn package specifications: + +DOME_PKG_APP= + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/makefile.packages b/Ivette/src/dome/template/makefile.packages new file mode 100644 index 00000000000..05b8cb03aec --- /dev/null +++ b/Ivette/src/dome/template/makefile.packages @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- +# --- Packages Definitions for Dome environment --- +# -------------------------------------------------------------------------- + +DOME_DEV_PACKAGES= \ + @babel/core@^7 \ + @babel/preset-env \ + @babel/preset-react \ + @babel/plugin-proposal-object-rest-spread \ + electron@^7 \ + electron-builder \ + electron-webpack \ + electron-devtools-installer \ + webpack \ + babel-loader \ + css-loader \ + react-hot-loader \ + @hot-loader/react-dom \ + @types/react + +DOME_APP_PACKAGES= \ + react@^16.8 \ + react-dom \ + source-map-support \ + lodash \ + react-virtualized \ + react-draggable \ + codemirror + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/package.sh b/Ivette/src/dome/template/package.sh new file mode 100755 index 00000000000..58e4428ffb8 --- /dev/null +++ b/Ivette/src/dome/template/package.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# -------------------------------------------------------------------------- +# --- Compute mode +# -------------------------------------------------------------------------- + +OPT="" +LOG="" + +case $1 in + "--dev"|"-D") + OPT="--dev" + LOG=".dome-pkg-dev" + shift + ;; + "--app"|"-A") + OPT="" + LOG=".dome-pkg-app" + shift + ;; + *) + echo "Require --dev or --app option" + exit 1 + ;; +esac + +# -------------------------------------------------------------------------- +# --- Check for Updates +# -------------------------------------------------------------------------- + +rm -f $LOG.tmp +echo $* > $LOG.tmp + +if [ -f $LOG.lock ] +then + diff $LOG.tmp $LOG.lock + if [ $? -eq 0 ] + then + rm -f $LOG.tmp + echo "Packages are up-to-date." + exit 0 + fi +fi + +# -------------------------------------------------------------------------- +# --- Updates Packages +# -------------------------------------------------------------------------- + +echo "yarn add $OPT $*" +yarn add $OPT $* + +if [ $? -eq 0 ] +then + mv -f $LOG.tmp $LOG.lock +else + echo "Package installation failed." + exit 1 +fi + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/packplugin.js b/Ivette/src/dome/template/packplugin.js new file mode 100644 index 00000000000..d0a9f265c28 --- /dev/null +++ b/Ivette/src/dome/template/packplugin.js @@ -0,0 +1,31 @@ +#!/bin/node + +const fs = require('fs'); +const name = process.argv[2]; +const INFOS = [ + 'name', + 'version', + 'description', + 'homepage', + 'bugs', + 'keywords', + 'author', + 'contributors', + 'repository', + 'license' +]; + +const dst = { + name, + version: '0.1', + license: 'UNLICENSED', + main: 'bundle.js' +}; + +let src = './src/plugins/' + name + '/package.json' ; +let tgt = './dist/plugins/' + name + '/package.json' ; +let pkg = JSON.parse( fs.readFileSync( src , 'UTF-8' ) ); +INFOS.forEach((fd) => { let d = pkg[fd] ; if (!d) dst[fd] = d }); +fs.writeFileSync( tgt , JSON.stringify(dst) , 'UTF-8' ); + +// End. diff --git a/Ivette/src/dome/template/renderer.js b/Ivette/src/dome/template/renderer.js new file mode 100644 index 00000000000..1544ac9e113 --- /dev/null +++ b/Ivette/src/dome/template/renderer.js @@ -0,0 +1,41 @@ +// -------------------------------------------------------------------------- +// --- Electron renderer-process entry-point for Dome. +// -------------------------------------------------------------------------- + +/* + Template of ./src/renderer/index.js + Imported from $(DOME)/template/renderer.js + + You can modify this template and add your own code before or + after rendering the main components. + + However, please note that React hot-reloading is fragile. + Component that are not imported by <Application/> or <Preferences/> + may suffer from well known limitations of hot-reloading and + may lead to state losses or complete application reloads. +*/ + +// Enable live-editing in React: +import 'react-hot-loader/patch' ; +import React from 'react' ; +import Dome from 'dome' ; + +// You can change the name of the main components, +// provided you define the makefile variable +// `DOME_CUSTOM_ENTRIES` to prevent files 'Application.js' and 'Preferences.js' +// from being generated by the template makefile. + +import Application from './Application' ; +import Preferences from './Preferences' ; + +// Define the application main components for each window: +Dome.setApplicationWindow(Application); +Dome.setPreferencesWindow(Preferences); + +// Mark the main application reloadable and enable live updates: +module.hot && Dome.isApplicationWindow() && + module.hot.accept('./Application',() => Dome.setApplicationWindow(Application)); +module.hot && Dome.isPreferencesWindow() && + module.hot.accept('./Preferences',() => Dome.setPreferencesWindow(Preferences)); + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/update.sh b/Ivette/src/dome/template/update.sh new file mode 100755 index 00000000000..56d22295ef2 --- /dev/null +++ b/Ivette/src/dome/template/update.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# -------------------------------------------------------------------------- +# --- Update Templated File (merge with user modifications) +# -------------------------------------------------------------------------- + +USER=$2 +TEMPLATE=$1 +BACK=$(dirname $USER)/.dome-$(basename $USER).back +ORIGIN=$(dirname $TEMPLATE)/.dome-$(basename $TEMPLATE).orig +DIFF=$(dirname $USER)/.dome-diff + +if [ ! -f $TEMPLATE ] +then + echo "[Dome] missing template ('$TEMPLATE')" + exit 2 +fi + +if [ -f $USER ] +then + if [ ! -f $ORIGIN ] + then + echo "[Dome] lost original template for '$USER' (search for diffs)" + cp -f $TEMPLATE $ORIGIN + fi + cp -f $USER $BACK + rm -f $USER + diff3 -m -L YOURS $BACK -L ORIGIN $ORIGIN -L TEMPLATE $TEMPLATE > $USER + MERGED=$? + cp -f $TEMPLATE $ORIGIN + if [ $MERGED -eq 0 ] + then + diff $USER $BACK > $DIFF + if [ $? -eq 0 ] + then + echo "[Dome] updated '$USER' with new template (no modifications)" + else + echo "[Dome] merged '$USER' with new template (backup saved)." + fi + rm -f $DIFF + exit 0 + else + while true + do + echo "[Dome] conflicting '$USER' with new template." + echo " (d) show diffs (e) edit conflict" + echo " (k) keep current (t) use template" + read -p "Your choice ? [t] " ACTION + case $ACTION in + d) + echo "Differences ( > yours, < template ):" + diff $TEMPLATE $BACK + ;; + e) + echo "Previous content saved in '$BACK'." + echo "Run 'make dome-templ' after '$USER' has been fixed." + exit 1 + ;; + k) + exit 0 + ;; + t|"") + cp -f $TEMPLATE $USER + exit 0 + ;; + esac + done + fi +else + echo "[Dome] creating '$USER' from template" + cp -f $TEMPLATE $USER + cp -f $TEMPLATE $ORIGIN +fi + +# -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/webpack.main.js b/Ivette/src/dome/template/webpack.main.js new file mode 100644 index 00000000000..608d2937231 --- /dev/null +++ b/Ivette/src/dome/template/webpack.main.js @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------- +// --- Webpack extension for electron main-process +// -------------------------------------------------------------------------- + +/* + Template of ./webpack.main.js from $(DOME)/template/webpack.main.js + + This webpack definitions will be merged into electron-webpack + ones thanks to electron-webpack.json configuration file. + + You may extend it with your own additions. +*/ + +const path = require('path'); +const DOME = process.env.DOME || path.resolve(__dirname , 'dome'); +const ENV = process.env.DOME_ENV ; + +// Do not use electron-devtools-installer in production mode +function domeDevtools() { + switch(ENV) { + case 'dev': + return 'electron-devtools-installer'; + default: + return path.resolve( DOME , 'src/misc/devtools.js' ); + } +} + +module.exports = { + resolve: { + alias: { + 'dome$': path.resolve( DOME , 'src/main/dome.js' ), + 'dome/system$': path.resolve( DOME , 'src/misc/system.js' ), + 'dome/devtools': domeDevtools() + } + } +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/webpack.plugin.js b/Ivette/src/dome/template/webpack.plugin.js new file mode 100644 index 00000000000..f60bdbf7ab8 --- /dev/null +++ b/Ivette/src/dome/template/webpack.plugin.js @@ -0,0 +1,41 @@ +// -------------------------------------------------------------------------- +// --- Webpack configuration for packing plugins +// -------------------------------------------------------------------------- + +/* + Template of ./webpack.plugin.js from $(DOME)/template/webpack.plugin.js + + This webpack definitions will be used to make plugin bundles. + + You may extend it with your own additions. +*/ + +const path = require('path'); +const DOME = process.env.DOME || path.resolve( __dirname , 'dome' ); +const PLUGIN = process.env.DOME_PLUGIN ; +const ENTRY = path.resolve( __dirname , 'src/plugins' , PLUGIN ); +const DIST = path.resolve( __dirname , 'dist/plugins' , PLUGIN ); + +module.exports = { + entry: ENTRY, + output: { + path: DIST, + filename: 'bundle.js', + libraryTarget: 'commonjs2' + }, + module: { + rules: [ + { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, + { test: /\.js$/, use: [ 'babel-loader' ], exclude: /(node_modules)/ } + ] + }, + externals: [ + 'lodash', + 'react', + /^dome\/.+$/, + /^@plugins\/.+$/, + /^@\/.+$/ + ] +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/dome/template/webpack.renderer.js b/Ivette/src/dome/template/webpack.renderer.js new file mode 100644 index 00000000000..5cba35d887a --- /dev/null +++ b/Ivette/src/dome/template/webpack.renderer.js @@ -0,0 +1,35 @@ +// -------------------------------------------------------------------------- +// --- Webpack extension for electron main-process +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/webpack.main.js + + This webpack definitions will be merged into electron-webpack + ones thanks to electron-webpack.json configuration file. + + You may extend it with your own additions. +*/ + +const path = require('path'); +const DOME = process.env.DOME || path.resolve( __dirname , 'dome' ); + +module.exports = { + module: { + rules: [ + { test: /\.css$/, use: [ 'css-loader' ] } + ] + }, + resolve: { + alias: { + '@plugins': path.resolve( __dirname , 'src/plugins' ), + 'dome/misc': path.resolve( DOME , 'src/misc' ), + 'dome/system': path.resolve( DOME , 'src/misc/system.js' ), + 'dome$': path.resolve( DOME , 'src/renderer/dome.js' ), + 'dome': path.resolve( DOME , 'src/renderer' ), + 'react-dom': '@hot-loader/react-dom' + } + } +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/frama-c/labviews.css b/Ivette/src/frama-c/labviews.css new file mode 100644 index 00000000000..1b6893fd996 --- /dev/null +++ b/Ivette/src/frama-c/labviews.css @@ -0,0 +1,53 @@ +/* -------------------------------------------------------------------------- */ +/* --- Styling LabViews --- */ +/* -------------------------------------------------------------------------- */ + +.dome-window-active .labview-icon { + fill: #7d7d7d ; +} + +.labview-field { + position: relative ; + left: -8px ; +} + +.labview-stock:hover { + background: #ccc ; +} + +.labview-stock:hover * { + cursor: move ; +} + +.labview-stock.dome-dragging +{ + border-radius: 4px ; + background: #ccc ; + border: thin solid black ; +} + +.labview-content +{ + background: #e6e6e6 ; +} + +.labview-titlebar +{ + background: #ccc ; +} + +.labview-titlebar .dome-xLabel +{ + padding-top: 3px ; +} + +.labview-handle +{ + flex: 1 1 auto ; + cursor: move ; +} + +.labview-close:hover +{ + fill: red ; +} diff --git a/Ivette/src/frama-c/labviews.js b/Ivette/src/frama-c/labviews.js new file mode 100644 index 00000000000..97fdcc2413e --- /dev/null +++ b/Ivette/src/frama-c/labviews.js @@ -0,0 +1,597 @@ +// -------------------------------------------------------------------------- +// --- Lab View Component +// -------------------------------------------------------------------------- + +/** @module frama-c/labviews */ + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import { Catch } from 'dome/errors' ; +import { DnD, DragSource } from 'dome/dnd' ; +import { SideBar, Section, Item } from 'dome/layout/sidebars' ; +import { Splitter } from 'dome/layout/splitters' ; +import Grids, { GridLayout, GridItem } from 'dome/layout/grids' ; +import { Hbox, Hfill, Vfill, Filler } from 'dome/layout/boxes' ; +import { IconButton, Field } from 'dome/controls/buttons' ; +import { Label } from 'dome/controls/labels' ; +import { Icon } from 'dome/controls/icons' ; +import { Item as RenderItem, Render } from 'dome/layout/dispatch' ; +import './labviews.css' ; + +// -------------------------------------------------------------------------- +// --- Library +// -------------------------------------------------------------------------- + +class Library { + + constructor() { + this.modified = false ; + this.virtual = {} ; + this.collection = {} ; + this.items = [] ; + } + + commit() { + if (!_.isEqual(this.collection,this.virtual)) { + this.collection = Object.assign({},this.virtual) ; + this.items = _.sortBy(this.collection , [ 'order', 'id' ]); + this.modified = false ; + Dome.emit('labview.library'); + } + } + + useItem(id,group,path,props) { + if (!this.modified) { + this.modified = true ; + setImmediate(() => this.commit()); + } + if (!id) return undefined; + let order = props.rank === undefined + ? path + : path.slice(0,-1).concat([props.rank]); + let collection = this.virtual ; + collection[id] = Object.assign( { id, order, group }, props ); + return () => delete collection[id]; + } + +} + +// -------------------------------------------------------------------------- +// --- Library Components +// -------------------------------------------------------------------------- + +const isItemId = (fd,id) => id.startsWith(fd) && id[fd.length] === '.' ; +const getItemId = (fd,id) => isItemId(fd,id) ? id.substring(fd.length+1) : undefined ; +const getItems = (items,fd) => items.filter((item) => isItemId(fd,item.id)); + +const LibraryManager = React.createContext(); + +const useLibraryItem = (fd,{id, ...props}) => { + let context = React.useContext(LibraryManager); + React.useEffect(() => { + if (context) { + let { group, order, library } = context ; + let itemId = fd + '.' + id ; + return library.useItem(itemId,group,order,props); + } else + return undefined ; + }); + return context ; +}; + + +const Rankify = ({ library, group, order, children }) => { + let rank = 0; + let rankify = (elt) => { + let context = { group, order:order.concat([rank++]), library }; + return ( + <LibraryManager.Provider value={context}> + {elt} + </LibraryManager.Provider> + ); + }; + return ( + <React.Fragment> + {React.Children.map( children, rankify )} + </React.Fragment> + ); +}; + +const HIDDEN = { display: 'none' }; + +const UseLibrary = ( { library, children } ) => ( + <div style={HIDDEN}> + <Rankify library={library} order={[]}> + {children} + </Rankify> + </div> +); + +/** + @class + @summary Ordered collection of LabView Components. + @description + Renderers its children in the specified order. + Otherwized, elements are ordered by `rank` and `id`. + */ +export const Fragment = ({ group, children }) => { + let context = React.useContext(LibraryManager); + if (!context) + return null; + else { + return ( + <Rankify + group={group || context.group} + order={context.order} + library={context.library} > + {children} + </Rankify> + ); + } +}; + +/** + @class + @summary Group of LabView Components. + @property {string} id - group identifier + @property {string} label - displayed name + @property {string} [title] - description tooltip + @property {React.Children} [children] - group content + @description + Defines a group of components. The components rendered + _inside_ its content are implicitely affected to this group, + unless specified. The group content are also rendered + in their specified order. For nested collections of components, + use `<Fragment/>` instead of `<React.Fragment/>` to specify order. + */ +export const Group = ({ children,...props}) => { + let context = useLibraryItem('groups',props); + return ( + <Rankify + group={props.id} + order={context.order} + library={context.library} > + {children} + </Rankify> + ); +}; + +// -------------------------------------------------------------------------- +// --- Views +// -------------------------------------------------------------------------- + +/** + @class + @summary Layout of LabView Components. + @property {string} id - view identifier + @property {string} label - displayed name + @property {string} [title] - description tooltip + @property {boolean} [defaultView] - use this view by default + @property {GridContent} children - grid content of the view + @description + Defines a predefined layout of components. The view is organized + into a GridContent, which must _only_ consists of: + - `<GridHbox>…</GridHbox>` an horizontal grid of `GridContent` elements; + - `<GridVbox>…</GridVbox>` a vertical grid of `GridContent` elements; + - `<GridItem id=…>` a single component. + + These grid content components must be imported from the `dome/layout/grids` module: + ``` + import { GridItem, GridHbox, GridVbox } from 'dome/layout/grids'; + ``` + */ +export const View = (props) => { + useLibraryItem('views',props); + return null; +}; + +// -------------------------------------------------------------------------- +// --- Components +// -------------------------------------------------------------------------- + +/** + @class + @summary LabView Component. + @property {string} id - component identifier + @property {string} label - displayed name + @property {number} [rank] - ordering index + @property {string} [group] - attachment group + @property {string} [title] - description tooltip + @property {React.Children} children - component rendering elements + @description + Defines a component and its content when incorporated inside a view. + Unless specified, the component will be implicitely attached + to the current enclosing group. The `rank` property can be used + for adjusting component ordering (see also `<Fragment/>` and `<Group/>`). + */ +export const Component = (props) => { + useLibraryItem('components',props); + return null; +}; + +const TitleContext = React.createContext(); + +/** + @class + @summary LabView Component's title bar. + @property {string} [icon] - displayed icon + @property {string} [label] - displayed name + @property {string} [title] - description tooltip + @property {React.Children} children - additional components to render + @description + Defines an alternative component title bar. + If specified, the icon, label and title properties are rendered in an `<Label/>` component. + By default, the component title bar is labelled according to the component properties. + */ +export const Title = ({icon,label,title,children}) => { + let context = React.useContext(TitleContext); + return ( + <RenderItem id={'labview.title.'+context.id}> + <Label className='labview-handle' icon={icon} + label={label || context.label} + title={title || context.title}/> + {children} + </RenderItem> + ); +}; + +// -------------------------------------------------------------------------- +// --- Grid Item +// -------------------------------------------------------------------------- + +const GRIDITEM = { + className: 'dome-container dome-xBoxes-vbox dome-xBoxes-box', + handle: '.labview-handle', + resize: 'both', + fill: 'none', + shrink: 'none', + minWidth: 40, + minHeight: 40, + width: 120, + height: 120 +}; + +const GRIDITEM_PLAIN = { fill: 'both' }; +const GRIDITEM_HPANE = { fill: 'horizontal' }; +const GRIDITEM_VPANE = { fill: 'vertical' }; + +const makeGridItem = (customize,onClose) => comp => { + let { id:libId, label, title, layout='PLAIN', children } = comp ; + let id = getItemId('components',libId); + let properties = Object.assign( {}, GRIDITEM ); + switch( layout ) { + case 'PLAIN': + Object.assign( properties, GRIDITEM_PLAIN ); + break; + case 'HPANE': + Object.assign( properties, GRIDITEM_HPANE ); + break; + case 'VPANE': + Object.assign( properties, GRIDITEM_VPANE ); + break; + default: + console.warn(`[labviews] unexpected layout for ${id} component`,layout); + break; + } + for (let fd in properties) { + let prop = comp[fd] ; + if (prop) properties[fd] = prop ; + } + let CLOSING ; + if (customize) CLOSING = ( + <IconButton + className='labview-close' + offset={-1} icon='CROSS' + onClick={() => onClose(id)}/> + ); + return ( + <GridItem id={id} {...properties}> + <Vfill className='labview-content'> + <Hbox className='labview-titlebar'> + <Hfill className='labview-handle'> + <Catch title={id}> + <Render id={ 'labview.title.' + id }> + <Label className='labview-handle' + label={label} title={title} /> + </Render> + </Catch> + </Hfill> + { CLOSING } + </Hbox> + <TitleContext.Provider value={{id,label,title}}> + <Catch title={id}>{children}</Catch> + </TitleContext.Provider> + </Vfill> + </GridItem> + ); +}; + +// -------------------------------------------------------------------------- +// --- Customization Views +// -------------------------------------------------------------------------- + +function CustomViews( { settings, shape, setShape, views:libViews } ) +{ + const [ local, setLocal ] = Dome.useState( settings, {} ); + const [ customs, setCustoms ] = Dome.useGlobalSetting( settings, {} ); + const [ edited, setEdited ] = React.useState(); + const { current , shapes={} } = local ; + + let theViews = {}; + + _.forEach( libViews, (view) => { + const { id: origin, order, label='(Stock View)', title } = view ; + const id = 'builtin.' + origin ; + theViews[ id ] = { id, order, label, title, builtin: true, origin }; + }); + + _.forEach( customs, (view) => { + const { id, order, label='(Custom View)', title, origin } = view ; + if (id && !theViews[id]) + theViews[id] = { id, order, label, title, builtin: false, origin }; + }); + + const getStock = (origin) => ( + (origin + && _.find( libViews, (v) => v.id === origin )) + || _.find( libViews, (v) => v.defaultView ) + || libViews[0] + ); + + const getDefaultShape = ( view ) => { + let stock = getStock( view && view.origin ); + return stock && Grids.makeChildrenShape(stock.children); + }; + + const SELECT = (id) => { + if (id && current !== id) { + if (current) shapes[current] = shape ; + setLocal({ current: id, shapes }); + setShape( shapes[id] || getDefaultShape(theViews[id]) ); + } + }; + + const POPUP = (id) => { + let view = theViews[id]; + if (!view) return; + let isCurrent = current === id ; + let isCustom = !view.builtin ; + + const DEFAULT = () => { + shapes[id] = undefined; + setLocal({ current:id, shapes }); + setShape( getDefaultShape(view) ); + }; + + const RENAME = () => setEdited(id); + + const DUPLICATE = () => { + let base = 'custom.' + view.origin ; + let stock = getStock(view.origin); + let k = 1, newId = base ; + while (theViews[newId]) newId = base + '~' + (++k) ; + let newOrder = view.order ; + if (newOrder && newOrder.concat) newOrder = newOrder.concat([k]); + let newLabel = 'Custom ' + stock.label ; + if (k>1) newLabel += '~' + k ; + customs[newId] = { + id: newId, + label: newLabel, + order: newOrder, + title:'Derived from ' + stock.label, + origin: view.origin, + builtin: false + }; + setCustoms(customs); + if (current) shapes[current] = shape; + setLocal({ current:newId, shapes }); + setEdited(newId); + }; + + const REMOVE = () => { + delete customs[id]; + delete shapes[id]; + setCustoms(customs); + let newCurrent = current === id ? undefined : current ; + setLocal({ current: newCurrent, shapes }); + }; + + Dome.popupMenu([ + { label: "Rename View", display:(!edited && isCustom), onClick: RENAME }, + { label: "Restore Default", display:isCurrent, onClick: DEFAULT }, + { label: "Duplicate View",onClick: DUPLICATE }, + 'separator', + { label: "Remove View", display:isCustom, onClick: REMOVE } + ]); + }; + + const makeViewItem = ({ id, label, title, builtin, origin }) => { + if (edited === id) { + const RENAMED = (newLabel) => { + if (newLabel) { + let custom = customs[id] ; + if (custom) custom.label = newLabel ; + setCustoms( customs ); + } + setEdited( undefined ); + }; + const FIELD=( + <Field className='labview-field' + placeholder='View Name' + autoFocus value={label} + onEnter={RENAMED} /> + ); + return ( + <Item key={id} id={id} icon='DISPLAY' title={title} label={FIELD}/> + ); + } else { + const FLAGS=[] ; + if (builtin) FLAGS.push('LOCK'); + return ( + <Item + key={id} id={id} + icon='DISPLAY' + label={label} + title={title} + selected={id && current === id} + onSelection={SELECT} + onContextMenu={POPUP} + > + {FLAGS.map((icn) => ( + <Icon key={icn} className='labview-icon' size={9} offset={1} id={icn} /> + ))} + </Item> + ); + } + }; + + return ( + <Section label='Views'> + {_.sortBy(theViews,['order','id']).map(makeViewItem)} + </Section> + ); +} + +// -------------------------------------------------------------------------- +// --- Customization Components +// -------------------------------------------------------------------------- + +const DRAGOVERLAY = { className: 'labview-stock' }; + +function CustomGroup( { dnd, shape, setDragging, id, title, label, components } ) +{ + + const makeComponent = ({ id, label, title }) => { + let itemId = getItemId('components',id); + let disabled = Grids.getShapeItem(shape,itemId) !== undefined ; + return ( + <DragSource key={id} dnd={dnd} + disabled={ disabled } + overlay={ disabled ? undefined : DRAGOVERLAY } + onStart={() => setDragging(itemId)} > + <Item icon='COMPONENT' disabled={ disabled } label={label} title={title} /> + </DragSource> + ); + }; + + return ( + <Section id={id} label={label} title={title}> + { components.map(makeComponent) } + </Section> + ); +} + +// -------------------------------------------------------------------------- +// --- Customization Panel +// -------------------------------------------------------------------------- + +function CustomizePanel({ dnd, settings, library, shape, setShape, setDragging }) +{ + + const items = library.items ; + const views = getItems(items,'views'); + const groups = getItems(items,'groups'); + const components = getItems(items,'components'); + const setting_folds = settings && settings + '.folds' ; + const setting_views = settings && settings + '.views' ; + const contents = {} ; + + groups.unshift({ id:'nogroup', label:'Components' }); + groups.forEach((g) => contents[g.id] = []); + + components.forEach((c) => { + let gid = c.group ? 'groups.' + c.group : 'nogroup' ; + let content = contents[gid] ; + if (content === undefined) content = contents.nogroup ; + content.push(c); + }); + + return ( + <SideBar settings={setting_folds}> + <CustomViews + key='views' + settings={setting_views} + shape={shape} + setShape={setShape} + views={views} /> + {groups.map((g) => ( + <CustomGroup + key={g.id} id={g.id} + label={g.label} title={g.title} + dnd={dnd} setDragging={setDragging} shape={shape} + components={contents[g.id]} /> + ))} + </SideBar> + ); +} + +// -------------------------------------------------------------------------- +// --- LabView Container +// -------------------------------------------------------------------------- + +/** + @class + @summary Reconfigurable Container (React Component) + @property {boolean} [customize] - show components panel (false by default) + @property {string} [settings] - window settings to make views persistent + @property {React.Children} children - the labview content + @description + This container displays its content into a reconfigurable view. + + The entire content is rendered, but elements must be packed into `<Component/>` + containers, otherwise, they would remain invisible. + Content may also contains `<View/>` and `<Group/>` definitions, and the content + can be defined through any kind of React components. +*/ +export function LabView(props) +{ + // Parameters + const { settings, customize=false, children } = props ; + const setting_split = settings && settings + '.split' ; + const setting_shape = settings && settings + '.shape' ; + const setting_panel = settings && settings + '.panel' ; + // Hooks & State + Dome.useUpdate('labview.library','dome.defaults'); + const dnd = React.useMemo(() => new DnD(),[]); + const lib = React.useMemo(() => new Library(),[]); + const [ shape, setShape ] = Dome.useState(setting_shape); + const [ dragging, setDragging ] = React.useState(); + // Preparation + const onClose = (id) => setShape(Grids.removeShapeItem(shape,id)); + const components = _.filter( lib.collection, (item) => isItemId('components',item.id) ); + const gridItems = components.map(makeGridItem(customize,onClose)); + const holding = dragging ? gridItems.find((elt) => elt.props.id === dragging) : undefined ; + // Make view + return ( + <React.Fragment> + <UseLibrary library={lib}> + {children} + </UseLibrary> + <Splitter settings={setting_split} unfold={customize} dir='RIGHT'> + <GridLayout + dnd={dnd} + padding={2} + className='labview-container' + items={gridItems} + shape={shape} + onReshape={setShape} + holding={holding} /> + <CustomizePanel + dnd={dnd} + settings={setting_panel} + shape={shape} + setShape={setShape} + setDragging={setDragging} + library={lib} /> + </Splitter> + </React.Fragment> + ); + +} + +// -------------------------------------------------------------------------- + +export default { LabView, View, Group, Component, Title } ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/frama-c/server.js b/Ivette/src/frama-c/server.js new file mode 100644 index 00000000000..60aabc6c853 --- /dev/null +++ b/Ivette/src/frama-c/server.js @@ -0,0 +1,623 @@ +// -------------------------------------------------------------------------- +// --- Frama-C Server +// -------------------------------------------------------------------------- + +/** + @module frama-c/server + @description + Manage the current Frama-C server/client interface +*/ + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; +import System from 'dome/system' ; +import { Buffer } from 'dome/text/buffers' ; +import Zmq from 'zeromq' ; + +// -------------------------------------------------------------------------- +// --- Events +// -------------------------------------------------------------------------- + +/** + @event + @summary Server Status Notification Event + @description + Event `'frama-c.server`. +*/ +export const SERVER = 'frama-c.server' ; + +// -------------------------------------------------------------------------- +// --- Server Utilities +// -------------------------------------------------------------------------- +/* +const SERVER_LOG = '-server-log' ; +const SERVER_NO_LOG = '-server-no-log' ; +const SERVER_OPT = '-server-zmq' ; +const SERVER_DEF = '-server-zmq=' ; +const SERVER_URL = '.frama-c.socket.io' ; + +const getZmqLog = (params) => params.find((opt) => ( + opt === SERVER_LOG || opt === SERVER_NO_LOG +)); + +const getZmqURL = (params) => { + let def = params.findIndex((opt) => opt.startsWith(SERVER_DEF)); + if (def) { + let quote = def[ SERVER_DEF.length ]; + return ( quote === "'" || quote === '"' ) + ? def.slice( SERVER_DEF.length + 1 , -1 ) + : def.slice( SERVER_DEF.length ); + } + let pos = params.findIndex((opt) => opt.startsWith(SERVER_OPT)); + if (pos) return params[pos+1]; + return undefined ; +}; +*/ +// -------------------------------------------------------------------------- +// --- Server Status +// -------------------------------------------------------------------------- + +/** + @typedef STATUS + @summary Server Status Codes. + @description +- `IDLE` Server paused +- `STARTED` Frama-C command launched +- `RUNNING` Server ready +- `KILLING` Server shutdown, waiting for exit +- `RESTART` Server shutdown, will reboot on exit +- `FAILED` Server halted on error + */ + +export const IDLE = 'IDLE' ; +export const STARTED = 'STARTED' ; // Command started +export const RUNNING = 'RUNNING' ; // Server connected +export const KILLING = 'KILLING' ; // Waiting for halt +export const RESTART = 'RESTART' ; // Restart when halt +export const FAILED = 'FAILED' ; // Error issued + +// -------------------------------------------------------------------------- +// --- Server Class +// -------------------------------------------------------------------------- + +/** + @summary Frama-C Server Interface. + @description + This class is responsible for running a Frama-C server + and communicate with it. + The server automatically locks the module when running + and listen to module KILL events. + + The server shall be property configured before being started. + It does _not_ use configuration from `module.config` on its own ; + you shall configure it by using `server.configure()`. + */ +export class Server { + + constructor() { + this.status = IDLE ; + this.console = new Buffer({ maxlines: 200 }); + this._reset(); + this.stop = this.stop.bind(this); + this.kill = this.kill.bind(this); + this.start = this.start.bind(this); + this.restart = this.restart.bind(this); + this.clearFailed = this.clearFailed.bind(this); + } + + // -------------------------------------------------------------------------- + + // CLIENT STATE: + // this.rqid // Request ID + // this.sent // Characters sent + // this.recv // Characters received + // this.started // Date of Server activity start + // this.process // Cumulated Server processing time + // this.pending // Pending promise callbacks + // this.queue_cmd // Queue of server commands to be sent + // this.queue_ids // Waiting request ids to be sent + // this.polling // Polling scheduled + + // SERVER STATE: + // this.config: server process config + // this.process: dome child process + // this.socket: ZMQ (REQ) socket + // this.busy: ZMQ socket is busy + // this.error: process error + // this.killer: killer timeout + + // SERVER CONFIG: + // See this.configure() + + // -------------------------------------------------------------------------- + // --- Server Status + // -------------------------------------------------------------------------- + + /** Return `FAILED` status message. */ + getError() { return this.error; } + + /** + @summary Current Server `STATUS`. + @return {STATUS} the current server status + @description + See [STATUS](module-frama-c_server.html#~STATUS) code definitions. + */ + getStatus() { return this.status; } + _status(s,err) { + if (s !== this.status || err) { + this.status = s; + this.error = err; + this.module.emit(SERVER); + } + } + + /** + @summary Frama-C Server is running and ready to handle requests. + @return {boolean} status is `RUNNING`. + */ + isRunning() { return this.status === RUNNING; } + + /** + @summary Server Statistics. + @return {object} stats (see above) + @description +The returned object has the following properties: +- `pending` : number of pending requests; +- `requests` : number of issued requests; +- `time` : ellapsed time of server activity, in milliseconds. +- `sent` : number of UTF-8 chars sent to server; +- `recv` : number of UTF-8 chars received from server; +- `rate` : number of requests per milliseconds. + */ + getStats() { + const pending = _.reduce( this.pending , (n,_) => n+1, 0 ); + const requests = this.rqid - pending ; + const process = this.process ; + const started = this.started ; + const sent = this.sent ; + const recv = this.recv ; + const time = process + (started ? Date.now() - started : 0 ); + const rate = process ? requests / process : 0 ; + return { + pending, requests, sent, recv, rate, time + }; + } + + // -------------------------------------------------------------------------- + // --- Server Control (Start) + // -------------------------------------------------------------------------- + + /** + @summary Start the Server. + @description + If the server is started or running, this is a no-op. + If the server is being shutdown, it will reboot. + Otherwise, the Frama-C Server is spawned. + + You can use `server.start` instead of `() => server.start()`. + */ + start() { + switch(this.status) { + case IDLE: + case FAILED: + this._status(STARTED); + this._launch() + .then(() => this._status(RUNNING)) + .catch((err) => this._status(FAILED,err)); + return; + case KILLING: + this._status(RESTART); + return; + case STARTED: + case RUNNING: + case RESTART: + default: + return; + } + } + + // -------------------------------------------------------------------------- + // --- Server Control (Stop) + // -------------------------------------------------------------------------- + + /** + @summary Stop the Server. + @description + If the server is starting, it is hard killed. + If the server is running, it is shutdown gracefully. + When the server is shutting down, restart is canceled. + Otherwise, this is a no-op. + + You can use `server.stop` instead of `() => server.stop()`. + */ + stop() { + switch(this.status) { + case STARTED: + this._kill(); + this._status(KILLING); + return; + case RUNNING: + this._shutdown(); + this._status(KILLING); + return; + case RESTART: + this._status(KILLING); + return; + case IDLE: + case FAILED: + case KILLING: + default: + return; + } + } + + // -------------------------------------------------------------------------- + // --- Server Control (Kill) + // -------------------------------------------------------------------------- + + /** + @summary Terminate the Server. + @description + If the server is starting or running or shutting down, + it is hard killed and restart is canceled. + Otherwize, this is no-op. + + You can use `server.kill` instead of `() => server.kill()`. + This function is automatically called when the `module` emits the `KILL` signal. + */ + kill() { + switch(this.status) { + case STARTED: + case RUNNING: + case KILLING: + case RESTART: + this._kill(); + this._status(KILLING); + return; + case IDLE: + case FAILED: + default: + return; + } + } + + // -------------------------------------------------------------------------- + // --- Server Control (Restart) + // -------------------------------------------------------------------------- + + /** + @summary Re-start the Server. + @description + If paused, simply start the Server. + When running, try to gracefully shutdown the Server, + and finally schedule a reboot on exit. + */ + restart() { + switch(this.status) { + case IDLE: + case FAILED: + this.start(); + return; + case RUNNING: + this._shutdown(); + // Fall Through + case KILLING: + this._status(RESTART); + return; + case STARTED: + case RESTART: + default: + return; + } + } + + // -------------------------------------------------------------------------- + // --- Server Control (Reset) + // -------------------------------------------------------------------------- + + /** + @summary Acknowledge `FAILED` status. + @description + Simply go back to `IDLE` status when `FAILED`. + Otherwised, do nothing. + */ + clearFailed() { + if (this.status === FAILED) + this._status(IDLE); + } + + // -------------------------------------------------------------------------- + // --- Server Configure + // -------------------------------------------------------------------------- + + /** + @summary Configure the Server. + @param {object} config - Server Configuration + @param {string} [config.command] - Server command (default: `frama-c`) + @param {Array.<string>} [config.params] - Server arguments (default: `-server-zmq .frama-c.socket.io`) + @param {string} [config.sockaddr] - Server socket name (default: `.frama-c.socket.io`) + @param {string} [config.logout] - Process stdout log file (default: `undefined`) + @param {string} [config.logerr] - Process stderr log file (default: `undefined`) + @param {Object} [config.env] - Process environment variables (default: `undefined`) + */ + configure( config ) + { + if (!config) + this.config = + { + command: 'frama-c', + params: ['-server-zmq', '.frama-c.socket.io'], + sockaddr: '.frama-c.socket.io' + } + else + this.config = config; + } + + // -------------------------------------------------------------------------- + // --- Low-level Launching + // -------------------------------------------------------------------------- + + async _launch() { + this._reset(); + if (!this.config) throw('Frama-C Server not configured'); + let { env, command, params, sockaddr, logout, logerr } = this.config; + sockaddr = System.join( this.module.session, sockaddr ); + logout = logout && System.join( this.module.session, logout ); + logerr = logerr && System.join( this.module.session, logerr ); + let options = { + cwd: this.module.session, + stdout: { path: logout, pipe: true }, + stderr: { path: logerr, pipe: true }, + env + }; + // Launch Process + const process = await System.spawn( command, params, options ); + const logging = this.console.append ; + const kill = this.kill ; + this.console.clear(); + this.module.lock(); + this.module.on(KILL,kill); + this.process = process ; + process.stdout.on('data', logging ); + process.stderr.on('data', logging ); + process.on('close', (status) => { + this.module.off(KILL,kill); + this.module.unlock(); + logging('Exit',status,'\n'); + this._close(status); + }); + // Connect to Server + this.socket = new Zmq.Request(); + this.busy = false ; + await this.socket.bind(addr).catch(kill); + } + + // -------------------------------------------------------------------------- + // --- Low-level Killing + // -------------------------------------------------------------------------- + + _reset() { + this.rqid = 0; + this.sent = 0; + this.recv = 0; + this.time = 0; + this.process = 0; + this.started = undefined; + this.queue_cmd = []; + this.queue_ids = []; + const pending = this.pending ; + this.pending = {}; + _.forEach( pending , ({ reject }) => reject('shutdown') ); + if (this.flushed) clearImmediate(this.flushed); + this.flushed = undefined; + if (this.polling) clearTimeout(this.polling); + this.polling = undefined; + } + + _kill() { + this._reset(); + if (this.killer) clearTimeout(this.killer); + if (this.process) this.process.kill(); + } + + _shutdown() { + this._reset(); + this.queue_cmd.push('SHUTDOWN'); + this._flush(); + if (!this.killer) { + const process = this.process ; + if (process) { + const timeout = (this.config && this.config.timeout) || 300 ; + this.killer = setTimeout( () => process.kill() , timeout ); + } + } + } + + _close(status) { + this._reset(); + if (this.killer) { + clearTimeout( this.killer ); + this.killer = undefined ; + } + if (this.socket) { + this.socket.close(); + this.socket = undefined ; + this.busy = false ; + } + if (this.process) { + this.process.kill(); + this.process = undefined ; + } + if (status) { + this._status(FAILED,'Exit Status ' + status); + } else { + this._status(IDLE); + } + } + + // -------------------------------------------------------------------------- + // --- Request Queue + // -------------------------------------------------------------------------- + + sendGET( rq, params ) { return this._sendRequest( 'GET' , rq , params ); } + sendSET( rq, params ) { return this._sendRequest( 'SET' , rq , params ); } + sendEXEC( rq, params ) { return this._sendRequest( 'EXEC' , rq , params ); } + + _sendRequest( kind, rq , params ) { + if (!this.isRunning()) return Promise.reject('Server not running'); + const rid = 'RQ.' + this.rqid++; + const data = JSON.stringify(params); + const promise = new Promise((resolve,reject) => { + this.pending[rid] = { resolve, reject }; + this.queue_cmd.push(kind,rid,rq,data); + this.queue_ids.push(rid); + }); + promise.kill = () => { + if (this.socket && this.pending[rid]) { + this.queue_cmd.push('KILL',rid); + this._flush(); + } + }; + this._flush(); + return promise; + } + + _resolve(id,result) { + let promise = this.pending[id]; + if (promise) { + delete this.pending[id]; + promise.resolve(result); + } + } + + _reject(id,error) { + let promise = this.pending[id]; + if (promise) { + delete this.pending[id]; + promise.reject(error); + } + } + + _cancel(ids) { + ids.forEach((rid) => this._reject(rid,'canceled')); + } + + _waiting() { + return _.find( this.resolve , () => true ) !== undefined ; + } + + // -------------------------------------------------------------------------- + // --- Server Command Queue + // -------------------------------------------------------------------------- + + _flush() { + if (!this.flushed) { + this.flushed = setImmediate(() => { + this.flushed = undefined; + this._send(); + }); + } + } + + _poll() { + if (!this.polling) { + let timeout = (this.config && this.config.polling) || 50 ; + this.polling = setTimeout(() => { + this.polling = false; + this._send(); + }, timeout); + } + } + + _send() { + // when busy, will be eventually re-triggered + if (!this.busy) { + const cmd = this.queue_cmd ; + if (!cmd.length && this._waiting()) cmd.push('POLL'); + if (!cmd.length) { + const ids = this.queue_ids ; + this.queue_cmd = []; + this.queue_ids = []; + const socket = this.socket ; + if (socket) { + if (!this.started) this.started = Date.now() ; + this.busy = true ; + this.sent = cmd.reduce( (s,p) => s + p.length , this.sent); + socket.send( cmd ) + .then(() => socket.receive().then((resp) => this._receive(resp))) + .catch(() => this._cancel(ids)) + .finally(() => this.busy = false); + } else + this._cancel(ids); + } else { + const started = this.started ; + if (started) { + const stopped = Date.now(); + this.process += stopped - started ; + this.started = undefined ; + } + } + } + } + + _receive(resp) { + try { + this.recv = resp.reduce( (s,p) => s + p.length , this.recv); + var rid,data,err,cmd; + const shift = () => resp.shift().toString(); + while( resp.length ) { + cmd = shift(); + switch( cmd ) { + case 'NONE': + break; + case 'DATA': + rid = shift(); + data = shift(); + this._resolve(rid,data); + break; + case 'KILLED': + rid = shift(); + this._reject(rid,'killed'); + break; + case 'ERROR': + rid = shift(); + err = shift(); + this._reject(rid,err); + break; + case 'REJECTED': + rid = shift(); + this._reject(rid,'rejected'); + break; + case 'WRONG': + err = shift(); + console.error('[Frama-C Server] ZMQ Protocol Error:',err); + break; + case 'NONE': + break; + default: + console.error('[Frama-C Server] Unknown Response:',cmd); + resp.length = 0; + break; + } + } + } finally { + if (this.queue_cmd.length) + this._flush(); + else + this._poll(); + } + } + +} + +// -------------------------------------------------------------------------- +// --- Exports +// -------------------------------------------------------------------------- + +export default { + Server, + IDLE,STARTED,RUNNING,KILLING,RESTART,FAILED +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/frama-c/states.js b/Ivette/src/frama-c/states.js new file mode 100644 index 00000000000..a602bb1430f --- /dev/null +++ b/Ivette/src/frama-c/states.js @@ -0,0 +1,114 @@ +// -------------------------------------------------------------------------- +// --- Frama-C States +// -------------------------------------------------------------------------- + +/** + @module frama-c/states + @description + Manage the current Frama-C project and projectified state values. +*/ + +import _ from 'lodash' ; +import React from 'react' ; +import Dome from 'dome' ; + +const NONE = [ undefined, () => undefined ]; // No-state + +/** + @event + @summary Current Project Updates + @description + Event `'frama-c.project'`. +*/ +export const PROJECT = 'frama-c.project' ; + +/** + @event + @summary State Notification Event (prefix) + @description + Event `'frama-c.state.<id>'` for project `<id>`. +*/ +export const STATE = 'frama-c.state.' ; + +// -------------------------------------------------------------------------- +// --- Current Project +// -------------------------------------------------------------------------- + +var currentProject = undefined ; + +/** + @summary Current Project (Custom React Hook). + @return {string} the current project identifier, or `undefined`. + */ +export function useProject() +{ + Dome.useUpdate(PROJECT); +} + +/** + @summary Update Current Project. + @param {string} project - the project identifier + @description + Make all states switching to their projectified value. + Emits `PROJECT`. + */ +export function setProject(project) +{ + currentProject = project ; + Dome.emit(PROJECT); +} + +/** + @summary Clear Project. + @param {Module} module - the Frama-C module + @param {string} [project] - the project identifier, defaults to current + @description + Remove all projectified values for the specified project + Emits `PROJECT`. + */ +export function clearProject(project) +{ + const theProject = project || currentProject ; + _.unset( globalStates , ['states',theProject] ); + Dome.emit(PROJECT); +} + +// -------------------------------------------------------------------------- +// --- Projectified State +// -------------------------------------------------------------------------- + +var globalStates = {} ; + +/** + @summary Projectified State (Custom React Hook). + @param {string} id - the state identifier (mandatory) + @param {string} [project] - the project identifier, defaults to current + @return {array} `[state,setState]` for the specified project + @description + Returns a getter and a setter for the specified state + in the specified or current project. + The initial value of states is always `undefined`. + + Each state is associated to a specific event `frama-c-state.<id>` which is + is used to notify updates. The hook also updates on `PROJECT` notifications. + */ +export function useState(id,project) +{ + const theEvent = STATE + id ; + Dome.useUpdate(PROJECT,theEvent); + const theProject = project || currentProject ; + if (!theProject) return NONE; + const thePath = ['states',theProject,id] ; + const theValue = _.get( globalStates, thePath ); + const setValue = (v) => { + Dome.emit(theEvent,v); + _.set( globalStates, thePath, v ); + }; + return [ theValue, setValue ]; +} + +// -------------------------------------------------------------------------- + +export default { useProject, setProject, clearProject, useState, PROJECT }; + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/main/index.js b/Ivette/src/main/index.js new file mode 100644 index 00000000000..2624543a9da --- /dev/null +++ b/Ivette/src/main/index.js @@ -0,0 +1,19 @@ +// -------------------------------------------------------------------------- +// --- Electron main-process entry-point for Dome. +// -------------------------------------------------------------------------- + +/* + Template of ./src/main/index.js + Imported from $(DOME)/template/main.js + + The call to Dome.start() will initialize the Dome application + and create the main window that will run the renderer process + from `src/renderer/index.js`. + + You may add your own code to be run in the Electron main-process + before or after the call to `Dome.start()`. +*/ + +import Dome from 'dome' ; +Dome.setName('Ivette'); +Dome.start(); diff --git a/Ivette/src/renderer/Application.js b/Ivette/src/renderer/Application.js new file mode 100644 index 00000000000..8129a62e076 --- /dev/null +++ b/Ivette/src/renderer/Application.js @@ -0,0 +1,63 @@ +// -------------------------------------------------------------------------- +// --- Main React Component rendered by './index.js' +// -------------------------------------------------------------------------- + +import React from 'react' ; +import Dome from 'dome' ; +import { Catch } from 'dome/errors' ; +import { Vfill } from 'dome/layout/boxes' ; +import { Splitter } from 'dome/layout/splitters' ; +import Toolbar from 'dome/layout/toolbars' ; +import Sidebar from 'dome/layout/sidebars' ; + +import './style.css' ; +import 'dome/misc/exports' ; + +import { LabView, View, Group, Component } from 'frama-c/labviews' ; + +// -------------------------------------------------------------------------- +// --- Main View +// -------------------------------------------------------------------------- + +export default (function() { + + const [sidebar,flipSidebar] = Dome.useSwitch('frama-c.sidebar.unfold',false); + const [viewbar,flipViewbar] = Dome.useSwitch('frama-c.viewbar.unfold',false); + + return ( + <Vfill> + <Toolbar.ToolBar> + <Toolbar.Button + icon='SIDEBAR' title='Show/Hide side bar' + selected={sidebar} + onClick={flipSidebar} + /> + <Toolbar.Filler/> + <Toolbar.Button + icon='ITEMS.GRID' + title='Customize Main View' + selected={viewbar} + onClick={flipViewbar}/> + </Toolbar.ToolBar> + <Splitter dir='LEFT' settings='frame-c.sidebar.position' unfold={sidebar}> + <Sidebar.SideBar> + <div>(Empty)</div> + </Sidebar.SideBar> + <LabView + customize={viewbar} + settings='frama-c.labview' + > + <View id='default' label='Dashboard' defaultView /> + <Component id='dashboard' label='Dashboard'/> + <Group id='plugins' label='Plugins'> + <Component id='plugins.eva' label='Frama-C / EVA' /> + <Component id='plugins.wp' label='Frama-C / WP' /> + </Group> + </LabView> + </Splitter> + </Vfill> + ); + +}); + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/renderer/Console.js b/Ivette/src/renderer/Console.js new file mode 100644 index 00000000000..cd542dd70a1 --- /dev/null +++ b/Ivette/src/renderer/Console.js @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------- +// --- Console +// -------------------------------------------------------------------------- + +import React from 'react' ; +import Dome from 'dome' ; +import { Buffer } from 'dome/text/buffers' ; +import { Text } from 'dome/text/editors' ; +import 'codemirror/theme/ambiance.css' ; + +const buffer = new Buffer( { maxlines: 1024 } ); + +{ + Dome.on('refresh',() => buffer.setFocused(false)); + Dome.on('console',(msg) => { buffer.append(msg); buffer.scroll(); } ); + buffer.log('Welcome to Ivette !'); +} + +function Console(props) { + return ( + <Text buffer={buffer} + mode='text' + theme="ambiance" + readOnly="nocursor" /> + ); +} + +Console.log = (...args) => buffer.log(...args); +Console.clear = () => buffer.clear(); + +export default Console ; diff --git a/Ivette/src/renderer/Preferences.js b/Ivette/src/renderer/Preferences.js new file mode 100644 index 00000000000..542d1d7c97a --- /dev/null +++ b/Ivette/src/renderer/Preferences.js @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------- +// --- Main React Component rendered by './index.js' +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/Settings.js + + This module shall export a React Component that + will be rendered (with empty props and children) + in the settings window of your application. + +*/ + +import React from 'react' ; + +export default (() => ( + <h1 className='dome-text-title' style={{margin: 24}}> + Settings (none) + </h1> +)); diff --git a/Ivette/src/renderer/index.js b/Ivette/src/renderer/index.js new file mode 100644 index 00000000000..1544ac9e113 --- /dev/null +++ b/Ivette/src/renderer/index.js @@ -0,0 +1,41 @@ +// -------------------------------------------------------------------------- +// --- Electron renderer-process entry-point for Dome. +// -------------------------------------------------------------------------- + +/* + Template of ./src/renderer/index.js + Imported from $(DOME)/template/renderer.js + + You can modify this template and add your own code before or + after rendering the main components. + + However, please note that React hot-reloading is fragile. + Component that are not imported by <Application/> or <Preferences/> + may suffer from well known limitations of hot-reloading and + may lead to state losses or complete application reloads. +*/ + +// Enable live-editing in React: +import 'react-hot-loader/patch' ; +import React from 'react' ; +import Dome from 'dome' ; + +// You can change the name of the main components, +// provided you define the makefile variable +// `DOME_CUSTOM_ENTRIES` to prevent files 'Application.js' and 'Preferences.js' +// from being generated by the template makefile. + +import Application from './Application' ; +import Preferences from './Preferences' ; + +// Define the application main components for each window: +Dome.setApplicationWindow(Application); +Dome.setPreferencesWindow(Preferences); + +// Mark the main application reloadable and enable live updates: +module.hot && Dome.isApplicationWindow() && + module.hot.accept('./Application',() => Dome.setApplicationWindow(Application)); +module.hot && Dome.isPreferencesWindow() && + module.hot.accept('./Preferences',() => Dome.setPreferencesWindow(Preferences)); + +// -------------------------------------------------------------------------- diff --git a/Ivette/src/renderer/style.css b/Ivette/src/renderer/style.css new file mode 100644 index 00000000000..b7459ca5531 --- /dev/null +++ b/Ivette/src/renderer/style.css @@ -0,0 +1,7 @@ +/* -------------------------------------------------------------------------- */ +/* --- Frama-C Styling --- */ +/* -------------------------------------------------------------------------- */ + +/* (Empty) */ + +/* -------------------------------------------------------------------------- */ diff --git a/Ivette/webpack.main.js b/Ivette/webpack.main.js new file mode 100644 index 00000000000..608d2937231 --- /dev/null +++ b/Ivette/webpack.main.js @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------- +// --- Webpack extension for electron main-process +// -------------------------------------------------------------------------- + +/* + Template of ./webpack.main.js from $(DOME)/template/webpack.main.js + + This webpack definitions will be merged into electron-webpack + ones thanks to electron-webpack.json configuration file. + + You may extend it with your own additions. +*/ + +const path = require('path'); +const DOME = process.env.DOME || path.resolve(__dirname , 'dome'); +const ENV = process.env.DOME_ENV ; + +// Do not use electron-devtools-installer in production mode +function domeDevtools() { + switch(ENV) { + case 'dev': + return 'electron-devtools-installer'; + default: + return path.resolve( DOME , 'src/misc/devtools.js' ); + } +} + +module.exports = { + resolve: { + alias: { + 'dome$': path.resolve( DOME , 'src/main/dome.js' ), + 'dome/system$': path.resolve( DOME , 'src/misc/system.js' ), + 'dome/devtools': domeDevtools() + } + } +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/webpack.plugin.js b/Ivette/webpack.plugin.js new file mode 100644 index 00000000000..f60bdbf7ab8 --- /dev/null +++ b/Ivette/webpack.plugin.js @@ -0,0 +1,41 @@ +// -------------------------------------------------------------------------- +// --- Webpack configuration for packing plugins +// -------------------------------------------------------------------------- + +/* + Template of ./webpack.plugin.js from $(DOME)/template/webpack.plugin.js + + This webpack definitions will be used to make plugin bundles. + + You may extend it with your own additions. +*/ + +const path = require('path'); +const DOME = process.env.DOME || path.resolve( __dirname , 'dome' ); +const PLUGIN = process.env.DOME_PLUGIN ; +const ENTRY = path.resolve( __dirname , 'src/plugins' , PLUGIN ); +const DIST = path.resolve( __dirname , 'dist/plugins' , PLUGIN ); + +module.exports = { + entry: ENTRY, + output: { + path: DIST, + filename: 'bundle.js', + libraryTarget: 'commonjs2' + }, + module: { + rules: [ + { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, + { test: /\.js$/, use: [ 'babel-loader' ], exclude: /(node_modules)/ } + ] + }, + externals: [ + 'lodash', + 'react', + /^dome\/.+$/, + /^@plugins\/.+$/, + /^@\/.+$/ + ] +}; + +// -------------------------------------------------------------------------- diff --git a/Ivette/webpack.renderer.js b/Ivette/webpack.renderer.js new file mode 100644 index 00000000000..523eaa554cd --- /dev/null +++ b/Ivette/webpack.renderer.js @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------- +// --- Webpack extension for electron main-process +// -------------------------------------------------------------------------- + +/* + Template from $(DOME)/template/webpack.main.js + + This webpack definitions will be merged into electron-webpack + ones thanks to electron-webpack.json configuration file. + + You may extend it with your own additions. +*/ + +const path = require('path'); +const DOME = process.env.DOME || path.resolve( __dirname , 'dome' ); + +// -------------------------------------------------------------------------- + +module.exports = { + module: { + rules: [ + { test: /\.css$/, use: [ 'css-loader' ] } + ] + }, + resolve: { + alias: { + 'frama-c': path.resolve( __dirname , 'src/frama-c' ), + '@plugins': path.resolve( __dirname , 'src/plugins' ), + 'dome/misc': path.resolve( DOME , 'src/misc' ), + 'dome/system': path.resolve( DOME , 'src/misc/system.js' ), + 'dome$': path.resolve( DOME , 'src/renderer/dome.js' ), + 'dome': path.resolve( DOME , 'src/renderer' ), + 'react-dom': '@hot-loader/react-dom' + } + } +} ; + +// -------------------------------------------------------------------------- diff --git a/Ivette/yarn.lock b/Ivette/yarn.lock new file mode 100644 index 00000000000..1df87103151 --- /dev/null +++ b/Ivette/yarn.lock @@ -0,0 +1,8215 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"7zip-bin@~5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" + integrity sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA== + +"7zip@0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/7zip/-/7zip-0.0.6.tgz#9cafb171af82329490353b4816f03347aa150a30" + integrity sha1-nK+xca+CMpSQNTtIFvAzR6oVCjA= + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/core@^7", "@babel/core@^7.5.0": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91" + integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.2" + "@babel/helpers" "^7.7.0" + "@babel/parser" "^7.7.2" + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.7.2" + convert-source-map "^1.7.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af" + integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ== + dependencies: + "@babel/types" "^7.7.2" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" + integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== + dependencies: + "@babel/types" "^7.7.4" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz#efc54032d43891fe267679e63f6860aa7dbf4a5e" + integrity sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-annotate-as-pure@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" + integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz#32dd9551d6ed3a5fc2edc50d6912852aa18274d9" + integrity sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" + integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-builder-react-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz#da188d247508b65375b2c30cf59de187be6b0c66" + integrity sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA== + dependencies: + "@babel/types" "^7.7.4" + esutils "^2.0.0" + +"@babel/helper-call-delegate@^7.4.4": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz#df8942452c2c1a217335ca7e393b9afc67f668dc" + integrity sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw== + dependencies: + "@babel/helper-hoist-variables" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-call-delegate@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801" + integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA== + dependencies: + "@babel/helper-hoist-variables" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-create-regexp-features-plugin@^7.7.0": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz#6f20443778c8fce2af2ff4206284afc0ced65db6" + integrity sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ== + dependencies: + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + +"@babel/helper-create-regexp-features-plugin@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" + integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A== + dependencies: + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + +"@babel/helper-define-map@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz#60b0e9fd60def9de5054c38afde8c8ee409c7529" + integrity sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/types" "^7.7.0" + lodash "^4.17.13" + +"@babel/helper-define-map@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" + integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/types" "^7.7.4" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz#db2a6705555ae1f9f33b4b8212a546bc7f9dc3ef" + integrity sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg== + dependencies: + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-explode-assignable-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" + integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg== + dependencies: + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-function-name@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3" + integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q== + dependencies: + "@babel/helper-get-function-arity" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" + integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== + dependencies: + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-get-function-arity@^7.0.0", "@babel/helper-get-function-arity@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d" + integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-get-function-arity@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" + integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-hoist-variables@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz#b4552e4cfe5577d7de7b183e193e84e4ec538c81" + integrity sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-hoist-variables@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" + integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-member-expression-to-functions@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz#472b93003a57071f95a541ea6c2b098398bcad8a" + integrity sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-member-expression-to-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" + integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-module-imports@7.0.0-beta.35": + version "7.0.0-beta.35" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz#308e350e731752cdb4d0f058df1d704925c64e0a" + integrity sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg== + dependencies: + "@babel/types" "7.0.0-beta.35" + lodash "^4.2.0" + +"@babel/helper-module-imports@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz#99c095889466e5f7b6d66d98dffc58baaf42654d" + integrity sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-module-imports@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" + integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz#154a69f0c5b8fd4d39e49750ff7ac4faa3f36786" + integrity sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-simple-access" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/types" "^7.7.0" + lodash "^4.17.13" + +"@babel/helper-module-transforms@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.4.tgz#8d7cdb1e1f8ea3d8c38b067345924ac4f8e0879a" + integrity sha512-ehGBu4mXrhs0FxAqN8tWkzF8GSIGAiEumu4ONZ/hD9M88uHcD+Yu2ttKfOCgwzoesJOJrtQh7trI5YPbRtMmnA== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-simple-access" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + lodash "^4.17.13" + +"@babel/helper-module-transforms@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" + integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-simple-access" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz#4f66a216116a66164135dc618c5d8b7a959f9365" + integrity sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-optimise-call-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" + integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-plugin-utils@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" + integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + +"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz#4d69ec653e8bff5bce62f5d33fc1508f223c75a7" + integrity sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.0" + "@babel/helper-wrap-function" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-remap-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" + integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-wrap-function" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-replace-supers@^7.5.5", "@babel/helper-replace-supers@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz#d5365c8667fe7cbd13b8ddddceb9bd7f2b387512" + integrity sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.7.0" + "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-replace-supers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" + integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-simple-access@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz#97a8b6c52105d76031b86237dc1852b44837243d" + integrity sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g== + dependencies: + "@babel/template" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-simple-access@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" + integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A== + dependencies: + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-split-export-declaration@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300" + integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-split-export-declaration@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" + integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-wrap-function@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz#15af3d3e98f8417a60554acbb6c14e75e0b33b74" + integrity sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-wrap-function@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" + integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helpers@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.0.tgz#359bb5ac3b4726f7c1fde0ec75f64b3f4275d60b" + integrity sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g== + dependencies: + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.4.4": + version "7.7.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" + integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== + +"@babel/parser@^7.7.0", "@babel/parser@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.2.tgz#ea8334dc77416bfd9473eb470fd00d8245b3943b" + integrity sha512-DDaR5e0g4ZTb9aP7cpSZLkACEBdoLGwJDWgHtBhrGX7Q1RjhdoMOfexICj5cqTAtpowjGQWfcvfnQG7G2kAB5w== + +"@babel/parser@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb" + integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g== + +"@babel/plugin-proposal-async-generator-functions@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971" + integrity sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + +"@babel/plugin-proposal-async-generator-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" + integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" + "@babel/plugin-syntax-async-generators" "^7.7.4" + +"@babel/plugin-proposal-dynamic-import@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz#dc02a8bad8d653fb59daf085516fa416edd2aa7f" + integrity sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + +"@babel/plugin-proposal-dynamic-import@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d" + integrity sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" + +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + +"@babel/plugin-proposal-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d" + integrity sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.7.4" + +"@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + +"@babel/plugin-proposal-object-rest-spread@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz#9f27075004ab99be08c5c1bd653a2985813cb370" + integrity sha512-3qp9I8lelgzNedI3hrhkvhaEYree6+WHnyA/q4Dza9z7iEIs1eyhWyJnetk3jJ69RT0AT4G0UhEGwyGFJ7GUuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" + +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" + integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz#549fe1717a1bd0a2a7e63163841cb37e78179d5d" + integrity sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.7.tgz#433fa9dac64f953c12578b29633f456b68831c4e" + integrity sha512-80PbkKyORBUVm1fbTLrHpYdJxMThzM1UqFGh0ALEhO9TYbG86Ah9zQYAB/84axz2vcxefDLdZwWwZNlYARlu9w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-async-generators@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889" + integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-dynamic-import@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" + integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-dynamic-import@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" + integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" + integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" + integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" + integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" + integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-top-level-await@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz#f5699549f50bbe8d12b1843a4e82f0a37bb65f4d" + integrity sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-top-level-await@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da" + integrity sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" + integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-arrow-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" + integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-async-to-generator@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz#e2b84f11952cf5913fe3438b7d2585042772f492" + integrity sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.0" + +"@babel/plugin-transform-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" + integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" + +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" + integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-block-scoped-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" + integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-block-scoping@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a" + integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" + +"@babel/plugin-transform-block-scoping@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" + integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz#b411ecc1b8822d24b81e5d184f24149136eddd4a" + integrity sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.0" + "@babel/helper-define-map" "^7.7.0" + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + globals "^11.1.0" + +"@babel/plugin-transform-classes@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" + integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-define-map" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" + integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-computed-properties@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" + integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-destructuring@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" + integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-destructuring@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" + integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz#c5c9ecacab3a5e0c11db6981610f0c32fd698b3b" + integrity sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.7.tgz#3e9713f1b69f339e87fa796b097d73ded16b937b" + integrity sha512-b4in+YlTeE/QmTgrllnb3bHA0HntYvjz8O3Mcbx75UBPJA2xhb5A8nle498VhxSXJHQefjtQxpnLPehDJ4TRlg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-duplicate-keys@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" + integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-duplicate-keys@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91" + integrity sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" + integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" + integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-for-of@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" + integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-for-of@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" + integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-function-name@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz#0fa786f1eef52e3b7d4fc02e54b2129de8a04c2a" + integrity sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" + integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" + integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" + integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-member-expression-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" + integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-member-expression-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" + integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-amd@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" + integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-amd@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c" + integrity sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ== + dependencies: + "@babel/helper-module-transforms" "^7.7.5" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz#3e5ffb4fd8c947feede69cbe24c9554ab4113fe3" + integrity sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg== + dependencies: + "@babel/helper-module-transforms" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.7.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" + integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q== + dependencies: + "@babel/helper-module-transforms" "^7.7.5" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.7.4" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz#9baf471213af9761c1617bb12fd278e629041417" + integrity sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg== + dependencies: + "@babel/helper-hoist-variables" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30" + integrity sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw== + dependencies: + "@babel/helper-hoist-variables" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz#d62c7da16670908e1d8c68ca0b5d4c0097b69966" + integrity sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA== + dependencies: + "@babel/helper-module-transforms" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-umd@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f" + integrity sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw== + dependencies: + "@babel/helper-module-transforms" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz#358e6fd869b9a4d8f5cbc79e4ed4fc340e60dcaf" + integrity sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220" + integrity sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + +"@babel/plugin-transform-new-target@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" + integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-new-target@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" + integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-object-super@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" + integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.5.5" + +"@babel/plugin-transform-object-super@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" + integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.4" + +"@babel/plugin-transform-parameters@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" + integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== + dependencies: + "@babel/helper-call-delegate" "^7.4.4" + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-parameters@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz#7a884b2460164dc5f194f668332736584c760007" + integrity sha512-OhGSrf9ZBrr1fw84oFXj5hgi8Nmg+E2w5L7NhnG0lPvpDtqd7dbyilM2/vR8CKbJ907RyxPh2kj6sBCSSfI9Ew== + dependencies: + "@babel/helper-call-delegate" "^7.7.4" + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-property-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" + integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-property-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" + integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-react-display-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.7.4.tgz#9f2b80b14ebc97eef4a9b29b612c58ed9c0d10dd" + integrity sha512-sBbIvqYkthai0X0vkD2xsAwluBp+LtNHH+/V4a5ydifmTtb8KOVOlrMIk/MYmIc4uTYDnjZUHQildYNo36SRJw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-react-jsx-self@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.7.4.tgz#81b8fbfd14b2215e8f1c2c3adfba266127b0231c" + integrity sha512-PWYjSfqrO273mc1pKCRTIJXyqfc9vWYBax88yIhQb+bpw3XChVC7VWS4VwRVs63wFHKxizvGSd00XEr+YB9Q2A== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.7.4" + +"@babel/plugin-transform-react-jsx-source@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.7.4.tgz#8994b1bf6014b133f5a46d3b7d1ee5f5e3e72c10" + integrity sha512-5ZU9FnPhqtHsOXxutRtXZAzoEJwDaP32QcobbMP1/qt7NYcsCNK8XgzJcJfoEr/ZnzVvUNInNjIW22Z6I8p9mg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.7.4" + +"@babel/plugin-transform-react-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.4.tgz#d91205717fae4e2f84d020cd3057ec02a10f11da" + integrity sha512-LixU4BS95ZTEAZdPaIuyg/k8FiiqN9laQ0dMHB4MlpydHY53uQdWCUrwjLr5o6ilS6fAgZey4Q14XBjl5tL6xw== + dependencies: + "@babel/helper-builder-react-jsx" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.7.4" + +"@babel/plugin-transform-regenerator@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz#f1b20b535e7716b622c99e989259d7dd942dd9cc" + integrity sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-regenerator@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" + integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-reserved-words@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" + integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-reserved-words@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb" + integrity sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" + integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-shorthand-properties@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" + integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" + integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" + integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + +"@babel/plugin-transform-sticky-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" + integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + +"@babel/plugin-transform-template-literals@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" + integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-template-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" + integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typeof-symbol@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e" + integrity sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-unicode-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz#743d9bcc44080e3cc7d49259a066efa30f9187a3" + integrity sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-unicode-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" + integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/preset-env@^7.5.3": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.1.tgz#04a2ff53552c5885cf1083e291c8dd5490f744bb" + integrity sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.7.0" + "@babel/plugin-proposal-dynamic-import" "^7.7.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.7.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-syntax-top-level-await" "^7.7.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.7.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.6.3" + "@babel/plugin-transform-classes" "^7.7.0" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.6.0" + "@babel/plugin-transform-dotall-regex" "^7.7.0" + "@babel/plugin-transform-duplicate-keys" "^7.5.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.4.4" + "@babel/plugin-transform-function-name" "^7.7.0" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-member-expression-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.5.0" + "@babel/plugin-transform-modules-commonjs" "^7.7.0" + "@babel/plugin-transform-modules-systemjs" "^7.7.0" + "@babel/plugin-transform-modules-umd" "^7.7.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.0" + "@babel/plugin-transform-new-target" "^7.4.4" + "@babel/plugin-transform-object-super" "^7.5.5" + "@babel/plugin-transform-parameters" "^7.4.4" + "@babel/plugin-transform-property-literals" "^7.2.0" + "@babel/plugin-transform-regenerator" "^7.7.0" + "@babel/plugin-transform-reserved-words" "^7.2.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.6.2" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.4.4" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.7.0" + "@babel/types" "^7.7.1" + browserslist "^4.6.0" + core-js-compat "^3.1.1" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + +"@babel/preset-env@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.7.tgz#c294167b91e53e7e36d820e943ece8d0c7fe46ac" + integrity sha512-pCu0hrSSDVI7kCVUOdcMNQEbOPJ52E+LrQ14sN8uL2ALfSqePZQlKrOy+tM4uhEdYlCHi4imr8Zz2cZe9oSdIg== + dependencies: + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.7.4" + "@babel/plugin-proposal-dynamic-import" "^7.7.4" + "@babel/plugin-proposal-json-strings" "^7.7.4" + "@babel/plugin-proposal-object-rest-spread" "^7.7.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.7.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.7.7" + "@babel/plugin-syntax-async-generators" "^7.7.4" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" + "@babel/plugin-syntax-json-strings" "^7.7.4" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" + "@babel/plugin-syntax-top-level-await" "^7.7.4" + "@babel/plugin-transform-arrow-functions" "^7.7.4" + "@babel/plugin-transform-async-to-generator" "^7.7.4" + "@babel/plugin-transform-block-scoped-functions" "^7.7.4" + "@babel/plugin-transform-block-scoping" "^7.7.4" + "@babel/plugin-transform-classes" "^7.7.4" + "@babel/plugin-transform-computed-properties" "^7.7.4" + "@babel/plugin-transform-destructuring" "^7.7.4" + "@babel/plugin-transform-dotall-regex" "^7.7.7" + "@babel/plugin-transform-duplicate-keys" "^7.7.4" + "@babel/plugin-transform-exponentiation-operator" "^7.7.4" + "@babel/plugin-transform-for-of" "^7.7.4" + "@babel/plugin-transform-function-name" "^7.7.4" + "@babel/plugin-transform-literals" "^7.7.4" + "@babel/plugin-transform-member-expression-literals" "^7.7.4" + "@babel/plugin-transform-modules-amd" "^7.7.5" + "@babel/plugin-transform-modules-commonjs" "^7.7.5" + "@babel/plugin-transform-modules-systemjs" "^7.7.4" + "@babel/plugin-transform-modules-umd" "^7.7.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.4" + "@babel/plugin-transform-new-target" "^7.7.4" + "@babel/plugin-transform-object-super" "^7.7.4" + "@babel/plugin-transform-parameters" "^7.7.7" + "@babel/plugin-transform-property-literals" "^7.7.4" + "@babel/plugin-transform-regenerator" "^7.7.5" + "@babel/plugin-transform-reserved-words" "^7.7.4" + "@babel/plugin-transform-shorthand-properties" "^7.7.4" + "@babel/plugin-transform-spread" "^7.7.4" + "@babel/plugin-transform-sticky-regex" "^7.7.4" + "@babel/plugin-transform-template-literals" "^7.7.4" + "@babel/plugin-transform-typeof-symbol" "^7.7.4" + "@babel/plugin-transform-unicode-regex" "^7.7.4" + "@babel/types" "^7.7.4" + browserslist "^4.6.0" + core-js-compat "^3.6.0" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + +"@babel/preset-react@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.7.4.tgz#3fe2ea698d8fb536d8e7881a592c3c1ee8bf5707" + integrity sha512-j+vZtg0/8pQr1H8wKoaJyGL2IEk3rG/GIvua7Sec7meXVIvGycihlGMx5xcU00kqCJbwzHs18xTu3YfREOqQ+g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.7.4" + "@babel/plugin-transform-react-jsx" "^7.7.4" + "@babel/plugin-transform-react-jsx-self" "^7.7.4" + "@babel/plugin-transform-react-jsx-source" "^7.7.4" + +"@babel/runtime@^7.6.3": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a" + integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/template@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0" + integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/template@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" + integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09" + integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.2" + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + "@babel/parser" "^7.7.2" + "@babel/types" "^7.7.2" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/traverse@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" + integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@7.0.0-beta.35": + version "7.0.0-beta.35" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.35.tgz#cf933a9a9a38484ca724b335b88d83726d5ab960" + integrity sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w== + dependencies: + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^2.0.0" + +"@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" + integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@babel/types@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" + integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@develar/schema-utils@~2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.1.0.tgz#eceb1695bfbed6f6bb84666d5d3abe5e1fd54e17" + integrity sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +"@electron/get@^1.0.1": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.6.0.tgz#3e1437fa0f436ce9d4e0c27a4c330835ae6d74ed" + integrity sha512-xuvAzbN9iBApfAMvW0hKUpxHR5wPVbG9RaoSTbpu/WaHISDu0MVfMWYhfeU0X730CpBV0G2RkLgwAs9WDan3GA== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + sanitize-filename "^1.6.2" + sumchecker "^3.0.0" + optionalDependencies: + global-agent "^2.0.2" + global-tunnel-ng "^2.7.1" + +"@hot-loader/react-dom@^16.11.0": + version "16.11.0" + resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.11.0.tgz#c0b483923b289db5431516f56ee2a69448ebf9bd" + integrity sha512-cIOVB8YgT4EVCNiXK+gGuYl6adW/TKlW3N7GvgY5QgpL2NTWagF/oJxVscHSdR3O7NjJsoxdseB5spqwCHNIhA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.17.0" + +"@posthtml/esm@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@posthtml/esm/-/esm-1.0.0.tgz#09bcb28a02438dcee22ad1970ca1d85a000ae0cf" + integrity sha512-dEVG+ITnvqKGa4v040tP+n8LOKOqr94qjLva7bE5pnfm2KHJwsKz69J4KMxgWLznbpBJzy8vQfCayEk3vLZnZQ== + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@types/debug@^4.1.4": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" + integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*", "@types/node@^12.0.12": + version "12.12.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.6.tgz#a47240c10d86a9a57bb0c633f0b2e0aea9ce9253" + integrity sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA== + +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@types/react@^16.9.17": + version "16.9.17" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.17.tgz#58f0cc0e9ec2425d1441dd7b623421a867aa253e" + integrity sha512-UP27In4fp4sWF5JgyV6pwVPAQM83Fj76JOcg02X5BZcpSu5Wx+fP9RMqc2v0ssBoQIFvD5JdKY41gjJJKmw6Bg== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + +"@types/webpack-env@^1.13.9": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.1.tgz#0d8a53f308f017c53a5ddc3d07f4d6fa76b790d7" + integrity sha512-0Ki9jAAhKDSuLDXOIMADg54Hu60SuBTEsWaJGGy5cV+SSUQ63J2a+RrYYGrErzz39fXzTibhKrAQJAb8M7PNcA== + +"@webassemblyjs/ast@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" + integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== + dependencies: + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" + +"@webassemblyjs/floating-point-hex-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" + integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== + +"@webassemblyjs/helper-api-error@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" + integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== + +"@webassemblyjs/helper-buffer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" + integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== + +"@webassemblyjs/helper-code-frame@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" + integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== + dependencies: + "@webassemblyjs/wast-printer" "1.8.5" + +"@webassemblyjs/helper-fsm@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" + integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== + +"@webassemblyjs/helper-module-context@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" + integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== + dependencies: + "@webassemblyjs/ast" "1.8.5" + mamacro "^0.0.3" + +"@webassemblyjs/helper-wasm-bytecode@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" + integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== + +"@webassemblyjs/helper-wasm-section@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" + integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + +"@webassemblyjs/ieee754@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" + integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" + integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" + integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== + +"@webassemblyjs/wasm-edit@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" + integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/helper-wasm-section" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-opt" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/wast-printer" "1.8.5" + +"@webassemblyjs/wasm-gen@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" + integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" + +"@webassemblyjs/wasm-opt@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" + integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + +"@webassemblyjs/wasm-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" + integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" + +"@webassemblyjs/wast-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" + integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/floating-point-hex-parser" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-code-frame" "1.8.5" + "@webassemblyjs/helper-fsm" "1.8.5" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" + integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" + integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" + integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + +ajv@^6.1.0, ajv@^6.10.1, ajv@^6.10.2: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + +ansi-colors@^3.0.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + +ansi-html@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +app-builder-bin@3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.4.3.tgz#58a74193eb882f029be6b7f0cd3f0c6805927a6b" + integrity sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg== + +app-builder-lib@21.2.0, app-builder-lib@~21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-21.2.0.tgz#fa1d1604601431e2c3476857e9b9b61d33ad26cc" + integrity sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A== + dependencies: + "7zip-bin" "~5.0.3" + "@develar/schema-utils" "~2.1.0" + async-exit-hook "^2.0.1" + bluebird-lst "^1.0.9" + builder-util "21.2.0" + builder-util-runtime "8.3.0" + chromium-pickle-js "^0.2.0" + debug "^4.1.1" + ejs "^2.6.2" + electron-publish "21.2.0" + fs-extra "^8.1.0" + hosted-git-info "^2.7.1" + is-ci "^2.0.0" + isbinaryfile "^4.0.2" + js-yaml "^3.13.1" + lazy-val "^1.0.4" + minimatch "^3.0.4" + normalize-package-data "^2.5.0" + read-config-file "5.0.0" + sanitize-filename "^1.6.2" + semver "^6.3.0" + temp-file "^3.3.4" + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-exit-hook@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" + integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +autoprefixer@^6.3.1: + version "6.7.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" + integrity sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ= + dependencies: + browserslist "^1.7.6" + caniuse-db "^1.0.30000634" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^5.2.16" + postcss-value-parser "^3.2.3" + +babel-loader@^8.0.6: + version "8.0.6" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" + integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== + dependencies: + find-cache-dir "^2.0.0" + loader-utils "^1.0.2" + mkdirp "^0.5.1" + pify "^4.0.1" + +babel-plugin-component@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-component/-/babel-plugin-component-1.1.1.tgz#9b023a23ff5c9aae0fd56c5a18b9cab8c4d45eea" + integrity sha512-WUw887kJf2GH80Ng/ZMctKZ511iamHNqPhd9uKo14yzisvV7Wt1EckIrb8oq/uCz3B3PpAW7Xfl7AkTLDYT6ag== + dependencies: + "@babel/helper-module-imports" "7.0.0-beta.35" + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +bluebird-lst@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c" + integrity sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw== + dependencies: + bluebird "^3.5.5" + +bluebird@^3.5.4, bluebird@^3.5.5: + version "3.7.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" + integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +boolean@^2.0.2, boolean@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-2.0.3.tgz#da4a5c5a85231d64dd4f6022a0fa5a66adc76653" + integrity sha512-iHzXeFCXWrpjYE7DToXGCBPGZf0eVISqzL+4sgrOSYEKXnb59WHPFvGTTyCj6zJ/MuuLAxEn8zPkrTHHzlt3IA== + +boxen@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" + integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^2.4.2" + cli-boxes "^2.2.0" + string-width "^3.0.0" + term-size "^1.2.0" + type-fest "^0.3.0" + widest-line "^2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + 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@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + integrity sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk= + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + +browserslist@^4.6.0, browserslist@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.2.tgz#1bb984531a476b5d389cedecb195b2cd69fb1348" + integrity sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw== + dependencies: + caniuse-lite "^1.0.30001004" + electron-to-chromium "^1.3.295" + node-releases "^1.1.38" + +browserslist@^4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289" + integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA== + dependencies: + caniuse-lite "^1.0.30001015" + electron-to-chromium "^1.3.322" + node-releases "^1.1.42" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builder-util-runtime@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz#f5fac9139af6facf42a21fbe4d3aebed88fda33e" + integrity sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw== + dependencies: + debug "^4.1.1" + sax "^1.2.4" + +builder-util@21.2.0, builder-util@~21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-21.2.0.tgz#aba721190e4e841009d9fb4b88f1130ed616522f" + integrity sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A== + dependencies: + "7zip-bin" "~5.0.3" + "@types/debug" "^4.1.4" + app-builder-bin "3.4.3" + bluebird-lst "^1.0.9" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^8.1.0" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.13" + stat-mode "^0.3.0" + temp-file "^3.3.4" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cacache@^12.0.2: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +camel-case@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-api@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" + integrity sha1-tTTnxzTE+B7F++isoq0kNUuWLGw= + dependencies: + browserslist "^1.3.6" + caniuse-db "^1.0.30000529" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: + version "1.0.30001008" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001008.tgz#1691f28db0e08bf6abb5e472d8aaea392ec4a995" + integrity sha512-Fog+uREPKb/RDc0puoAqqBZB05I8wYff+TIMDkYw9Lweq7+hUEN5fNLpIaBX6AJxq4sndqPct8fYLrDUV6u4xw== + +caniuse-lite@^1.0.30001004: + version "1.0.30001008" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz#b8841b1df78a9f5ed9702537ef592f1f8772c0d9" + integrity sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw== + +caniuse-lite@^1.0.30001015: + version "1.0.30001015" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0" + integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ== + +catharsis@^0.8.11: + version "0.8.11" + resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.8.11.tgz#d0eb3d2b82b7da7a3ce2efb1a7b00becc6643468" + integrity sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g== + dependencies: + lodash "^4.17.14" + +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chokidar@^2.0.2, chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chownr@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +chromium-pickle-js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" + integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + integrity sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA== + dependencies: + chalk "^1.1.3" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +classnames@^2.2.5: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + +clean-css@4.2.x: + version "4.2.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" + integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== + dependencies: + source-map "~0.6.0" + +cli-boxes@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" + integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +clsx@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" + integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg== + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + integrity sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0= + dependencies: + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +codemirror@^5.49.2: + version "5.49.2" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.49.2.tgz#c84fdaf11b19803f828b0c67060c7bc6d154ccad" + integrity sha512-dwJ2HRPHm8w51WB5YTF9J7m6Z5dtkqbU9ntMZ1dqXyFB9IpjoUFDj80ahRVEoVanfIp6pfASJbOlbWdEf8FOzQ== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.3.0, color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= + dependencies: + color-name "^1.0.0" + +color@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" + integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= + dependencies: + clone "^1.0.2" + color-convert "^1.3.0" + color-string "^0.3.0" + +colormin@^1.0.5: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" + integrity sha1-6i90IKcrlogaOKrlnsEkpvcpgTM= + dependencies: + color "^0.11.0" + css-color-names "0.0.4" + has "^1.0.1" + +colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= + +commander@2.17.x: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== + +commander@^2.19.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@~2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +compressible@~2.0.16: + version "2.0.17" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" + integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw== + dependencies: + mime-db ">= 1.40.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@1.6.2, concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@^1.1.11: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" + integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ== + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + 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@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-compat@^3.1.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.4.0.tgz#2a47c51d3dc026d290018cacd987495f68a47c75" + integrity sha512-pgQUcgT2+v9/yxHgMynYjNj7nmxLRXv3UC39rjCjDwpe63ev2rioQTju1PKLYUBbPCQQvZNWvQC8tBJd65q11g== + dependencies: + browserslist "^4.7.2" + semver "^6.3.0" + +core-js-compat@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.0.tgz#4eb6cb69d03d99159ed7c860cd5fcf7d23a62ea9" + integrity sha512-Z3eCNjGgoYluH89Jt4wVkfYsc/VdLrA2/woX5lm0isO/pCT+P+Y+o65bOuEnjDJLthdwTBxbCVzptTXtc18fJg== + dependencies: + browserslist "^4.8.2" + semver "7.0.0" + +core-js@^2.4.0: + version "2.6.10" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" + integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== + +core-js@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.0.tgz#29ea478601789c72f2978e9bb98f43546f89d3aa" + integrity sha512-lQxb4HScV71YugF/X28LtePZj9AB7WqOpcB+YztYxusvhrgZiQXPmCYfPC5LHsw/+ScEtDbXU3xbqH3CjBRmYA== + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + 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@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +crocket@^0.9.11: + version "0.9.11" + resolved "https://registry.yarnpkg.com/crocket/-/crocket-0.9.11.tgz#288fca11ef0d3dd239b62c488265f30c8edfb0c5" + integrity sha1-KI/KEe8NPdI5tixIgmXzDI7fsMU= + dependencies: + xpipe "*" + +cross-spawn@6.0.5, cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-unzip@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f" + integrity sha1-UYO8R6CVWb78+YzEZXlkmZNZNy8= + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= + +css-color-names@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-hot-loader@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/css-hot-loader/-/css-hot-loader-1.4.4.tgz#ae784932cd8b7d092f7f15702af08b3ec9436052" + integrity sha512-J/qXHz+r7FOT92qMIJfxUk0LC9fecQNZVr0MswQ4FOpKLyOCBjofVMfc6R268bh/5ktkTShrweMr0wWqerC92g== + dependencies: + loader-utils "^1.1.0" + lodash "^4.17.5" + normalize-url "^1.9.1" + +css-loader@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.2.0.tgz#bb570d89c194f763627fcf1f80059c6832d009b2" + integrity sha512-QTF3Ud5H7DaZotgdcJjGMvyDj5F3Pn1j/sC6VBEOVp94cbwqyIBdcs/quzj4MC1BKQSrTpQznegH/5giYbhnCQ== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.17" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.1.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.0" + schema-utils "^2.0.0" + +css-loader@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.4.0.tgz#9fb263436783117a41d014e45e8eaeba54dd6670" + integrity sha512-JornYo4RAXl1Mzt0lOSVPmArzAMV3rGY2VuwtaDc732WTWjdwTaeS19nCGWMcSCf305Q396lhhDAJEWWM0SgPQ== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.23" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.1.1" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.2" + schema-utils "^2.6.0" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-select@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" + integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== + dependencies: + boolbase "^1.0.0" + css-what "^2.1.2" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-what@2.1, css-what@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano@^3.4.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" + integrity sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg= + dependencies: + autoprefixer "^6.3.1" + decamelize "^1.1.2" + defined "^1.0.0" + has "^1.0.1" + object-assign "^4.0.1" + postcss "^5.0.14" + postcss-calc "^5.2.0" + postcss-colormin "^2.1.8" + postcss-convert-values "^2.3.4" + postcss-discard-comments "^2.0.4" + postcss-discard-duplicates "^2.0.1" + postcss-discard-empty "^2.0.1" + postcss-discard-overridden "^0.1.1" + postcss-discard-unused "^2.2.1" + postcss-filter-plugins "^2.0.0" + postcss-merge-idents "^2.1.5" + postcss-merge-longhand "^2.0.1" + postcss-merge-rules "^2.0.3" + postcss-minify-font-values "^1.0.2" + postcss-minify-gradients "^1.0.1" + postcss-minify-params "^1.0.4" + postcss-minify-selectors "^2.0.4" + postcss-normalize-charset "^1.1.0" + postcss-normalize-url "^3.0.7" + postcss-ordered-values "^2.1.0" + postcss-reduce-idents "^2.2.2" + postcss-reduce-initial "^1.0.0" + postcss-reduce-transforms "^1.0.3" + postcss-svgo "^2.1.1" + postcss-unique-selectors "^2.0.2" + postcss-value-parser "^3.2.3" + postcss-zindex "^2.0.1" + +csso@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" + integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== + dependencies: + css-tree "1.0.0-alpha.37" + +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + integrity sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U= + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + +csstype@^2.2.0, csstype@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" + integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.2, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-equal@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.0.tgz#3103cdf8ab6d32cf4a8df7865458f2b8d33f3745" + integrity sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +default-gateway@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" + integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== + dependencies: + execa "^1.0.0" + ip-regex "^2.1.0" + +defer-to-connect@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.0.tgz#b41bd7efa8508cef13f8456975f7a278c72833fd" + integrity sha512-WE2sZoctWm/v4smfCAdjYbrfS55JiMRdlY9ZubFhsYbteCK9+BvAx4YV7nPjYM6ZnX5BcoVKwfmyx9sIFTgQMQ== + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +detect-node@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" + integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dmg-builder@21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-21.2.0.tgz#a9c883557cacb9abdb66c7133b30fe921c1a3ba7" + integrity sha512-9cJEclnGy7EyKFCoHDYDf54pub/t92CQapyiUxU0w9Bj2vUvfoDagP1PMiX4XD5rPp96141h9A+QN0OB4VgvQg== + dependencies: + app-builder-lib "~21.2.0" + bluebird-lst "^1.0.9" + builder-util "~21.2.0" + fs-extra "^8.1.0" + iconv-lite "^0.5.0" + js-yaml "^3.13.1" + sanitize-filename "^1.6.2" + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= + +dns-packet@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" + integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= + dependencies: + buffer-indexof "^1.0.0" + +dom-converter@^0.2: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-helpers@^5.0.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821" + integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw== + dependencies: + "@babel/runtime" "^7.6.3" + csstype "^2.6.7" + +dom-serializer@0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" + integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@1, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1, domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== + +dotenv@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228" + integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ== + +electron-builder@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-21.2.0.tgz#b68ec4def713fc0b8602654ce842f972432f50c5" + integrity sha512-x8EXrqFbAb2L3N22YlGar3dGh8vwptbB3ovo3OF6K7NTpcsmM2zEoJv7GhFyX73rNzSG2HaWpXwGAtOp2JWiEw== + dependencies: + app-builder-lib "21.2.0" + bluebird-lst "^1.0.9" + builder-util "21.2.0" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + dmg-builder "21.2.0" + fs-extra "^8.1.0" + is-ci "^2.0.0" + lazy-val "^1.0.4" + read-config-file "5.0.0" + sanitize-filename "^1.6.2" + update-notifier "^3.0.1" + yargs "^13.3.0" + +electron-devtools-installer@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.4.tgz#261a50337e37121d338b966f07922eb4939a8763" + integrity sha512-b5kcM3hmUqn64+RUcHjjr8ZMpHS2WJ5YO0pnG9+P/RTdx46of/JrEjuciHWux6pE+On6ynWhHJF53j/EDJN0PA== + dependencies: + "7zip" "0.0.6" + cross-unzip "0.0.2" + rimraf "^2.5.2" + semver "^5.3.0" + +electron-publish@21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-21.2.0.tgz#cc225cb46aa62e74b899f2f7299b396c9802387d" + integrity sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA== + dependencies: + bluebird-lst "^1.0.9" + builder-util "~21.2.0" + builder-util-runtime "8.3.0" + chalk "^2.4.2" + fs-extra "^8.1.0" + lazy-val "^1.0.4" + mime "^2.4.4" + +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.295: + version "1.3.306" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.306.tgz#e8265301d053d5f74e36cb876486830261fbe946" + integrity sha512-frDqXvrIROoYvikSKTIKbHbzO6M3/qC6kCIt/1FOa9kALe++c4VAJnwjSFvf1tYLEUsP2n9XZ4XSCyqc3l7A/A== + +electron-to-chromium@^1.3.322: + version "1.3.322" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" + integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA== + +electron-webpack-js@~2.3.2: + version "2.3.4" + resolved "https://registry.yarnpkg.com/electron-webpack-js/-/electron-webpack-js-2.3.4.tgz#f1ffb076530559e48dd5e1b961e8e5be299a5b6c" + integrity sha512-lHP/hqNFkf7WXuo5ABfcpbm920cQdymNI2DnTHH1ZqizJMZE8dPCAn6VVZiY95Z8l5bN9qFz8idKCfuQMN5NCQ== + dependencies: + "@babel/core" "^7.5.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/preset-env" "^7.5.3" + babel-loader "^8.0.6" + babel-plugin-component "^1.1.1" + +electron-webpack@^2.7.4: + version "2.7.4" + resolved "https://registry.yarnpkg.com/electron-webpack/-/electron-webpack-2.7.4.tgz#f1deed156375fbd846ee718bfc9ccf93a2e27207" + integrity sha512-0278nUbG4bANuvrWpLq/CYKJhGwR1gzhAI5IInasbAV8FVA3PyAvu/KMZCZLuVbTxGmWStPg2pdLf1a9alfLCQ== + dependencies: + "@types/webpack-env" "^1.13.9" + async-exit-hook "^2.0.1" + bluebird "^3.5.5" + chalk "^2.4.2" + crocket "^0.9.11" + css-hot-loader "^1.4.4" + css-loader "^3.0.0" + debug "^4.1.1" + dotenv "^8.0.0" + dotenv-expand "^5.1.0" + electron-devtools-installer "^2.2.4" + electron-webpack-js "~2.3.2" + file-loader "^4.0.0" + fs-extra "^8.1.0" + html-loader "^1.0.0-alpha.0" + html-webpack-plugin "^3.2.0" + lazy-val "^1.0.4" + mini-css-extract-plugin "^0.7.0" + node-loader "^0.6.0" + read-config-file "^4.0.1" + semver "^6.2.0" + source-map-support "^0.5.12" + style-loader "^0.23.1" + terser-webpack-plugin "^1.3.0" + url-loader "^2.0.1" + webpack-cli "^3.3.5" + webpack-dev-server "^3.7.2" + webpack-merge "^4.2.1" + yargs "^13.2.4" + +electron@^7: + version "7.1.1" + resolved "https://registry.yarnpkg.com/electron/-/electron-7.1.1.tgz#98be17d850e64689a09ab6dd1e437b36307f2fcf" + integrity sha512-NJPv4SuMJlRUtXBd/Ey9XKSLOZ4+hxsOrHHPXwrBQNNdeZesoSrTMgPymee/FwMRtrSt0Pz8NccEZUu/pxmbhQ== + dependencies: + "@electron/get" "^1.0.1" + "@types/node" "^12.0.12" + extract-zip "^1.0.3" + +elliptic@^6.0.0: + version "6.5.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" + integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +encodeurl@^1.0.2, encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + +enhanced-resolve@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +es-abstract@^1.12.0, es-abstract@^1.5.1: + version "1.16.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-error@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.0, esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eventemitter3@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" + integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== + +events@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + +eventsource@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" + integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== + dependencies: + original "^1.0.0" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + 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.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extract-zip@^1.0.3: + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" + integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= + dependencies: + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" + yauzl "2.4.1" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +faye-websocket@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" + integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= + dependencies: + websocket-driver ">=0.5.1" + +faye-websocket@~0.11.1: + version "0.11.3" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" + integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== + dependencies: + websocket-driver ">=0.5.1" + +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= + dependencies: + pend "~1.2.0" + +figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +file-loader@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.2.0.tgz#5fb124d2369d7075d70a9a5abecd12e60a95215e" + integrity sha512-+xZnaK5R8kBJrHK0/6HRlrKNamvVS5rjyuju+rnyxRGuwUJwpAMsVzUl5dz6rK8brkzjV6JpcFNjp6NqV0g1OQ== + dependencies: + loader-utils "^1.2.3" + schema-utils "^2.0.0" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +findup-sync@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +flatten@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" + integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +follow-redirects@^1.0.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" + integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A== + dependencies: + debug "^3.0.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + dependencies: + nan "^2.12.1" + node-pre-gyp "^0.12.0" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob@^7.0.3, glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-agent@^2.0.2: + version "2.1.5" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.5.tgz#0e9b8367f7068bb6fa360a8f920499e1d873762f" + integrity sha512-pYJjCxxNBzYxo6iNO62JZn8iCFVbvpiM0zE4w/G5hBNIvLjnvzIeCVQPMKc3aK8ju5L7Q8NNI/oBSosU0eeSYw== + dependencies: + boolean "^2.0.2" + core-js "^3.3.3" + es6-error "^4.1.1" + matcher "^2.0.0" + roarr "^2.14.2" + semver "^6.3.0" + serialize-error "^5.0.0" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + dependencies: + ini "^1.3.4" + +global-modules@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +global-tunnel-ng@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" + integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg== + dependencies: + encodeurl "^1.0.2" + lodash "^4.17.10" + npm-conf "^1.1.3" + tunnel "^0.0.6" + +global@^4.3.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globalthis@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.0.tgz#c5fb98213a9b4595f59cf3e7074f141b4169daae" + integrity sha512-vcCAZTJ3r5Qcu5l8/2oyVdoFwxKgfYnMTR2vwWeux/NAVZK3PwcMaWkdUIn4GJbmKuRK7xcvDsLuK+CKcXyodg== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + object-keys "^1.0.12" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +handle-thing@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" + integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoist-non-react-statics@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" + integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== + dependencies: + react-is "^16.7.0" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + +html-entities@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" + integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= + +html-loader@^1.0.0-alpha.0: + version "1.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.0.0-alpha.0.tgz#3f4ae7b490a587619be6d1eaa8ce16683580c642" + integrity sha512-KcuaIRWTU0kFjOJCs32a3JsGNCWkeOak0/F/uvJNp3x/N4McXdqHpcK64cYTozK7QLPKKtUqb9h7wR9K9rYRkg== + dependencies: + "@posthtml/esm" "^1.0.0" + htmlnano "^0.1.6" + loader-utils "^1.1.0" + posthtml "^0.11.2" + schema-utils "^0.4.3" + +html-minifier@^3.2.3: + version "3.5.21" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" + integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== + dependencies: + camel-case "3.0.x" + clean-css "4.2.x" + commander "2.17.x" + he "1.2.x" + param-case "2.1.x" + relateurl "0.2.x" + uglify-js "3.4.x" + +html-webpack-plugin@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" + integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s= + dependencies: + 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" + +htmlnano@^0.1.6: + version "0.1.10" + resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.1.10.tgz#a0a548eb4c76ae2cf2423ec7a25c881734d3dea6" + integrity sha512-eTEUzz8VdWYp+w/KUdb99kwao4reR64epUySyZkQeepcyzPQ2n2EPWzibf6QDxmkGy10Kr+CKxYqI3izSbmhJQ== + dependencies: + cssnano "^3.4.0" + object-assign "^4.0.1" + posthtml "^0.11.3" + posthtml-render "^1.1.4" + svgo "^1.0.5" + terser "^3.8.1" + +htmlparser2@^3.3.0, htmlparser2@^3.9.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +http-cache-semantics@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" + integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +"http-parser-js@>=0.4.0 <0.4.11": + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= + +http-proxy-middleware@0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== + dependencies: + http-proxy "^1.17.0" + is-glob "^4.0.0" + lodash "^4.17.11" + micromatch "^3.1.10" + +http-proxy@^1.17.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" + integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +iconv-lite@0.4.24, iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.0.tgz#59cdde0a2a297cc2aeb0c6445a195ee89f127550" + integrity sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + +immutable@^4.0.0-rc.12: + version "4.0.0-rc.12" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" + integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +import-local@2.0.0, import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +internal-ip@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== + dependencies: + default-gateway "^4.2.0" + ipaddr.js "^1.9.0" + +interpret@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= + +ip@^1.1.0, ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +ipaddr.js@1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" + integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== + +ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + +is-npm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" + integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA== + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-path-cwd@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= + dependencies: + path-is-inside "^1.0.1" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-svg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" + integrity sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk= + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isbinaryfile@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.2.tgz#bfc45642da645681c610cca831022e30af426488" + integrity sha512-C3FSxJdNrEr2F4z6uFtNzECDM5hXk+46fxaa+cwBe5/XrWSmzdG8DDgyjfX6/NRdBB21q2JXuRAzPCUs+fclnQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +js-base64@^2.1.9: + version "2.5.1" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" + integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== + +js-levenshtein@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + integrity sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A= + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +js2xmlparser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.0.tgz#ae14cc711b2892083eed6e219fbc993d858bc3a5" + integrity sha512-WuNgdZOXVmBk5kUPMcTcVUpbGRzLfNkv7+7APq7WiDihpXVKrgxo6wwRpRl9OQeEBgKCVk9mR7RbzrnNWC8oBw== + dependencies: + xmlcreate "^2.0.0" + +jsdoc@^3.6.3: + version "3.6.3" + resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.3.tgz#dccea97d0e62d63d306b8b3ed1527173b5e2190d" + integrity sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A== + dependencies: + "@babel/parser" "^7.4.4" + bluebird "^3.5.4" + catharsis "^0.8.11" + escape-string-regexp "^2.0.0" + js2xmlparser "^4.0.0" + klaw "^3.0.0" + markdown-it "^8.4.2" + markdown-it-anchor "^5.0.2" + marked "^0.7.0" + mkdirp "^0.5.1" + requizzle "^0.2.3" + strip-json-comments "^3.0.1" + taffydb "2.6.2" + underscore "~1.9.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json3@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" + integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== + dependencies: + minimist "^1.2.0" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +killable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" + integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +klaw@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" + integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== + dependencies: + graceful-fs "^4.1.9" + +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +lazy-val@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65" + integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q== + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +linkify-it@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +loader-utils@^0.2.16: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5, lodash@^4.2.0: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +loglevel@^1.6.4: + version "1.6.6" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312" + integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +mamacro@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" + integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-it-anchor@^5.0.2: + version "5.2.5" + resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz#dbf13cfcdbffd16a510984f1263e1d479a47d27a" + integrity sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ== + +markdown-it@^8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" + integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== + dependencies: + argparse "^1.0.7" + entities "~1.1.1" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marked@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" + integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== + +matcher@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-2.0.0.tgz#85fe38d97670dbd2a46590cf099401e2ffb4755c" + integrity sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng== + dependencies: + escape-string-regexp "^2.0.0" + +math-expression-evaluator@^1.2.14: + version "1.2.17" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" + integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +memory-fs@^0.4.0, memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + 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" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== + +"mime-db@>= 1.40.0 < 2": + version "1.42.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" + integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== + +mime-types@~2.1.17, mime-types@~2.1.24: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + dependencies: + mime-db "1.40.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +mini-css-extract-plugin@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.7.0.tgz#5ba8290fbb4179a43dd27cca444ba150bee743a0" + integrity sha512-RQIw6+7utTYn8DBGsf/LpRgZCJMpZt+kuawJ/fju0KiOL6nAaTBNmCJwS7HtwSCXfS47gCkmtBFS7HdsquhdxQ== + dependencies: + loader-utils "^1.1.0" + normalize-url "1.9.1" + schema-utils "^1.0.0" + webpack-sources "^1.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + 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" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + 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@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + 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" + +needle@^2.2.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.5.0, neo-async@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +node-forge@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" + integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== + +node-gyp-build@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.0.tgz#2c2b05f461f4178641a6ce2d7159f04094e9376d" + integrity sha512-4oiumOLhCDU9Rronz8PZ5S4IvT39H5+JEv/hps9V8s7RSLhsac0TCP78ulnHXOo8X1wdpPiTayGlM1jr4IbnaQ== + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + 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.11.0" + vm-browserify "^1.0.1" + +node-loader@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/node-loader/-/node-loader-0.6.0.tgz#c797ef51095ed5859902b157f6384f6361e05ae8" + integrity sha1-x5fvUQle1YWZArFX9jhPY2HgWug= + +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-releases@^1.1.38: + version "1.1.39" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.39.tgz#c1011f30343aff5b633153b10ff691d278d08e8d" + integrity sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA== + dependencies: + semver "^6.3.0" + +node-releases@^1.1.42: + version "1.1.42" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.42.tgz#a999f6a62f8746981f6da90627a8d2fc090bbad7" + integrity sha512-OQ/ESmUqGawI2PRX+XIRao44qWYBBfN54ImQYdWVTQqUckuejOg76ysSqDBK8NG3zwySRVnX36JwDQ6x+9GxzA== + dependencies: + semver "^6.3.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-url@1.9.1, normalize-url@^1.4.0, normalize-url@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= + dependencies: + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-conf@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" + integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== + dependencies: + config-chain "^1.1.11" + pify "^3.0.0" + +npm-packlist@^1.1.6: + version "1.4.6" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" + integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@^1.0.2, nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-is@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" + integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +opn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: + is-wsl "^1.1.0" + +original@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" + integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== + dependencies: + url-parse "^1.4.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^3.0.0, os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-retry@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== + dependencies: + retry "^0.12.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +pako@~1.0.5: + version "1.0.10" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +param-case@2.1.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= + dependencies: + no-case "^2.2.0" + +parse-asn1@^5.0.0: + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +portfinder@^1.0.25: + version "1.0.25" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" + integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.1" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-calc@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" + integrity sha1-d7rnypKK2FcW4v2kLyYb98HWW14= + dependencies: + postcss "^5.0.2" + postcss-message-helpers "^2.0.0" + reduce-css-calc "^1.2.6" + +postcss-colormin@^2.1.8: + version "2.2.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" + integrity sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks= + dependencies: + colormin "^1.0.5" + postcss "^5.0.13" + postcss-value-parser "^3.2.3" + +postcss-convert-values@^2.3.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" + integrity sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0= + dependencies: + postcss "^5.0.11" + postcss-value-parser "^3.1.2" + +postcss-discard-comments@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" + integrity sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0= + dependencies: + postcss "^5.0.14" + +postcss-discard-duplicates@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" + integrity sha1-uavye4isGIFYpesSq8riAmO5GTI= + dependencies: + postcss "^5.0.4" + +postcss-discard-empty@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" + integrity sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU= + dependencies: + postcss "^5.0.14" + +postcss-discard-overridden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" + integrity sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg= + dependencies: + postcss "^5.0.16" + +postcss-discard-unused@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" + integrity sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM= + dependencies: + postcss "^5.0.14" + uniqs "^2.0.0" + +postcss-filter-plugins@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" + integrity sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ== + dependencies: + postcss "^5.0.4" + +postcss-merge-idents@^2.1.5: + version "2.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" + integrity sha1-TFUwMTwI4dWzu/PSu8dH4njuonA= + dependencies: + has "^1.0.1" + postcss "^5.0.10" + postcss-value-parser "^3.1.1" + +postcss-merge-longhand@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" + integrity sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg= + dependencies: + postcss "^5.0.4" + +postcss-merge-rules@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" + integrity sha1-0d9d+qexrMO+VT8OnhDofGG19yE= + dependencies: + browserslist "^1.5.2" + caniuse-api "^1.5.2" + postcss "^5.0.4" + postcss-selector-parser "^2.2.2" + vendors "^1.0.0" + +postcss-message-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" + integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= + +postcss-minify-font-values@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" + integrity sha1-S1jttWZB66fIR0qzUmyv17vey2k= + dependencies: + object-assign "^4.0.1" + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-minify-gradients@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" + integrity sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE= + dependencies: + postcss "^5.0.12" + postcss-value-parser "^3.3.0" + +postcss-minify-params@^1.0.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" + integrity sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM= + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.2" + postcss-value-parser "^3.0.2" + uniqs "^2.0.0" + +postcss-minify-selectors@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" + integrity sha1-ssapjAByz5G5MtGkllCBFDEXNb8= + dependencies: + alphanum-sort "^1.0.2" + has "^1.0.1" + postcss "^5.0.14" + postcss-selector-parser "^2.0.0" + +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" + integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" + +postcss-modules-scope@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb" + integrity sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-scope@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz#33d4fc946602eb5e9355c4165d68a10727689dba" + integrity sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + +postcss-normalize-charset@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" + integrity sha1-757nEhLX/nWceO0WL2HtYrXLk/E= + dependencies: + postcss "^5.0.5" + +postcss-normalize-url@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" + integrity sha1-EI90s/L82viRov+j6kWSJ5/HgiI= + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^1.4.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + +postcss-ordered-values@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" + integrity sha1-7sbCpntsQSqNsgQud/6NpD+VwR0= + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.1" + +postcss-reduce-idents@^2.2.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" + integrity sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM= + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-reduce-initial@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" + integrity sha1-aPgGlfBF0IJjqHmtJA343WT2ROo= + dependencies: + postcss "^5.0.4" + +postcss-reduce-transforms@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" + integrity sha1-/3b02CEkN7McKYpC0uFEQCV3GuE= + dependencies: + has "^1.0.1" + postcss "^5.0.8" + postcss-value-parser "^3.0.1" + +postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^2.1.1: + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" + integrity sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0= + dependencies: + is-svg "^2.0.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + svgo "^0.7.0" + +postcss-unique-selectors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" + integrity sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0= + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== + +postcss-zindex@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" + integrity sha1-0hCd3AVbka9n/EyzsCWUZjnSryI= + dependencies: + has "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.21" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17" + integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^7.0.23: + version "7.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.23.tgz#9f9759fad661b15964f3cfc3140f66f1e05eadc1" + integrity sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +posthtml-parser@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.2.tgz#a132bbdf0cd4bc199d34f322f5c1599385d7c6c1" + integrity sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg== + dependencies: + htmlparser2 "^3.9.2" + +posthtml-render@^1.1.4, posthtml-render@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.5.tgz#387934e85438a3de77085fbc7d264efb00bd0e0f" + integrity sha512-yvt54j0zCBHQVEFAuR+yHld8CZrCa/E1Z/OcFNCV1IEWTLVxT8O7nYnM4IIw1CD4r8kaRd3lc42+0lgCKgm87w== + +posthtml@^0.11.2, posthtml@^0.11.3: + version "0.11.6" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.6.tgz#e349d51af7929d0683b9d8c3abd8166beecc90a8" + integrity sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw== + dependencies: + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +pretty-error@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" + integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= + dependencies: + renderkid "^2.0.1" + utila "~0.4" + +private@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +proxy-addr@~2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" + integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.0" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +querystringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@^1.2.7, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-dom@^16.12.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" + integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.18.0" + +react-draggable@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.2.0.tgz#40cc5209082ca7d613104bf6daf31372cc0e1114" + integrity sha512-5wFq//gEoeTYprnd4ze8GrFc+Rbnx+9RkOMR3vk4EbWxj02U6L6T3yrlKeiw4X5CtjD2ma2+b3WujghcXNRzkw== + dependencies: + classnames "^2.2.5" + prop-types "^15.6.0" + +react-hot-loader@^4.12.18: + version "4.12.18" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.18.tgz#a9029e34af2690d76208f9a35189d73c2dfea6a7" + integrity sha512-qYD0Qi9lIbg9jLyfmodfqvAQqCBsoPKxAhca8Nxvy2/2pO5Q9r2kM28jN0bbbSnhwK8dJ7FjsfVtXKOxMW+bqw== + dependencies: + fast-levenshtein "^2.0.6" + global "^4.3.0" + hoist-non-react-statics "^3.3.0" + loader-utils "^1.1.0" + prop-types "^15.6.1" + react-lifecycles-compat "^3.0.4" + shallowequal "^1.1.0" + source-map "^0.7.3" + +react-is@^16.7.0, react-is@^16.8.1: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" + integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== + +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-virtualized@^9.21.2: + version "9.21.2" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e" + integrity sha512-oX7I7KYiUM7lVXQzmhtF4Xg/4UA5duSA+/ZcAvdWlTLFCoFYq1SbauJT5gZK9cZS/wdYR6TPGpX/dqzvTqQeBA== + dependencies: + babel-runtime "^6.26.0" + clsx "^1.0.1" + dom-helpers "^5.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-lifecycles-compat "^3.0.4" + +react@^16.8: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" + integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + +read-config-file@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-5.0.0.tgz#1487c983fae9c1b672d3acda5cac899a2d451f02" + integrity sha512-jIKUu+C84bfnKxyJ5j30CxCqgXWYjZLXuVE/NYlMEpeni+dhESgAeZOZd0JZbg1xTkMmnCdxksDoarkOyfEsOg== + dependencies: + dotenv "^8.0.0" + dotenv-expand "^5.1.0" + fs-extra "^8.1.0" + js-yaml "^3.13.1" + json5 "^2.1.0" + lazy-val "^1.0.4" + +read-config-file@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-4.0.1.tgz#ece5f6b1a5e6a46d0d93fdd0339f2f60ab892776" + integrity sha512-5caED3uo2IAZMPcbh/9hx/O29s2430RLxtnFDdzxpH/epEpawOrQnGBHueotIXUrGPPIgdNQN+S/CIp2WmiSfw== + dependencies: + ajv "^6.10.1" + ajv-keywords "^3.4.1" + dotenv "^8.0.0" + dotenv-expand "^5.1.0" + fs-extra "^8.1.0" + js-yaml "^3.13.1" + json5 "^2.1.0" + lazy-val "^1.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +reduce-css-calc@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" + integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= + dependencies: + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-function-call@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.3.tgz#60350f7fb252c0a67eb10fd4694d16909971300f" + integrity sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ== + dependencies: + balanced-match "^1.0.0" + +regenerate-unicode-properties@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== + +regenerator-transform@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== + dependencies: + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" + integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== + dependencies: + define-properties "^1.1.2" + +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +registry-auth-token@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.0.0.tgz#30e55961eec77379da551ea5c4cf43cbf03522be" + integrity sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw== + dependencies: + rc "^1.2.8" + safe-buffer "^5.0.1" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +regjsgen@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + dependencies: + jsesc "~0.5.0" + +relateurl@0.2.x: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +renderkid@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149" + integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA== + dependencies: + css-select "^1.1.0" + dom-converter "^0.2" + htmlparser2 "^3.3.0" + strip-ansi "^3.0.0" + utila "^0.4.0" + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +requizzle@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.3.tgz#4675c90aacafb2c036bd39ba2daa4a1cb777fded" + integrity sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ== + dependencies: + lodash "^4.17.14" + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.10.0, resolve@^1.3.2: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +roarr@^2.14.2: + version "2.14.4" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.14.4.tgz#2d9d26864ce95ce570b4b5c5e548aefd40bb2bf7" + integrity sha512-QMzRAQGZFPgnx4nNWp4Q+WHfiZh2HTSEjNaxFLrEIj3PmcQ1GHL5OjaaIyF9ybUDD2aZ9t3Awc/obrRPils9ng== + dependencies: + boolean "^2.0.3" + detect-node "^2.0.4" + globalthis "^1.0.0" + json-stringify-safe "^5.0.1" + semver-compare "^1.0.0" + sprintf-js "^1.1.2" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sanitize-filename@^1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + +sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +scheduler@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" + integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +scheduler@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" + integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +schema-utils@^0.4.3: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^2.0.0, schema-utils@^2.4.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.5.0.tgz#8f254f618d402cc80257486213c8970edfd7c22f" + integrity sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + +schema-utils@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.1.tgz#eb78f0b945c7bcfa2082b3565e8db3548011dc4f" + integrity sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= + +selfsigned@^1.10.7: + version "1.10.7" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" + integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== + dependencies: + node-forge "0.9.0" + +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= + dependencies: + semver "^5.0.3" + +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + 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.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-error@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac" + integrity sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA== + dependencies: + type-fest "^0.8.0" + +serialize-javascript@^1.7.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" + integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== + +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sockjs-client@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" + integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== + dependencies: + debug "^3.2.5" + eventsource "^1.0.7" + faye-websocket "~0.11.1" + inherits "^2.0.3" + json3 "^3.3.2" + url-parse "^1.4.3" + +sockjs@0.3.19: + version "0.3.19" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" + integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw== + dependencies: + faye-websocket "^0.10.0" + uuid "^3.0.1" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= + dependencies: + is-plain-obj "^1.0.0" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.5.12, source-map-support@^0.5.13, source-map-support@^0.5.16, source-map-support@~0.5.10, source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" + integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stat-mode@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.3.0.tgz#69283b081f851582b328d2a4ace5f591ce52f54b" + integrity sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng== + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +style-loader@^0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" + integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg== + dependencies: + loader-utils "^1.1.0" + schema-utils "^1.0.0" + +sumchecker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.0.tgz#da5457b4605184575c76540e5e99cc777cb8ce4c" + integrity sha512-yreseuC/z4iaodVoq07XULEOO9p4jnQazO7mbrnDSvWAU/y2cbyIKs+gWJptfcGu9R+1l27K8Rkj0bfvqnBpgQ== + dependencies: + debug "^4.1.0" + +supports-color@6.1.0, supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + integrity sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U= + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + +svgo@^1.0.5: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +taffydb@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" + integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg= + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tar@^4: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +temp-file@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.3.4.tgz#73af868cd7cb7400a44e4bb03e653b2280ce2878" + integrity sha512-qSZ5W5q54iyGnP8cNl49RE0jTJc5CrzNocux5APD5yIxcgonoMuMSbsZfaZy8rTGCYo0Xz6ySVv3adagZ8gffg== + dependencies: + async-exit-hook "^2.0.1" + fs-extra "^8.1.0" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= + dependencies: + execa "^0.7.0" + +terser-webpack-plugin@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" + integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^1.7.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser@^3.8.1: + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== + dependencies: + commander "^2.19.0" + source-map "~0.6.1" + source-map-support "~0.5.10" + +terser@^4.1.2: + version "4.3.9" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.9.tgz#e4be37f80553d02645668727777687dad26bbca8" + integrity sha512-NFGMpHjlzmyOtPL+fDw3G7+6Ueh/sz4mkaUYa4lJCxOPTNzd0Uj0aZJOmsDYoSQyfuVoWDMSWTPU3huyOm2zdA== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +toposort@^1.0.0: + version "1.0.7" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" + integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= + +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= + dependencies: + utf8-byte-length "^1.0.1" + +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +uglify-js@3.4.x: + version "3.4.10" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" + integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== + dependencies: + commander "~2.19.0" + source-map "~0.6.1" + +underscore@~1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= + dependencies: + crypto-random-string "^1.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +update-notifier@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" + integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ== + dependencies: + boxen "^3.0.0" + chalk "^2.0.1" + configstore "^4.0.0" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.1.0" + is-npm "^3.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-loader@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.2.0.tgz#af321aece1fd0d683adc8aaeb27829f29c75b46e" + integrity sha512-G8nk3np8ZAnwhHXas1JxJEwJyQdqFXAKJehfgZ/XrC48volFBRtO+FIKtF2u0Ma3bw+4vnDVjHPAQYlF9p2vsw== + dependencies: + loader-utils "^1.2.3" + mime "^2.4.4" + schema-utils "^2.4.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-parse@^1.4.3: + version "1.4.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" + integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@1.0.0, util.promisify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utila@^0.4.0, utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.0.1, uuid@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + +v8-compile-cache@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" + integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +vendors@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" + integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +watchpack@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webpack-cli@^3.3.5: + version "3.3.10" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" + integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== + dependencies: + chalk "2.4.2" + cross-spawn "6.0.5" + enhanced-resolve "4.1.0" + findup-sync "3.0.0" + global-modules "2.0.0" + import-local "2.0.0" + interpret "1.2.0" + loader-utils "1.2.3" + supports-color "6.1.0" + v8-compile-cache "2.0.3" + yargs "13.2.4" + +webpack-dev-middleware@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" + integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + +webpack-dev-server@^3.7.2: + version "3.9.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz#27c3b5d0f6b6677c4304465ac817623c8b27b89c" + integrity sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw== + dependencies: + ansi-html "0.0.7" + bonjour "^3.5.0" + chokidar "^2.1.8" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + debug "^4.1.1" + del "^4.1.1" + express "^4.17.1" + html-entities "^1.2.1" + http-proxy-middleware "0.19.1" + import-local "^2.0.0" + internal-ip "^4.3.0" + ip "^1.1.5" + is-absolute-url "^3.0.3" + killable "^1.0.1" + loglevel "^1.6.4" + opn "^5.5.0" + p-retry "^3.0.1" + portfinder "^1.0.25" + schema-utils "^1.0.0" + selfsigned "^1.10.7" + semver "^6.3.0" + serve-index "^1.9.1" + sockjs "0.3.19" + sockjs-client "1.4.0" + spdy "^4.0.1" + strip-ansi "^3.0.1" + supports-color "^6.1.0" + url "^0.11.0" + webpack-dev-middleware "^3.7.2" + webpack-log "^2.0.0" + ws "^6.2.1" + yargs "12.0.5" + +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== + dependencies: + ansi-colors "^3.0.0" + uuid "^3.3.2" + +webpack-merge@^4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== + dependencies: + lodash "^4.17.15" + +webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.41.4: + version "4.41.4" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.4.tgz#4bec4125224bdf50efa8be6226c19047599cd034" + integrity sha512-Lc+2uB6NjpCWsHI3trkoISOI64h9QYIXenbEWj3bn3oyjfB1lEBXjWAfAyY2sM0rZn41oD5V91OLwKRwS6Wp8Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.0" + webpack-sources "^1.4.1" + +websocket-driver@>=0.5.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" + integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== + dependencies: + http-parser-js ">=0.4.0 <0.4.11" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" + integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^2.0.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +ws@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= + +xmlcreate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.1.tgz#2ec38bd7b708d213fd1a90e2431c4af9c09f6a52" + integrity sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA== + +xpipe@*: + version "1.0.5" + resolved "https://registry.yarnpkg.com/xpipe/-/xpipe-1.0.5.tgz#8dd8bf45fc3f7f55f0e054b878f43a62614dafdf" + integrity sha1-jdi/Rfw/f1Xw4FS4ePQ6YmFNr98= + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^13.1.0, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== + dependencies: + cliui "^4.0.0" + decamelize "^1.2.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 "^11.1.1" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0" + +yargs@^13.2.4, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= + dependencies: + fd-slicer "~1.0.1" + +zeromq@^6.0.0-beta.5: + version "6.0.0-beta.5" + resolved "https://registry.yarnpkg.com/zeromq/-/zeromq-6.0.0-beta.5.tgz#098505fcb66beb78eeb0c541efe415d3e2090292" + integrity sha512-zsSbjfLjDxQq/Mp6NemNK/AVpm1NeafJRgz7nos1nV9MI/3w/P76pFdlqzxRTW4cuNqyFXJ4Q7g2tUhaZi4rcg== + dependencies: + node-gyp-build "^4.1.0" -- GitLab