From be8aff17c9b5f7215841a353c95a424e0fe49d1d Mon Sep 17 00:00:00 2001 From: smolck <46855713+smolck@users.noreply.github.com> Date: Sun, 18 Oct 2020 11:39:21 -0500 Subject: [PATCH] Switch from hyperapp -> inferno (#20) * Hyperapp is no longer a dep, use inferno instead * Switch to using JSX via Babel (so to do type checking run `npm run check-types`) * Added feather-icons dependency * Various changes that I won't list Co-authored-by: Christian Clason --- .babelrc | 10 + .npmignore | 2 + .prettierrc.json | 4 +- package-lock.json | 3669 +++++++++++++---- package.json | 23 +- src/bootstrap/galaxy.ts | 40 +- src/bootstrap/index.html | 19 +- src/components/README.md | 8 + src/components/autocomplete.ts | 358 -- src/components/buffers.ts | 96 - src/components/change-project.ts | 200 - src/components/code-action.ts | 139 - src/components/command-line.ts | 140 - src/components/explorer.ts | 273 -- src/components/extensions/buffers.tsx | 116 + .../color-picker.tsx} | 92 +- src/components/extensions/explorer.tsx | 297 ++ src/components/extensions/files.tsx | 151 + .../extensions/future/change-project.tsx | 204 + .../extensions/future/generic-menu.tsx | 122 + .../extensions/future/generic-prompt.tsx | 66 + .../extensions/future/vim-create.tsx | 50 + .../extensions/future/vim-rename.tsx | 52 + .../extensions/future/vim-switch.tsx | 101 + src/components/extensions/grep.tsx | 347 ++ .../{ => extensions/legacy}/buffer-search.ts | 0 .../{ => extensions/legacy}/debug.ts | 0 .../{ => extensions/legacy}/divination.ts | 0 .../legacy}/inventory-search.ts | 0 .../{ => extensions/legacy}/inventory.ts | 0 .../{ => extensions/legacy}/problem-info.ts | 0 .../{ => extensions/legacy}/spell-check.ts | 0 .../{ => extensions/legacy}/user-menu.ts | 0 .../legacy}/user-overlay-menu.ts | 0 .../legacy}/viewport-search.ts | 2 +- src/components/extensions/lsp-code-action.tsx | 135 + src/components/extensions/lsp-hover.tsx | 115 + src/components/extensions/lsp-references.tsx | 307 ++ .../extensions/lsp-signature-help.tsx | 211 + src/components/files.ts | 154 - src/components/filetype-icon.ts | 76 - src/components/filetype-icon.tsx | 66 + src/components/generic-menu.ts | 110 - src/components/generic-prompt.ts | 59 - src/components/grep.ts | 356 -- src/components/hint.ts | 208 - src/components/hover.ts | 106 - src/components/icon.tsx | 8 + src/components/loading.ts | 24 - src/components/loading.tsx | 25 + src/components/memes/nc.tsx | 45 + src/components/message-history.ts | 162 - src/components/messages.ts | 416 -- src/components/nc.ts | 39 - src/components/nvim/autocomplete.tsx | 345 ++ src/components/nvim/command-line.tsx | 135 + src/components/nvim/message-history.tsx | 167 + src/components/nvim/messages.tsx | 367 ++ src/components/nvim/search.tsx | 105 + src/components/nvim/statusline.tsx | 456 ++ src/components/overlay.ts | 64 - src/components/overlay.tsx | 40 + src/components/plugin-container.ts | 127 - src/components/plugin-container.tsx | 121 + src/components/references.ts | 321 -- src/components/row-container.ts | 123 - src/components/row-container.tsx | 120 + src/components/statusline.ts | 479 --- src/components/text-input.ts | 222 - src/components/text-input.tsx | 228 + src/components/vim-create.ts | 41 - src/components/vim-rename.ts | 41 - src/components/vim-search.ts | 117 - src/components/vim-switch.ts | 84 - src/core/cursor.ts | 18 +- src/core/input.ts | 10 +- src/core/instance-api.ts | 2 +- src/core/master-control.ts | 6 +- src/dev/recorder.ts | 2 +- src/inventory/actions.ts | 2 +- src/neovim/api.ts | 58 +- src/neovim/state.ts | 23 +- src/render/events.ts | 4 +- src/tsconfig.json | 9 +- src/ui/color-picker.ts | 507 --- src/ui/color-picker.tsx | 439 ++ src/ui/css.ts | 16 +- src/ui/styles.ts | 8 +- src/ui/uikit.ts | 64 +- src/windows/nameplate.ts | 150 - src/windows/nameplate.tsx | 121 + tools/build.js | 2 +- tools/start.js | 18 +- 93 files changed, 8117 insertions(+), 6248 deletions(-) create mode 100644 .babelrc create mode 100644 .npmignore create mode 100644 src/components/README.md delete mode 100644 src/components/autocomplete.ts delete mode 100644 src/components/buffers.ts delete mode 100644 src/components/change-project.ts delete mode 100644 src/components/code-action.ts delete mode 100644 src/components/command-line.ts delete mode 100644 src/components/explorer.ts create mode 100644 src/components/extensions/buffers.tsx rename src/components/{color-picker.ts => extensions/color-picker.tsx} (58%) create mode 100644 src/components/extensions/explorer.tsx create mode 100644 src/components/extensions/files.tsx create mode 100644 src/components/extensions/future/change-project.tsx create mode 100644 src/components/extensions/future/generic-menu.tsx create mode 100644 src/components/extensions/future/generic-prompt.tsx create mode 100644 src/components/extensions/future/vim-create.tsx create mode 100644 src/components/extensions/future/vim-rename.tsx create mode 100644 src/components/extensions/future/vim-switch.tsx create mode 100644 src/components/extensions/grep.tsx rename src/components/{ => extensions/legacy}/buffer-search.ts (100%) rename src/components/{ => extensions/legacy}/debug.ts (100%) rename src/components/{ => extensions/legacy}/divination.ts (100%) rename src/components/{ => extensions/legacy}/inventory-search.ts (100%) rename src/components/{ => extensions/legacy}/inventory.ts (100%) rename src/components/{ => extensions/legacy}/problem-info.ts (100%) rename src/components/{ => extensions/legacy}/spell-check.ts (100%) rename src/components/{ => extensions/legacy}/user-menu.ts (100%) rename src/components/{ => extensions/legacy}/user-overlay-menu.ts (100%) rename src/components/{ => extensions/legacy}/viewport-search.ts (98%) create mode 100644 src/components/extensions/lsp-code-action.tsx create mode 100644 src/components/extensions/lsp-hover.tsx create mode 100644 src/components/extensions/lsp-references.tsx create mode 100644 src/components/extensions/lsp-signature-help.tsx delete mode 100644 src/components/files.ts delete mode 100644 src/components/filetype-icon.ts create mode 100644 src/components/filetype-icon.tsx delete mode 100644 src/components/generic-menu.ts delete mode 100644 src/components/generic-prompt.ts delete mode 100644 src/components/grep.ts delete mode 100644 src/components/hint.ts delete mode 100644 src/components/hover.ts create mode 100644 src/components/icon.tsx delete mode 100644 src/components/loading.ts create mode 100644 src/components/loading.tsx create mode 100644 src/components/memes/nc.tsx delete mode 100644 src/components/message-history.ts delete mode 100644 src/components/messages.ts delete mode 100644 src/components/nc.ts create mode 100644 src/components/nvim/autocomplete.tsx create mode 100644 src/components/nvim/command-line.tsx create mode 100644 src/components/nvim/message-history.tsx create mode 100644 src/components/nvim/messages.tsx create mode 100644 src/components/nvim/search.tsx create mode 100644 src/components/nvim/statusline.tsx delete mode 100644 src/components/overlay.ts create mode 100644 src/components/overlay.tsx delete mode 100644 src/components/plugin-container.ts create mode 100644 src/components/plugin-container.tsx delete mode 100644 src/components/references.ts delete mode 100644 src/components/row-container.ts create mode 100644 src/components/row-container.tsx delete mode 100644 src/components/statusline.ts delete mode 100644 src/components/text-input.ts create mode 100644 src/components/text-input.tsx delete mode 100644 src/components/vim-create.ts delete mode 100644 src/components/vim-rename.ts delete mode 100644 src/components/vim-search.ts delete mode 100644 src/components/vim-switch.ts delete mode 100644 src/ui/color-picker.ts create mode 100644 src/ui/color-picker.tsx delete mode 100644 src/windows/nameplate.ts create mode 100644 src/windows/nameplate.tsx diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..cf8be55a --- /dev/null +++ b/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": ["@babel/preset-typescript"], + "plugins": [ + ["babel-plugin-inferno", { "imports": true }], + "@babel/plugin-proposal-object-rest-spread", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-transform-modules-commonjs" + ], + "ignore": ["**/legacy/", "**/future/"] +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..52bb78cc --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +**/legacy/ +**/future/ diff --git a/.prettierrc.json b/.prettierrc.json index b2095be8..85602a3e 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,4 +1,6 @@ { "semi": false, - "singleQuote": true + "singleQuote": true, + "quoteProps": "as-needed", + "jsxSingleQuote": true } diff --git a/package-lock.json b/package-lock.json index 4096985d..4375487c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,14 +10,376 @@ "integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA==", "dev": true }, - "@deomitrus/hyperapp-redux-devtools": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@deomitrus/hyperapp-redux-devtools/-/hyperapp-redux-devtools-1.2.0.tgz", - "integrity": "sha512-GEI7c1Ubv7vz3ePBi0anatROrLfHJCqp8rSX2la2GnBfby5/yoltFz4qnvoPmzpJ7aWHL+sJm4u4TyyigFDwow==", + "@babel/cli": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.12.1.tgz", + "integrity": "sha512-eRJREyrfAJ2r42Iaxe8h3v6yyj1wu9OyosaUHW6UImjGf9ahGL9nsFNh7OCopvtcPL8WnEo7tp78wrZaZ6vG9g==", + "dev": true, + "requires": { + "@nicolo-ribaudo/chokidar-2": "^2.1.8", + "chokidar": "^3.4.0", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/core": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", + "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.1", + "@babel/parser": "^7.12.3", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", + "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", + "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz", + "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-module-imports": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz", + "integrity": "sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-module-transforms": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", + "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-simple-access": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/helper-validator-identifier": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz", + "integrity": "sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-simple-access": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", + "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.1.tgz", + "integrity": "sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", + "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", + "dev": true + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz", + "integrity": "sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.12.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz", + "integrity": "sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-typescript": "^7.12.1" + } + }, + "@babel/preset-typescript": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.1.tgz", + "integrity": "sha512-hNK/DhmoJPsksdHuI/RVrcEws7GN5eamhi28JkO52MqIxU8Z0QpmiSOQxZHWOHV7I3P4UjHV97ay4TcamMA6Kw==", "dev": true, "requires": { - "redux": "^3.7.2", - "redux-devtools-extension": "^2.13.2" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.12.1" + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", + "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.1", + "@babel/types": "^7.12.1", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" } }, "@develar/schema-utils": { @@ -56,12 +418,6 @@ "ms": "2.1.2" } }, - "env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", - "dev": true - }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -73,26 +429,11 @@ "universalify": "^0.1.0" } }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true - }, - "sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "requires": { - "debug": "^4.1.0" - } } } }, @@ -102,6 +443,39 @@ "integrity": "sha512-gV4jOsGpiWNDGd8Dw7tod1Fc9Gc7StaOT4oZ/6srHRWtsHU+HYWzmkYsa3Qy/z0e9tY1WpJ9wWdBFGskfbzoug==", "dev": true }, + "@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8.tgz", + "integrity": "sha512-FohwULwAebCUKi/akMFyGi7jfc7JXTeMHzKxuP3umRd9mK/2Y7/SMBSI2jX+YLopPXi+PF9l307NmpfxTdCegA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "2.1.8" + }, + "dependencies": { + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "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" + } + } + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -129,12 +503,6 @@ "@types/responselike": "*" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, "@types/debug": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", @@ -183,6 +551,21 @@ "@types/node": "*" } }, + "@types/lodash": { + "version": "4.14.162", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.162.tgz", + "integrity": "sha512-alvcho1kRUnnD1Gcl4J+hK0eencvzq9rmzvFPRmP5rPHx9VVsJj6bKLTATPVf9ktgv4ujzh7T+XWKp+jhuODig==", + "dev": true + }, + "@types/lodash.merge": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/@types/lodash.merge/-/lodash.merge-4.6.6.tgz", + "integrity": "sha512-IB90krzMf7YpfgP3u/EvZEdXVvm4e3gJbUvh5ieuI+o+XqiNEt6fCzqNRaiLlPVScLI59RxIGZMQ3+Ko/DJ8vQ==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, "@types/marked": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@types/marked/-/marked-1.1.0.tgz", @@ -220,9 +603,9 @@ "dev": true }, "@types/yargs": { - "version": "15.0.8", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.8.tgz", - "integrity": "sha512-b0BYzFUzBpOhPjpl1wtAHU994jBeKF4TKVlT7ssFv44T617XNcPdRoG4AzHLVshLzlrF7i3lTelH7UbuNYV58Q==", + "version": "15.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz", + "integrity": "sha512-HmU8SeIRhZCWcnRskCs36Q1Q00KBV6Cqh/ora8WN1+22dY07AZdn6Gel8QZ3t26XYPImtcL8WV/eqjhVmMEw4g==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -251,20 +634,20 @@ "dev": true }, "@wdio/config": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-6.4.7.tgz", - "integrity": "sha512-wtcj9yKm5+SivwhsgpusBrFR7a3rpDsN/WH6ekoqlZFs7oCpJeTLwawWnoX6MJQy2no5o00lGxDDJnqjaBdiiQ==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-6.6.3.tgz", + "integrity": "sha512-zJjPpjJu05els9A2ZzOVMAYccaHSXmmqQ2h+ftelXmFgO4mYDlKufx0HaCZDdn+O0SCG0ASqv+u1KNuqmNhjDw==", "dev": true, "requires": { - "@wdio/logger": "6.4.7", + "@wdio/logger": "6.6.0", "deepmerge": "^4.0.0", "glob": "^7.1.2" } }, "@wdio/logger": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-6.4.7.tgz", - "integrity": "sha512-Mm/rsRa/1u/l8/IrNKM2c9tkvLE90i83d3KZ0Ujh4cicYJv+lNi9whsCi+p3QNFCo64nJ6bfC+0Ho5VgD3MiKw==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-6.6.0.tgz", + "integrity": "sha512-BAvXcnlWdQC93MLWObetpcjHUEGR8niW2mH2KAwLPQhXwJkKxXjhlMKH/DmUn5uQ4/S7iySLlMq9EEEg9KuCwA==", "dev": true, "requires": { "chalk": "^4.0.0", @@ -279,6 +662,46 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -287,31 +710,40 @@ "requires": { "ansi-regex": "^5.0.0" } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "@wdio/protocols": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-6.3.6.tgz", - "integrity": "sha512-cocBRkv5sYUBxXResuxskQhIkKgDgE/yAtgMGR5wXLrtG/sMpZ2HVy6LOcOeARidAaRwbav80M2ZHjTCjPn53w==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-6.6.0.tgz", + "integrity": "sha512-0wWSZTB4sBzr9HG3hT9a0jaO+xPhz+eFdE/qMLvM8b1yPOOgHieGPSoTXPjkBaks0CZpqeimbT4myYoim2JK1w==", "dev": true }, "@wdio/repl": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-6.5.0.tgz", - "integrity": "sha512-qKm2j0qY7mrZQipHv4PhKpAL7pkyxCzW1XDoEjp09OHLvmGvvCwY6aEBuLziD9BaiR30BXVNLIKPZfM4Xl2Zfg==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-6.6.3.tgz", + "integrity": "sha512-j+Euu/UvvSkcgGAzcI6QXmOGs0/ZhUo22Un3mrtSKotyjHDqoJW8Oz33etutug6svWGNV9ECNp/zzrwvzRyZyg==", "dev": true, "requires": { - "@wdio/utils": "6.5.0" + "@wdio/utils": "6.6.3" } }, "@wdio/utils": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-6.5.0.tgz", - "integrity": "sha512-k5RxRj/re/BbK76SjWSmyhJFHWnXD74vl/doCAQNuOaKFBd2dqMCs3GiFjYCyLcU37XGMAnRvI3tKHflyLGJYw==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-6.6.3.tgz", + "integrity": "sha512-vZf4vyBJNlkOOwADoZmzkCtdkeNfc9DKr+TbhDnf8atHksL2AKgqoB2VdZ0F19WAw2X59OrFLIWVH0mnuGEMEA==", "dev": true, "requires": { - "@wdio/logger": "6.4.7" + "@wdio/logger": "6.6.0" } }, "agent-base": { @@ -321,9 +753,9 @@ "dev": true }, "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -347,12 +779,6 @@ "string-width": "^3.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -363,15 +789,6 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, @@ -382,9 +799,9 @@ "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { @@ -397,13 +814,26 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, + "optional": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, "app-builder-bin": { @@ -456,6 +886,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true } } }, @@ -472,6 +908,25 @@ "readdir-glob": "^1.0.0", "tar-stream": "^2.1.4", "zip-stream": "^4.0.0" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "archiver-utils": { @@ -490,29 +945,6 @@ "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^2.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } } }, "argparse": { @@ -522,8 +954,44 @@ "dev": true, "requires": { "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "optional": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "optional": true + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -539,12 +1007,26 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "optional": true + }, "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": true + }, "async-exit-hook": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", @@ -581,12 +1063,97 @@ "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-inferno": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-inferno/-/babel-plugin-inferno-6.1.1.tgz", + "integrity": "sha512-uyFJZ1gMRokXA2gFCQhxM9V0V9daOpgCiMj8Qp/gkJN0zW471ozPoTPppt+pmm+soxWyU7UmLMxa3/cqsBGm+Q==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7", + "@babel/types": "^7" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "optional": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -603,10 +1170,21 @@ } }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } }, "bl": { "version": "4.0.3", @@ -619,11 +1197,16 @@ "readable-stream": "^3.4.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } } } }, @@ -665,12 +1248,6 @@ "widest-line": "^3.1.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -705,44 +1282,33 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "has-flag": "^4.0.0" } }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -750,12 +1316,34 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, + "optional": true, "requires": { - "fill-range": "^7.0.1" + "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" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "browser-stdout": { @@ -781,9 +1369,9 @@ "dev": true }, "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "builder-util": { @@ -808,6 +1396,40 @@ "temp-file": "^3.3.7" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "debug": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.0.tgz", @@ -817,11 +1439,26 @@ "ms": "2.1.2" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, @@ -852,6 +1489,24 @@ } } }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "optional": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, "cacheable-lookup": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz", @@ -874,9 +1529,9 @@ }, "dependencies": { "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" @@ -903,40 +1558,14 @@ "dev": true }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "chokidar": { @@ -953,6 +1582,91 @@ "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.5.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "chownr": { @@ -987,6 +1701,36 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "optional": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "cli-boxes": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", @@ -994,40 +1738,29 @@ "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz", + "integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } } } @@ -1041,13 +1774,24 @@ "mimic-response": "^1.0.0" } }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "optional": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -1065,6 +1809,19 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true, + "optional": true + }, "compress-commons": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.0.1.tgz", @@ -1075,6 +1832,19 @@ "crc32-stream": "^4.0.0", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "concat-map": { @@ -1093,23 +1863,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } } }, "config-chain": { @@ -1135,8 +1888,46 @@ "unique-string": "^2.0.0", "write-file-atomic": "^3.0.0", "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" } }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "optional": true + }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1160,6 +1951,19 @@ "requires": { "crc": "^3.4.4", "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "crypto-random-string": { @@ -1198,6 +2002,13 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "optional": true + }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -1220,9 +2031,9 @@ "dev": true }, "defer-to-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", - "integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, "define-properties": { @@ -1230,17 +2041,52 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, - "optional": true, "requires": { "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, - "optional": true + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, @@ -1264,25 +2110,26 @@ "dev": true }, "devtools": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-6.5.0.tgz", - "integrity": "sha512-P/9+jSK+Jq4gWO5a79OLtDsZPcrNZN9JDCqWdCmKcbCCikV3fYic+0wmRzAPff8iYLCdmNXf/no4XMLwXR5LXQ==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/devtools/-/devtools-6.6.3.tgz", + "integrity": "sha512-tT4dXTZlE51pbCnT/FmoL4m07OkdbGZ3GtDabaGGSqoxxSorna11FOZX2I6vMc31ZDLQJpErPHScY8S0Q8iIGA==", "dev": true, "requires": { - "@wdio/config": "6.4.7", - "@wdio/logger": "6.4.7", - "@wdio/protocols": "6.3.6", - "@wdio/utils": "6.5.0", + "@wdio/config": "6.6.3", + "@wdio/logger": "6.6.0", + "@wdio/protocols": "6.6.0", + "@wdio/utils": "6.6.3", "chrome-launcher": "^0.13.1", + "edge-paths": "^2.1.0", "puppeteer-core": "^5.1.0", "ua-parser-js": "^0.7.21", "uuid": "^8.0.0" }, "dependencies": { "uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", "dev": true } } @@ -1355,6 +2202,12 @@ "safer-buffer": "^2.1.0" } }, + "edge-paths": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-2.1.0.tgz", + "integrity": "sha512-ZpIN1Vm5hlo9dkkST/1s8QqPNne2uwk3Plf6HcVUhnpfal0WnDRLdNj/wdQo3xRc+wnN3C25wPpPlV2E6aOunQ==", + "dev": true + }, "ejs": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", @@ -1376,9 +2229,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.62", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.62.tgz", - "integrity": "sha512-qAfo81CsD7yQIM9mVyh6B/U47li5g7cfpVQEDMfQeF8pSZVwzbhwU3crc0qG4DmpsebpJPR49AKOExQyJ05Cpg==", + "version": "12.12.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.68.tgz", + "integrity": "sha512-3RW2s24ewB7F9dAHvgb9FRvNHn6nO9IK6Eaknbz7HTOe2a5GVne5XbUh5+YA+kcCn67glyHhClUUdFP73LWrgQ==", "dev": true } } @@ -1403,6 +2256,57 @@ "sanitize-filename": "^1.6.3", "update-notifier": "^4.1.1", "yargs": "^16.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "electron-chromedriver": { @@ -1436,6 +2340,15 @@ "yauzl": "^2.10.0" } }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1477,6 +2390,57 @@ "fs-extra": "^9.0.1", "lazy-val": "^1.0.4", "mime": "^2.4.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "emoji-regex": { @@ -1493,14 +2457,51 @@ "optional": true }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { "once": "^1.4.0" } }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "dev": true + }, + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -1509,9 +2510,9 @@ "optional": true }, "escalade": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", - "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-goat": { @@ -1532,12 +2533,144 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "optional": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "optional": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "extract-zip": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", @@ -1563,9 +2696,9 @@ "dev": true }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fd-slicer": { @@ -1574,9 +2707,25 @@ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "~1.2.0" + } + }, + "feather-icons": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/feather-icons/-/feather-icons-4.28.0.tgz", + "integrity": "sha512-gRdqKESXRBUZn6Nl0VBq2wPHKRJgZz7yblrrc2lYsS6odkNFDnA4bqvrlEVRUPjE1tFax+0TdbJKZ31ziJuzjg==", + "requires": { + "classnames": "^2.2.5", + "core-js": "^3.1.3" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "filelist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", @@ -1597,12 +2746,28 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "optional": true, "requires": { - "to-regex-range": "^5.0.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "find-up": { @@ -1621,6 +2786,13 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "optional": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1638,6 +2810,16 @@ "mime-types": "^2.1.12" } }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "optional": true, + "requires": { + "map-cache": "^0.2.2" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -1656,12 +2838,6 @@ "universalify": "^1.0.0" }, "dependencies": { - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, "jsonfile": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", @@ -1680,6 +2856,12 @@ } } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1687,17 +2869,33 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "fuzzaldrin-plus": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/fuzzaldrin-plus/-/fuzzaldrin-plus-0.6.0.tgz", "integrity": "sha1-gy9kifvodnaUWVmckUpnDsIpR+4=" }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1711,14 +2909,21 @@ "dev": true }, "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { "pump": "^3.0.0" } }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "optional": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -1743,12 +2948,26 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, + "optional": true, "requires": { - "is-glob": "^4.0.1" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } }, "global-agent": { @@ -1767,13 +2986,6 @@ "serialize-error": "^7.0.1" }, "dependencies": { - "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", - "dev": true, - "optional": true - }, "semver": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", @@ -1790,14 +3002,6 @@ "dev": true, "requires": { "ini": "^1.3.5" - }, - "dependencies": { - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - } } }, "global-tunnel-ng": { @@ -1813,6 +3017,12 @@ "tunnel": "^0.0.6" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "globalthis": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", @@ -1840,23 +3050,12 @@ "p-cancelable": "^1.0.0", "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "grapheme-splitter": { @@ -1887,12 +3086,62 @@ "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "optional": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "optional": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -1906,23 +3155,23 @@ "dev": true }, "highlight.js": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.2.1.tgz", - "integrity": "sha512-A+sckVPIb9zQTUydC9lpRX1qRFO/N0OKEh0NwIr65ckvWA/oMY8v9P3+kGRK3w2ULSh9E8v5MszXafodQ6039g==" + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.3.1.tgz", + "integrity": "sha512-jeW8rdPdhshYKObedYg5XGbpVgb1/DT4AHvDFXhkU7UnGSIjy9kkJ7zHG7qplhFHMitTSzh5/iClKQk3Kb2RFQ==" }, "hosted-git-info": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz", - "integrity": "sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", "dev": true }, "http-signature": { @@ -1973,21 +3222,6 @@ } } }, - "hyperapp": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.9.tgz", - "integrity": "sha512-bIzi12am7pyQ5nc2qnQpN6GWonjdJp+AghY7j9H9L0vccM1OQ3Cqn13cZlmS9KYm91Nf9fwF4KjvbQekFBxHVw==" - }, - "hyperapp-feather": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/hyperapp-feather/-/hyperapp-feather-0.4.0.tgz", - "integrity": "sha512-gLca/Ug5JmxZQiyOeyxNY1Sqptqd83RE7xy9MKsCFrQBV1c1bcxTO0j7NzRc0Dgbm6izmJrf3dNCUIh5b4Vupw==" - }, - "hyperapp-seti": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/hyperapp-seti/-/hyperapp-seti-0.3.0.tgz", - "integrity": "sha512-7+HT6ele6aC+DENzrrtR2S+MkQ6pxVloBRCW8Ryid/uMo4FWPgxoa4eA0uXd/Jkx//i1CphTvLPiyB6RNuMPmA==" - }, "iconv-lite": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", @@ -2021,6 +3255,26 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "inferno": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/inferno/-/inferno-7.4.5.tgz", + "integrity": "sha512-J/NnRqcucSaqUaOXy+RwojoOiEJE6QGAO0JyA4pyvv4t2e2NwLWGOP+5UR6ui6EvecbHoOAcu3SQVKwkL22TBg==", + "requires": { + "inferno-shared": "7.4.5", + "inferno-vnode-flags": "7.4.5", + "opencollective-postinstall": "^2.0.2" + } + }, + "inferno-shared": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/inferno-shared/-/inferno-shared-7.4.5.tgz", + "integrity": "sha512-jMI19wZN9kClOg+LLCzovcrHS1DPQagRaJQbPoZFzQxZLS8HejEd2gvYNbA/V7B0XmaNTezMZJnl1AcUOQC5kQ==" + }, + "inferno-vnode-flags": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/inferno-vnode-flags/-/inferno-vnode-flags-7.4.5.tgz", + "integrity": "sha512-BohIU7EW7I8yH/vgHAoYn06foIhl56pPN4J/DZ/bIseUmTG1mAzYZrhLc3qNZF6INgFQIAMcdpxdJKKEqjTl6w==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2032,26 +3286,62 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, + "optional": true, "requires": { - "binary-extensions": "^2.0.0" + "binary-extensions": "^1.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -2061,12 +3351,68 @@ "ci-info": "^2.0.0" } }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, "is-docker": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", "dev": true }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "optional": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2098,6 +3444,12 @@ "is-path-inside": "^3.0.1" } }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-npm": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", @@ -2105,10 +3457,26 @@ "dev": true }, "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } }, "is-obj": { "version": "2.0.0", @@ -2134,12 +3502,47 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "optional": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "optional": true + }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -2173,6 +3576,13 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -2189,42 +3599,14 @@ "chalk": "^2.4.2", "filelist": "^1.0.1", "minimatch": "^3.0.4" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", @@ -2241,6 +3623,12 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -2305,23 +3693,6 @@ "pako": "~1.0.2", "readable-stream": "~2.3.6", "set-immediate-shim": "~1.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } } }, "keyv": { @@ -2333,6 +3704,13 @@ "json-buffer": "3.0.0" } }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "optional": true + }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -2355,23 +3733,6 @@ "dev": true, "requires": { "readable-stream": "^2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } } }, "lie": { @@ -2408,12 +3769,6 @@ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, - "lodash-es": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz", - "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==", - "dev": true - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -2475,6 +3830,57 @@ "dev": true, "requires": { "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "loglevel": { @@ -2489,23 +3895,6 @@ "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", "dev": true }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "^3.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - } - } - }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -2522,20 +3911,30 @@ } }, "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "optional": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "optional": true, + "requires": { + "object-visit": "^1.0.0" } }, "marked": { @@ -2574,6 +3973,28 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, "mime": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", @@ -2616,6 +4037,29 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "optional": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "optional": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -2664,11 +4108,16 @@ "yargs-unparser": "2.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } }, "debug": { "version": "4.2.0", @@ -2685,6 +4134,12 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -2701,6 +4156,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -2727,21 +4191,38 @@ "strip-ansi": "^5.1.0" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, "yargs": { "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", @@ -2770,6 +4251,16 @@ } } } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -2785,12 +4276,39 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, "nanoid": { "version": "3.1.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", "dev": true }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -2808,12 +4326,6 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true } } }, @@ -2824,9 +4336,9 @@ "dev": true }, "normalize-url": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", - "integrity": "sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", "dev": true }, "npm-conf": { @@ -2855,6 +4367,84 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "optional": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "optional": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "optional": true, + "requires": { + "isobject": "^3.0.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2864,6 +4454,11 @@ "wrappy": "1" } }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==" + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -2871,9 +4466,9 @@ "dev": true }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -2886,17 +4481,6 @@ "dev": true, "requires": { "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } } }, "p-try": { @@ -2931,6 +4515,20 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "optional": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true, + "optional": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2967,6 +4565,12 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -2995,6 +4599,15 @@ "p-locate": "^4.1.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -3003,15 +4616,16 @@ "requires": { "p-limit": "^2.2.0" } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true } } }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "optional": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -3025,9 +4639,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "progress": { @@ -3131,6 +4745,15 @@ "yauzl": "^2.10.0" } }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3186,52 +4809,52 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "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" } }, "readdir-glob": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.0.tgz", - "integrity": "sha512-KgT0oXPIDQRRRYFf+06AUaodICTep2Q5635BORLzTEzp7rEqcR14a47j3Vzm3ix7FeI1lp8mYyG7r8lTB06Pyg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", "dev": true, "requires": { "minimatch": "^3.0.4" } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, + "optional": true, "requires": { - "picomatch": "^2.2.1" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, - "redux": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", - "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, + "optional": true, "requires": { - "lodash": "^4.2.1", - "lodash-es": "^4.2.1", - "loose-envify": "^1.1.0", - "symbol-observable": "^1.0.3" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, - "redux-devtools-extension": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.2.tgz", - "integrity": "sha1-4Pmo6N/KfBe+kscSSVijuU6ykR0=", - "dev": true - }, "registry-auth-token": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", @@ -3246,9 +4869,30 @@ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", "dev": true, - "requires": { - "rc": "^1.2.8" - } + "requires": { + "rc": "^1.2.8" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true, + "optional": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "optional": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "optional": true }, "request": { "version": "2.88.2", @@ -3276,14 +4920,6 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } } }, "require-directory": { @@ -3313,6 +4949,13 @@ "integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==", "dev": true }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true, + "optional": true + }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -3323,9 +4966,9 @@ } }, "resq": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.8.0.tgz", - "integrity": "sha512-VObcnfPcE6/EKfHqsi5qoJ0+BF9qfl5181CytP1su3HgzilqF03DrQ+Y7kZQrd+5myfmantl9W3/5uUcpwvKeg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.9.2.tgz", + "integrity": "sha512-Y+fprJ9wQY64gh+vJRNatiG61G+9XD5jJe4kI/Rqw6gmOa5ihZvgrxZVydqyM96xj75jwaRCPVYPU3RwsEk6ug==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1" @@ -3339,6 +4982,13 @@ } } }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "optional": true + }, "rgb2hex": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.0.tgz", @@ -3367,23 +5017,24 @@ "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true, - "optional": true - } } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "optional": true, + "requires": { + "ret": "~0.1.10" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3406,9 +5057,9 @@ "dev": true }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "semver-compare": { @@ -3442,14 +5093,6 @@ "dev": true, "requires": { "type-fest": "^0.13.1" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - } } }, "serialize-javascript": { @@ -3473,18 +5116,180 @@ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "optional": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "optional": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "optional": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -3493,8 +5298,23 @@ "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true, + "optional": true + }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -3549,11 +5369,22 @@ "through": "2" } }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true }, "sshpk": { "version": "1.16.1", @@ -3578,14 +5409,129 @@ "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "optional": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string_decoder": { @@ -3598,12 +5544,12 @@ } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } }, "strip-bom": { @@ -3618,20 +5564,40 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "debug": "^4.1.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "tar-fs": { "version": "2.1.0", @@ -3656,6 +5622,19 @@ "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "temp-file": { @@ -3678,12 +5657,6 @@ "jsonfile": "^4.0.0", "universalify": "^0.1.0" } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true } } }, @@ -3699,19 +5672,62 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "dev": true }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "optional": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, + "optional": true, "requires": { - "is-number": "^7.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "tough-cookie": { @@ -3745,12 +5761,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -3832,23 +5847,6 @@ "dev": true, "requires": { "resolve": ">=1.9.0" - }, - "dependencies": { - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } } }, "tunnel": { @@ -3874,9 +5872,9 @@ "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true }, "typedarray": { @@ -3916,6 +5914,19 @@ "through": "^2.3.8" } }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "optional": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -3926,11 +5937,55 @@ } }, "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "optional": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "optional": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "optional": true + } + } + }, "unzip-crx-3": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/unzip-crx-3/-/unzip-crx-3-0.2.0.tgz", @@ -3942,6 +5997,13 @@ "yaku": "^0.16.6" } }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "optional": true + }, "update-notifier": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", @@ -3996,26 +6058,40 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - } } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true, + "optional": true + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -4025,6 +6101,13 @@ "prepend-http": "^2.0.0" } }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "optional": true + }, "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", @@ -4065,15 +6148,16 @@ } }, "webdriver": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-6.5.0.tgz", - "integrity": "sha512-6iOll9TshD4+2J+em+bLshvM1uXtnotdZ+JaALqRLbkVswLRFU0pTVP1oug0e/IYwL7Me4Cafh9ugQ4PwPuOnA==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-6.6.3.tgz", + "integrity": "sha512-0qiwYIiWjHLmi6E1U7C+fW5pBNy7oBhMyVLYt/v1HDL2K6znQ/RiTJxU8lG5U22xx6LCEY9eRnIfV25QVqzfTQ==", "dev": true, "requires": { - "@wdio/config": "6.4.7", - "@wdio/logger": "6.4.7", - "@wdio/protocols": "6.3.6", - "@wdio/utils": "6.5.0", + "@types/lodash.merge": "^4.6.6", + "@wdio/config": "6.6.3", + "@wdio/logger": "6.6.0", + "@wdio/protocols": "6.6.0", + "@wdio/utils": "6.6.3", "got": "^11.0.2", "lodash.merge": "^4.6.1" }, @@ -4123,6 +6207,15 @@ "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==", "dev": true }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "got": { "version": "11.7.0", "resolved": "https://registry.npmjs.org/got/-/got-11.7.0.tgz", @@ -4187,20 +6280,21 @@ } }, "webdriverio": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-6.5.2.tgz", - "integrity": "sha512-ChAV6RmF10mlyWnAL2y+PdnzAjpxL/UuyAHJsYSuirEeEAAqFWWePxniz67bUEVQPVClVj8Jh7oeoK6rhu4RAA==", + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-6.6.6.tgz", + "integrity": "sha512-DzNSh9rx8iYFVr8gfs5q+/EwqXLEAWJSpog8cQZMABSxmooQKKpClRQ/j0dg2Lj2x7cDji69qvWDq0BtgUNzGw==", "dev": true, "requires": { "@types/puppeteer": "^3.0.1", - "@wdio/config": "6.4.7", - "@wdio/logger": "6.4.7", - "@wdio/repl": "6.5.0", - "@wdio/utils": "6.5.0", + "@wdio/config": "6.6.3", + "@wdio/logger": "6.6.0", + "@wdio/repl": "6.6.3", + "@wdio/utils": "6.6.3", "archiver": "^5.0.0", "atob": "^2.1.2", "css-value": "^0.0.1", - "devtools": "6.5.0", + "devtools": "6.6.3", + "fs-extra": "^9.0.1", "get-port": "^5.1.1", "grapheme-splitter": "^1.0.2", "lodash.clonedeep": "^4.5.0", @@ -4209,10 +6303,10 @@ "lodash.zip": "^4.2.0", "minimatch": "^3.0.4", "puppeteer-core": "^5.1.0", - "resq": "^1.6.0", + "resq": "^1.9.1", "rgb2hex": "^0.2.0", "serialize-error": "^7.0.0", - "webdriver": "6.5.0" + "webdriver": "6.6.3" } }, "which": { @@ -4237,57 +6331,44 @@ "dev": true, "requires": { "string-width": "^1.0.2 || 2" - } - }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^3.0.0" } } } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, "workerpool": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", @@ -4295,40 +6376,53 @@ "dev": true }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } } } @@ -4364,9 +6458,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.4.tgz", + "integrity": "sha512-deLOfD+RvFgrpAmSZgfGdWYE+OKyHcVHaRQ7NphG/63scpRvTHHeQMAxGGvaLVGJ+HYVcCXlzcTK0ZehFf+eHQ==", "dev": true }, "yaku": { @@ -4382,127 +6476,25 @@ "dev": true }, "yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz", + "integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==", "dev": true, "requires": { - "cliui": "^7.0.0", - "escalade": "^3.0.2", + "cliui": "^7.0.2", + "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", - "y18n": "^5.0.1", - "yargs-parser": "^20.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.1.tgz", - "integrity": "sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.2.tgz", - "integrity": "sha512-CkwaeZw6dQgqgPGeTWKMXCRmMcBgETFlTml1+ZOO+q7kGst8NREJ+eWwFNPVUQ4QGdAaklbqCZHH6Zuep1RjiA==", - "dev": true - }, - "yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-yYsjuSkjbLMBp16eaOt7/siKTjNVjMm3SoJnIg3sEh/JsvqVVDyjRKmaJV4cl+lNIgq6QEco2i3gDebJl7/vLA==", - "dev": true - } + "y18n": "^5.0.2", + "yargs-parser": "^20.2.2" } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz", + "integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==", + "dev": true }, "yargs-unparser": { "version": "2.0.0", @@ -4549,6 +6541,19 @@ "archiver-utils": "^2.1.0", "compress-commons": "^4.0.0", "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } } } diff --git a/package.json b/package.json index 9dd89a55..463febab 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,9 @@ "main": "build/bootstrap/main.js", "scripts": { "start": "node tools/start.js", - "start:release": "electron build/bootstrap/main.js", + "start:release": "NODE_ENV=production electron build/bootstrap/main.js", "build": "node tools/build.js", + "check-types": "tsc -p src/tsconfig.json --noEmit", "package": "node tools/package.js", "test": "mocha test/unit", "test:e2e": "mocha test/e2e -t 0", @@ -18,7 +19,7 @@ "test:integration:watch": "npm run test:integration -- -w", "gen:api": "node tools/gen-api.js", "gen:font-sizes": "electron tools/font-sizer/index.js", - "unused-exports": "ts-unused-exports tsconfig.json $(find src -name *.ts)", + "unused-exports": "ts-unused-exports src/tsconfig.json", "setup-mirrors": "node tools/setup-mirrors.js" }, "repository": { @@ -31,21 +32,27 @@ "homepage": "https://github.com/smolck/uivonim#readme", "dependencies": { "diff-match-patch": "^1.0.5", + "feather-icons": "^4.28.0", "fuzzaldrin-plus": "^0.6.0", - "highlight.js": "^10.2.1", - "hyperapp": "1.2.9", - "hyperapp-feather": "0.4.0", - "hyperapp-seti": "^0.3.0", + "highlight.js": "^10.3.1", + "inferno": "^7.4.5", "marked": "^1.2.0" }, "devDependencies": { - "@types/marked": "^1.1.0", - "@deomitrus/hyperapp-redux-devtools": "1.2.0", + "@babel/cli": "^7.12.1", + "@babel/core": "^7.12.3", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/preset-typescript": "^7.12.1", "@medv/finder": "^2.0.0", "@types/diff-match-patch": "1.0.32", "@types/fuzzaldrin-plus": "^0.6.1", + "@types/marked": "^1.1.0", "@types/node": "^14.11.10", "@types/webgl2": "0.0.5", + "babel-plugin-inferno": "^6.1.1", + "babel-plugin-syntax-jsx": "^6.18.0", "electron": "^10.1.3", "electron-builder": "^22.9.1", "electron-devtools-installer": "^3.1.1", diff --git a/src/bootstrap/galaxy.ts b/src/bootstrap/galaxy.ts index c8d4259b..f8d3a4e7 100644 --- a/src/bootstrap/galaxy.ts +++ b/src/bootstrap/galaxy.ts @@ -5,13 +5,16 @@ import * as workspace from '../core/workspace' import { remote } from 'electron' import '../render/redraw' import '../core/screen-events' +import { merge } from '../support/utils' +import * as dispatch from '../messaging/dispatch' +import { specs as titleSpecs } from '../core/title' // TODO: do we need to sync instance nvim state to main thread? see instance-api todo note // TODO: webgl line width // TODO: investigate no texture on unit0. im guessing the texture atlas are not // ready on load? // TODO: do we still need roboto-sizes.json? we generate the font atlas before -// we can wrender anything to webgl, so we can probably grab the size then +// we can render anything to webgl, so we can probably grab the size then // TODO: temp rows minus 1 because it doesn't fit. we will resize windows // individually once we get ext_windows working @@ -23,32 +26,22 @@ requestAnimationFrame(() => { // high priority components requestAnimationFrame(() => { - // Need to focus hacky textarea so input is registered right off the bat. - document.getElementById('hacky-textarea')?.focus() - - require('../components/statusline') - require('../components/command-line') - require('../components/vim-search') + requireDir(`${__dirname}/../components/nvim`) }) setTimeout(() => { requireDir(`${__dirname}/../components`) + requireDir(`${__dirname}/../components/extensions`) + requireDir(`${__dirname}/../components/memes`) }, 600) setTimeout(() => { - // Focus on hacky textarea when clicking main window, since input events are - // received from that textarea. - document.addEventListener('click', (e: MouseEvent) => { - e.preventDefault() - document.getElementById('hacky-textarea')?.focus() - }) - require('../services/remote') require('../services/app-info') if (process.env.VEONIM_DEV) { - require('../dev/menu') - require('../dev/recorder') + // require('../dev/menu') + // require('../dev/recorder') } }, 199) }) @@ -77,3 +70,18 @@ win.on('enter-full-screen', () => win.on('leave-full-screen', () => window.removeEventListener('mousemove', mouseTrap) ) + +const pluginsContainer = document.getElementById('plugins') as HTMLElement +merge(pluginsContainer.style, { + position: 'absolute', + display: 'flex', + width: '100vw', + zIndex: 420, + // TODO: 24px for statusline. do it better + // TODO: and title. bruv do i even know css? + height: `calc(100vh - 24px - ${titleSpecs.height}px)`, +}) + +dispatch.sub('window.change', () => { + pluginsContainer.style.height = `calc(100vh - 24px - ${titleSpecs.height}px)` +}) diff --git a/src/bootstrap/index.html b/src/bootstrap/index.html index 9a44766f..f07f6a57 100644 --- a/src/bootstrap/index.html +++ b/src/bootstrap/index.html @@ -13,6 +13,21 @@ src: url('../assets/roboto-mono.ttf'); } + /* TODO(smolck): HACK that breaks stuff maybe potentially */ + #plugins > div { + width: 100%; + height: 100%; + position: absolute; + /* Don't want these divs to obstruct clicking components/extensions, so + make them not visible. */ + visibility: hidden; + } + + #plugins > div > div { + /* Do want the actual components to be visible and thus clickable. */ + visibility: visible; + } + html { --font: 'Roboto Mono Veonim'; --font-size: 14; @@ -62,7 +77,7 @@ } /* Without this, there's extra margin on the top and bottom of the - hover (src/components/hover.ts) */ + hover (src/components/extensions/lsp-hover.ts) */ p, pre { margin: 0; @@ -143,7 +158,7 @@
- +
diff --git a/src/components/README.md b/src/components/README.md new file mode 100644 index 00000000..c6ff30c7 --- /dev/null +++ b/src/components/README.md @@ -0,0 +1,8 @@ +Implementations of the different UI elements used by Uivonim + +- top-level contains elements used by Uivomim itself +- `nvim` contains elements replacing neovim builtin UI (command line, pum, search, statusline, messages) +- `extensions` contains optional elements that can be called via `:Uivonim xxx` or bound to Lua (in particular, LSP hover, signature help, references, symbols) +- `extensions/legacy` contains elements from veonim that are no longer exposed +- `extensions/future` contains elements from veonim that are planned to be exposed in the future (requiring further work) +- `memes` contains Nyancat diff --git a/src/components/autocomplete.ts b/src/components/autocomplete.ts deleted file mode 100644 index 5299993d..00000000 --- a/src/components/autocomplete.ts +++ /dev/null @@ -1,358 +0,0 @@ -import { RowNormal, RowComplete } from '../components/row-container' -import { resetMarkdownHTMLStyle } from '../ui/styles' -import * as windows from '../windows/window-manager' -import * as dispatch from '../messaging/dispatch' -import * as workspace from '../core/workspace' -import { PopupMenu } from '../render/events' -import { paddingVH, cvar } from '../ui/css' -import Overlay from '../components/overlay' -import * as Icon from 'hyperapp-feather' -import { cursor } from '../core/cursor' -import { h, app } from '../ui/uikit' -import { parse as stringToMarkdown } from 'marked' - -export interface CompletionShow { - row: number - col: number - options: CompletionOption[] -} - -export interface CompletionOption { - /** Display text for the UI */ - text: string - /** Text that will be inserted in the buffer */ - insertText: string - /** An enum used to display a fancy icon and color in the completion menu UI */ - kind: CompletionItemKind - /** The entire CompletionItem object. Is used by the UI to get/show documentation. If this does not exist the program will query a completion item provider from a relevant extensions */ - raw?: CompletionItem -} - -// TODO(smolck): Should this be here or somewhere else? -export class CompletionItem { - label: string - kind: CompletionItemKind | undefined - // @ts-ignore - detail: string - // @ts-ignore - documentation: string | MarkdownString - // @ts-ignore - sortText: string - // @ts-ignore - filterText: string - // @ts-ignore - preselect: boolean - // @ts-ignore - insertText: string | SnippetString - keepWhitespace?: boolean - // @ts-ignore - range: Range - // @ts-ignore - commitCharacters: string[] - // @ts-ignore - textEdit: TextEdit - // @ts-ignore - additionalTextEdits: TextEdit[] - // @ts-ignore - - constructor(label: string, kind?: CompletionItemKind) { - this.label = label - this.kind = kind - } - - toJSON(): any { - return { - label: this.label, - kind: this.kind && CompletionItemKind[this.kind], - detail: this.detail, - documentation: this.documentation, - sortText: this.sortText, - filterText: this.filterText, - preselect: this.preselect, - insertText: this.insertText, - textEdit: this.textEdit, - } - } -} - -export enum CompletionItemKind { - Text = 0, - Method = 1, - Function = 2, - Constructor = 3, - Field = 4, - Variable = 5, - Class = 6, - Interface = 7, - Module = 8, - Property = 9, - Unit = 10, - Value = 11, - Enum = 12, - Keyword = 13, - Snippet = 14, - Color = 15, - File = 16, - Reference = 17, - Folder = 18, - EnumMember = 19, - Constant = 20, - Struct = 21, - Event = 22, - Operator = 23, - TypeParameter = 24, -} - -const MAX_VISIBLE_OPTIONS = 12 - -const state = { - x: 0, - y: 0, - ix: 0, - anchorAbove: false, - options: [] as CompletionOption[], - visible: false, - documentation: {} as any, - visibleOptions: MAX_VISIBLE_OPTIONS, -} - -type S = typeof state - -// const pos: { container: ClientRect } = { -// container: { left: 0, right: 0, bottom: 0, top: 0, height: 0, width: 0 } -// } - -const icons = new Map([ - [CompletionItemKind.Text, h(Icon.ChevronsRight)], - [CompletionItemKind.Method, h(Icon.Box, { color: '#bb5ef1' })], - [CompletionItemKind.Property, h(Icon.Disc, { color: '#54c8ff' })], - [CompletionItemKind.Function, h(Icon.Share2, { color: '#6da7ff' })], - [CompletionItemKind.Constructor, h(Icon.Aperture, { color: '#c9ff56' })], - [CompletionItemKind.Field, h(Icon.Feather, { color: '#9866ff' })], - [CompletionItemKind.Variable, h(Icon.Database, { color: '#ff70e4' })], - [CompletionItemKind.Class, h(Icon.Compass, { color: '#ffeb5b' })], - [CompletionItemKind.Interface, h(Icon.Map, { color: '#ffa354' })], - [CompletionItemKind.Module, h(Icon.Grid, { color: '#ff5f54' })], - [CompletionItemKind.Unit, h(Icon.Cpu, { color: '#ffadc5' })], - [CompletionItemKind.Value, h(Icon.Bell, { color: '#ffa4d0' })], - [CompletionItemKind.Enum, h(Icon.Award, { color: '#84ff54' })], - [CompletionItemKind.Keyword, h(Icon.Navigation, { color: '#ff0c53' })], - [CompletionItemKind.Snippet, h(Icon.Paperclip, { color: '#0c2dff' })], - [CompletionItemKind.Color, h(Icon.Eye, { color: '#54ffe5' })], - [CompletionItemKind.File, h(Icon.File, { color: '#a5c3ff' })], - [CompletionItemKind.Reference, h(Icon.Link, { color: '#ffdca3' })], - // TODO: we need some colors pls - [CompletionItemKind.Folder, h(Icon.Folder, { color: '#ccc' })], - [CompletionItemKind.EnumMember, h(Icon.Menu, { color: '#ccc' })], - [CompletionItemKind.Constant, h(Icon.Save, { color: '#ccc' })], - [CompletionItemKind.Struct, h(Icon.Layers, { color: '#ccc' })], - [CompletionItemKind.Event, h(Icon.Video, { color: '#ccc' })], - [CompletionItemKind.Operator, h(Icon.Anchor, { color: '#ccc' })], - [CompletionItemKind.TypeParameter, h(Icon.Type, { color: '#ccc' })], -]) - -const getCompletionIcon = (kind: CompletionItemKind) => - icons.get(kind) || h(Icon.Code) - -// TODO: move to common place. used in other places like signature-hint -const parseDocs = async (docs?: string): Promise => { - if (!docs) return - return stringToMarkdown(docs) -} - -const docs = (data: string) => - h(RowNormal, { - style: { - ...paddingVH(6, 4), - // RowNormal gives us display: flex but this causes things - // to be flex-flow: row. we just want the standard no fancy pls kthx - display: 'block', - paddingTop: '6px', - overflow: 'visible', - whiteSpace: 'normal', - color: cvar('foreground-20'), - background: cvar('background-45'), - fontSize: `${workspace.font.size - 2}px`, - }, - oncreate: (e: HTMLElement) => - (e.innerHTML = `
${data}
`), - }) - -const actions = { - hide: () => ({ visible: false, ix: 0 }), - - showDocs: (documentation: any) => ({ documentation }), - - show: ({ anchorAbove, visibleOptions, options, x, y, ix = -1 }: any) => { - return { - visibleOptions, - anchorAbove, - options, - ix, - x, - y, - visible: true, - documentation: undefined, - } - }, - - select: (ix: number) => (s: S, a: typeof actions) => { - const completionItem = (s.options[ix] || {}).raw - // raw could be missing if not semantic completions - if (!completionItem) return { ix, documentation: undefined } - - const { detail, documentation } = completionItem - // TODO: what are we doing with detail and documentation? - // show both? or one or the other? - - // TODO(smolck): I commented this out but . . . what is the purpose of this - // exactly? Should I re-add (a refactored version of) it? Feels - // unnecessary now that VSCode completions are no longer a thing. - // if (!detail || !documentation) - // (async () => { - // // TODO: what do with .detail? - // const details = await api.ai.completions.getDetail(completionItem) - // if (!details || !details.documentation) return - // const richFormatDocs = await parseDocs(details.documentation) - // a.showDocs(richFormatDocs) - // })() - - if (documentation) parseDocs(documentation).then(a.showDocs) - return { ix, documentation: detail } - }, -} - -const view = ($: S) => - Overlay( - { - x: $.x, - y: $.y, - zIndex: 200, - maxWidth: 400, - visible: $.visible, - anchorAbove: $.anchorAbove, - }, - [ - , - $.documentation && $.anchorAbove && docs($.documentation), - - h( - 'div', - { - // onupdate: (e: HTMLElement) => pos.container = e.getBoundingClientRect(), - style: { - overflowY: 'hidden', - background: cvar('background-30'), - maxHeight: `${workspace.cell.height * $.visibleOptions}px`, - }, - }, - $.options.map(({ text, kind }, id) => - h( - RowComplete, - { - key: `${text}-${kind}`, - active: id === $.ix, - // TODO: no scrolling because slow - // onupdate: (e: HTMLElement) => { - // if (id !== $.ix) return - // const { top, bottom } = e.getBoundingClientRect() - // if (top < pos.container.top) return e.scrollIntoView(true) - // if (bottom > pos.container.bottom) return e.scrollIntoView(false) - // }, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - // TODO: this doesn't scale with font size? - width: '24px', - marginRight: '2px', - alignItems: 'center', - justifyContent: 'center', - }, - }, - [getCompletionIcon(kind)] - ), - - h('div', text), - ] - ) - ) - ), - - $.documentation && !$.anchorAbove && docs($.documentation), - ] - ) - -const ui = app({ - name: 'autocomplete', - state, - actions, - view, -}) - -export const hide = () => ui.hide() -export const select = (index: number) => ui.select(index) -export const show = ({ row, col, options }: CompletionShow) => { - const visibleOptions = Math.min(MAX_VISIBLE_OPTIONS, options.length) - const anchorAbove = cursor.row + visibleOptions > workspace.size.rows - - ui.show({ - anchorAbove, - visibleOptions, - options: options.slice(0, visibleOptions), - ...windows.pixelPosition(anchorAbove ? row : row + 1, col), - }) -} - -dispatch.sub('pmenu.select', (ix) => select(ix)) -dispatch.sub('pmenu.hide', hide) -dispatch.sub('pmenu.show', ({ items, index, row, col }: PopupMenu) => { - const options = items.map( - (m) => - ({ - text: `${m.word} ${m.menu}`, - insertText: m.word, - kind: stringToKind(m.kind), - raw: { - documentation: m.info, - }, - } as CompletionOption) - ) - - show({ row, col, options }) - select(index) -}) - -// TODO(smolck): Support more kinds. -// Names and things taken from: -// https://github.com/vhakulinen/gnvim/blob/1afac027e15623affd3e5435b88e056e0394c2f8/src/nvim_bridge/mod.rs#L276 -const completionKindMappings = new Map([ - ['Variable', CompletionItemKind.Variable], - ['variable', CompletionItemKind.Variable], - ['V', CompletionItemKind.Variable], - - ['function', CompletionItemKind.Function], - ['Function', CompletionItemKind.Function], - - ['property', CompletionItemKind.Property], - ['Property', CompletionItemKind.Property], - ['method', CompletionItemKind.Property], - ['Method', CompletionItemKind.Property], - ['f', CompletionItemKind.Property], - - ['type paramter', CompletionItemKind.TypeParameter], - ['Type Parameter', CompletionItemKind.TypeParameter], - ['T', CompletionItemKind.TypeParameter], - - ['interface', CompletionItemKind.Interface], - ['I', CompletionItemKind.Interface], - ['Interface', CompletionItemKind.Interface], -]) - -const stringToKind = (kind: string): CompletionItemKind => { - return completionKindMappings.get(kind) || CompletionItemKind.Text -} diff --git a/src/components/buffers.ts b/src/components/buffers.ts deleted file mode 100644 index 3e42c9f2..00000000 --- a/src/components/buffers.ts +++ /dev/null @@ -1,96 +0,0 @@ -import FiletypeIcon, { Terminal } from '../components/filetype-icon' -import { Plugin } from '../components/plugin-container' -import { RowNormal } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import { BufferInfo } from '../neovim/types' -import Input from '../components/text-input' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' - -const state = { - value: '', - buffers: [] as BufferInfo[], - cache: [] as BufferInfo[], - visible: false, - index: 0, -} - -type S = typeof state - -const resetState = { value: '', visible: false, index: 0 } - -const actions = { - select: () => (s: S) => { - vimFocus() - if (!s.buffers.length) return resetState - const { name } = s.buffers[s.index] - if (name) api.nvim.cmd(`b ${name}`) - return resetState - }, - - change: (value: string) => (s: S) => ({ - value, - index: 0, - buffers: value - ? filter(s.cache, value, { key: 'name' }).slice(0, 10) - : s.cache.slice(0, 10), - }), - - hide: () => (vimFocus(), resetState), - show: (buffers: BufferInfo[]) => ( - vimBlur(), { buffers, cache: buffers, visible: true } - ), - next: () => (s: S) => ({ - index: s.index + 1 > Math.min(s.buffers.length - 1, 9) ? 0 : s.index + 1, - }), - prev: () => (s: S) => ({ - index: s.index - 1 < 0 ? Math.min(s.buffers.length - 1, 9) : s.index - 1, - }), -} - -const view = ($: S, a: typeof actions) => - Plugin($.visible, [ - , - Input({ - select: a.select, - change: a.change, - hide: a.hide, - next: a.next, - prev: a.prev, - value: $.value, - focus: true, - icon: Icon.List, - desc: 'switch buffer', - }), - - h( - 'div', - $.buffers.map((f, ix) => - h( - RowNormal, - { - active: ix === $.index, - }, - [ - , - f.terminal ? Terminal : FiletypeIcon(f.name), - - h( - 'span', - { - render: f.duplicate, - style: { color: '#666' }, - }, - `${f.dir}/` - ), - - h('span', f.duplicate ? f.base : f.name), - ] - ) - ) - ), - ]) - -const ui = app({ name: 'buffers', state, actions, view }) -api.onAction('buffers', async () => ui.show(await api.nvim.getBufferInfo())) diff --git a/src/components/change-project.ts b/src/components/change-project.ts deleted file mode 100644 index 34c3754c..00000000 --- a/src/components/change-project.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { getDirFiles, exists, pathRelativeToHome } from '../support/utils' -import { createVim, renameCurrentToCwd } from '../core/instance-manager' -import { RowNormal, RowImportant } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import { Plugin } from '../components/plugin-container' -import Input from '../components/text-input' -import { join, sep, basename } from 'path' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' -import { homedir } from 'os' - -const $HOME = homedir() - -interface FileDir { - name: string - file: boolean - dir: boolean -} - -const state = { - value: '', - cwd: '', - path: '', - paths: [] as FileDir[], - cache: [] as FileDir[], - visible: false, - index: 0, - create: false, -} - -type S = typeof state - -const absPath = (path = '') => - path.startsWith('~') ? join($HOME, path.slice(1)) : path -const validPath = async (path = '') => { - if (!path) return '' - const fullpath = absPath(path) - return (await exists(fullpath)) ? fullpath : '' -} - -const filterDirs = (filedirs: FileDir[]) => filedirs.filter((f) => f.dir) - -let listElRef: HTMLElement - -const resetState = { value: '', path: '', visible: false, index: 0 } - -const actions = { - select: () => (s: S) => { - vimFocus() - if (!s.paths.length) return resetState - const { name } = s.paths[s.index] - if (!name) return - const dirpath = join(s.path, name) - s.create ? createVim(name, dirpath) : api.nvim.cmd(`cd ${dirpath}`) - return resetState - }, - - change: (value: string) => (s: S) => ({ - value, - index: 0, - paths: value - ? filterDirs(filter(s.paths, value, { key: 'name' })) - : s.cache, - }), - - tab: () => (s: S) => { - if (!s.paths.length) return resetState - const { name } = s.paths[s.index] - if (!name) return - const path = join(s.path, name) - getDirFiles(path).then((paths) => - ui.show({ path, paths: filterDirs(paths) }) - ) - }, - - jumpNext: () => (s: S) => { - const { name, dir } = s.paths[s.index] - if (!dir) return - const path = join(s.path, name) - getDirFiles(path).then((paths) => - ui.show({ path, paths: filterDirs(paths) }) - ) - }, - - jumpPrev: () => (s: S) => { - const next = s.path.split(sep) - next.pop() - const path = join(sep, ...next) - getDirFiles(path).then((paths) => - ui.show({ path, paths: filterDirs(paths) }) - ) - }, - - show: ({ paths, path, cwd, create }: any) => (s: S) => ( - vimBlur(), - { - path, - paths, - create, - cwd: cwd || s.cwd, - index: 0, - value: '', - visible: true, - cache: paths, - } - ), - - // TODO: be more precise than this? also depends on scaled devices - down: () => (s: S) => { - listElRef.scrollTop += 300 - return { index: Math.min(s.index + 17, s.paths.length - 1) } - }, - - up: () => (s: S) => { - listElRef.scrollTop -= 300 - return { index: Math.max(s.index - 17, 0) } - }, - - top: () => { - listElRef.scrollTop = 0 - }, - bottom: () => { - listElRef.scrollTop = listElRef.scrollHeight - }, - hide: () => (vimFocus(), resetState), - next: () => (s: S) => ({ - index: s.index + 1 >= s.paths.length ? 0 : s.index + 1, - }), - prev: () => (s: S) => ({ - index: s.index - 1 < 0 ? s.paths.length - 1 : s.index - 1, - }), -} - -const view = ($: S, a: typeof actions) => - Plugin($.visible, [ - , - Input({ - up: a.up, - top: a.top, - tab: a.tab, - next: a.next, - prev: a.prev, - down: a.down, - hide: a.hide, - select: a.select, - change: a.change, - bottom: a.bottom, - jumpNext: a.jumpNext, - jumpPrev: a.jumpPrev, - value: $.value, - focus: true, - icon: Icon.Home, - desc: $.create ? 'create new vim session with project' : 'change project', - }), - - h(RowImportant, [, h('span', pathRelativeToHome($.path))]), - - h( - 'div', - { - oncreate: (e: HTMLElement) => { - if (e) listElRef = e - }, - style: { - maxHeight: '50vh', - overflowY: 'hidden', - }, - }, - $.paths.map(({ name }, ix) => - h( - RowNormal, - { - key: name, - active: ix === $.index, - }, - [, h('span', name)] - ) - ) - ), - ]) - -const ui = app({ name: 'change-project', state, actions, view }) - -const go = async (userPath: string, create = false) => { - const cwd = (await validPath(userPath)) || api.nvim.state.cwd - const filedirs = await getDirFiles(cwd) - const paths = filterDirs(filedirs) - ui.show({ paths, cwd, path: cwd, create }) -} - -api.onAction('change-dir', (path = '') => go(path, false)) -api.onAction('vim-create-dir', (path = '') => go(path, true)) - -api.nvim.watchState.cwd((cwd: string) => { - if (cwd && homedir() !== cwd) renameCurrentToCwd(basename(cwd)) -}) - -export const changeDir = () => go('', false) -export const createInstanceWithDir = () => go('', true) diff --git a/src/components/code-action.ts b/src/components/code-action.ts deleted file mode 100644 index d67d35a3..00000000 --- a/src/components/code-action.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { RowNormal } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import * as windows from '../windows/window-manager' -import Input from '../components/text-input' -import Overlay from '../components/overlay' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' -import { cursor } from '../core/cursor' - -type CodeAction = { - title: string - kind?: string - isPreferred?: boolean - edit?: any - command?: any - arguments: any -} - -const state = { - x: 0, - y: 0, - value: '', - visible: false, - actions: [] as CodeAction[], - cache: [] as CodeAction[], - index: 0, -} - -type S = typeof state - -const resetState = { value: '', visible: false } - -const actions = { - show: ({ x, y, actions }: any) => { - vimBlur() - return { x, y, actions, cache: actions, visible: true } - }, - hide: () => (vimFocus(), resetState), - - change: (value: string) => (s: S) => ({ - value, - index: 0, - actions: value ? filter(s.actions, value, { key: 'title' }) : s.cache, - }), - - select: () => (s: S) => { - vimFocus() - if (!s.actions.length) return resetState - const action = s.actions[s.index] - if (action) - // @ts-ignore <- without this get an error about luaeval not being a - // property - - // roundtrip through vimscript since TS dict looks like a vimscript dict - // TODO: see if action can be converted to a Lua table to allow direct call to lua - api.nvim.call.luaeval( - "require'uivonim/lsp'.handle_chosen_code_action(_A)", - action - ) - return resetState - }, - - next: () => (s: S) => ({ - index: s.index + 1 > s.actions.length - 1 ? 0 : s.index + 1, - }), - prev: () => (s: S) => ({ - index: s.index - 1 < 0 ? s.actions.length - 1 : s.index - 1, - }), -} - -const view = ($: S, a: typeof actions) => - Overlay( - { - x: $.x, - y: $.y, - zIndex: 100, - maxWidth: 600, - visible: $.visible, - anchorAbove: false, - }, - [ - , - h( - 'div', - { - style: { - background: 'var(--background-40)', - }, - }, - [ - , - Input({ - hide: a.hide, - next: a.next, - prev: a.prev, - change: a.change, - select: a.select, - value: $.value, - focus: true, - small: true, - icon: Icon.Code, - desc: 'run code action', - }), - - h( - 'div', - $.actions.map((s, ix) => - h( - RowNormal, - { - key: s.title, - active: ix === $.index, - }, - [, h('span', s.title)] - ) - ) - ), - ] - ), - ] - ) - -const ui = app({ name: 'code-actions', state, actions, view }) - -api.onAction('code-action', (actions) => { - const { x, y } = windows.pixelPosition(cursor.row + 1, cursor.col) - ui.show({ - x, - y, - actions: actions.map((x) => ({ - title: x.title, - kind: x.kind, - edit: x.edit, - command: x.command, - arguments: x.arguments, - })), - }) -}) diff --git a/src/components/command-line.ts b/src/components/command-line.ts deleted file mode 100644 index 39d33202..00000000 --- a/src/components/command-line.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { - enableCursor, - disableCursor, - hideCursor, - showCursor, -} from '../core/cursor' -import { CommandType, CommandUpdate } from '../render/events' -import { Plugin } from '../components/plugin-container' -import { RowNormal } from '../components/row-container' -import Input from '../components/text-input' -import { sub } from '../messaging/dispatch' -import * as Icon from 'hyperapp-feather' -import { is } from '../support/utils' -import { h, app } from '../ui/uikit' - -const modeSwitch = new Map([ - [CommandType.Ex, Icon.Command], - [CommandType.Prompt, Icon.ChevronsRight], -]) - -const state = { - options: [] as string[], - visible: false, - value: '', - ix: 0, - position: 0, - prompt: '', - kind: CommandType.Ex, -} - -type S = typeof state - -const actions = { - // there is logic in text-input to show/hide cursor based on text input - // foucs/blur events. however i noticed that when selecting a wildmenu option - // somehow causes the text input to lose focus (we need to update the - // selected menu item in the text input field). i'm not sure why this is - // different than the normal command update, since we do not use the text - // input natively. we send input events directly to vim, vim sends cmd - // updates back to us, and we update the text input field. - hide: () => { - enableCursor() - showCursor() - return { visible: false } - }, - updateCommand: ({ cmd, kind, position, prompt }: CommandUpdate) => (s: S) => { - hideCursor() - disableCursor() - - return { - kind, - prompt, - position, - visible: true, - options: cmd ? s.options : [], - value: is.string(cmd) && s.value !== cmd ? cmd : s.value, - } - }, - - selectWildmenu: (ix: number) => ({ ix }), - updateWildmenu: (options: string[]) => ({ - options: [...new Set(options)], - }), -} - -type A = typeof actions - -const view = ($: S) => - Plugin( - $.visible, - { - position: 'relative', - }, - [ - , - $.prompt && - h( - 'div', - { - style: { - position: 'absolute', - width: '100%', - background: 'var(--background-50)', - marginTop: '-40px', - height: '40px', - display: 'flex', - alignItems: 'center', - }, - }, - [ - , - h( - 'div', - { - style: { - padding: '0 15px', - fontSize: '1.1rem', - }, - }, - $.prompt - ), - ] - ), - - Input({ - focus: true, - value: $.value, - desc: $.kind == CommandType.Ex ? 'command line' : 'prompt', - position: $.position, - icon: - $.value.startsWith('lua ') && $.kind == CommandType.Ex - ? Icon.Moon - : modeSwitch.get($.kind) || Icon.Command, - }), - - h( - 'div', - $.options.map((name, ix) => - h( - RowNormal, - { - active: ix === $.ix, - }, - [, h('div', name)] - ) - ) - ), - ] - ) - -const ui = app({ name: 'command-line', state, actions, view }) - -// TODO: use export cns. this component is a high priority so it should be loaded early -// because someone might open cmdline early -sub('wildmenu.show', (opts) => ui.updateWildmenu(opts)) -sub('wildmenu.select', (ix) => ui.selectWildmenu(ix)) -sub('wildmenu.hide', () => ui.updateWildmenu([])) - -sub('cmd.hide', ui.hide) -sub('cmd.update', ui.updateCommand) diff --git a/src/components/explorer.ts b/src/components/explorer.ts deleted file mode 100644 index d05f4c94..00000000 --- a/src/components/explorer.ts +++ /dev/null @@ -1,273 +0,0 @@ -import { - getDirFiles, - pathRelativeToHome, - pathRelativeToCwd, - getDirs, - $HOME, -} from '../support/utils' -import { RowNormal, RowImportant } from '../components/row-container' -import FiletypeIcon, { Folder } from '../components/filetype-icon' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import { Plugin } from '../components/plugin-container' -import { join, sep, basename, dirname } from 'path' -import Input from '../components/text-input' -import { BufferType } from '../neovim/types' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' -import { colors } from '../ui/styles' -import { cvar } from '../ui/css' - -interface FileDir { - name: string - file: boolean - dir: boolean -} - -const state = { - val: '', - cwd: '', - path: '', - paths: [] as FileDir[], - cache: [] as FileDir[], - vis: false, - ix: 0, - pathMode: false, - pathValue: '', -} - -const sortDirFiles = (filedirs: FileDir[]) => { - const dirs = filedirs.filter((f) => f.dir) - const files = filedirs.filter((f) => f.file) - return [...dirs, ...files] -} - -const absolutePath = (path: string) => path.replace(/^~\//, `${$HOME}/`) - -const pathExplore = async (path: string) => { - const fullpath = absolutePath(path) - const complete = fullpath.endsWith('/') - const dir = complete ? fullpath : dirname(fullpath) - const top = basename(fullpath) - const dirs = await getDirs(dir) - return complete ? dirs : filter(dirs, top, { key: 'name' }) -} - -const resetState = { val: '', path: '', vis: false, ix: 0 } - -type S = typeof state - -const actions = { - // TODO: when choosing custom path and go back, make sure it updates correctly - // like ~/proj/veonim/ -> OK - // but ~/proj/veonim -> DERP! - - ctrlG: () => ({ pathMode: true, ix: 0, val: '', pathValue: '' }), - - completePath: () => (s: S) => { - if (!s.paths.length) return - const dir = dirname(absolutePath(s.pathValue)) - const { name } = s.paths[s.ix] - const next = `${join(dir, name)}/` - pathExplore(next).then(ui.updatePaths) - return { ix: 0, pathValue: next } - }, - - normalMode: () => ({ pathMode: false }), - updatePaths: (paths: FileDir[]) => ({ paths }), - - selectPath: () => (s: S) => { - if (!s.pathValue) return { pathMode: false, ix: 0 } - getDirFiles(s.pathValue).then((paths) => - ui.updatePaths(sortDirFiles(paths)) - ) - return { pathMode: false, path: s.pathValue, ix: 0 } - }, - - changePath: (pathValue: string) => { - pathExplore(pathValue).then(ui.updatePaths) - return { pathValue } - }, - - nextPath: () => (s: S) => { - const ix = s.ix + 1 >= s.paths.length ? 0 : s.ix + 1 - const fullpath = absolutePath(s.pathValue) - const goodPath = fullpath.endsWith('/') ? fullpath : dirname(fullpath) - const { name } = s.paths[ix] - const pathValue = `${join(goodPath, name)}` - return { ix, pathValue } - }, - - prevPath: () => (s: S) => { - const ix = s.ix - 1 < 0 ? s.paths.length - 1 : s.ix - 1 - const fullpath = absolutePath(s.pathValue) - const goodPath = fullpath.endsWith('/') ? fullpath : dirname(fullpath) - const { name } = s.paths[ix] - const pathValue = `${join(goodPath, name)}` - return { ix, pathValue } - }, - - select: () => (s: S) => { - vimFocus() - if (!s.paths.length) return resetState - - const { name, file } = s.paths[s.ix] - if (!name) return - - if (file) { - api.nvim.cmd(`e ${pathRelativeToCwd(join(s.path, name), s.cwd)}`) - return resetState - } - - const path = join(s.path, name) - getDirFiles(path).then((paths) => - ui.show({ path, paths: sortDirFiles(paths) }) - ) - }, - - change: (val: string) => (s: S) => ({ - val, - ix: 0, - paths: val ? sortDirFiles(filter(s.paths, val, { key: 'name' })) : s.cache, - }), - - ctrlH: async () => { - const { cwd } = api.nvim.state - const filedirs = await getDirFiles(cwd) - const paths = sortDirFiles(filedirs) - ui.show({ paths, cwd, path: cwd }) - }, - - jumpPrev: () => (s: S) => { - const next = s.path.split(sep) - next.pop() - const path = join(sep, ...next) - getDirFiles(path).then((paths) => - ui.show({ path, paths: sortDirFiles(paths) }) - ) - }, - - show: ({ paths, path, cwd }: any) => (s: S) => ( - vimBlur(), - { - ...resetState, - path, - paths, - vis: true, - cache: paths, - cwd: cwd || s.cwd, - } - ), - - // TODO: be more precise than this? also depends on scaled devices - down: () => (s: S) => { - listElRef.scrollTop += 300 - return { ix: Math.min(s.ix + 17, s.paths.length - 1) } - }, - - up: () => (s: S) => { - listElRef.scrollTop -= 300 - return { ix: Math.max(s.ix - 17, 0) } - }, - - top: () => { - listElRef.scrollTop = 0 - }, - bottom: () => { - listElRef.scrollTop = listElRef.scrollHeight - }, - hide: () => (vimFocus(), resetState), - next: () => (s: S) => ({ ix: s.ix + 1 >= s.paths.length ? 0 : s.ix + 1 }), - prev: () => (s: S) => ({ ix: s.ix - 1 < 0 ? s.paths.length - 1 : s.ix - 1 }), -} - -let listElRef: HTMLElement - -type A = typeof actions - -const view = ($: S, a: A) => - Plugin($.vis, [ - , - Input({ - value: $.val, - focus: !$.pathMode, - icon: Icon.HardDrive, - desc: 'explorer', - change: a.change, - hide: a.hide, - next: a.next, - prev: a.prev, - select: a.select, - jumpPrev: a.jumpPrev, - down: a.down, - up: a.up, - ctrlG: a.ctrlG, - ctrlH: a.ctrlH, - }), - - !$.pathMode && h(RowImportant, [, h('span', pathRelativeToHome($.path))]), - - $.pathMode && - Input({ - change: a.changePath, - hide: a.normalMode, - select: a.selectPath, - tab: a.completePath, - next: a.nextPath, - prev: a.prevPath, - value: pathRelativeToHome($.pathValue), - background: cvar('background-50'), - color: colors.important, - icon: Icon.Search, - desc: 'open path', - small: true, - focus: true, - pathMode: true, - }), - - h( - 'div', - { - oncreate: (e: HTMLElement) => (listElRef = e), - style: { - maxHeight: '50vh', - overflowY: 'hidden', - }, - }, - $.paths.map(({ name, dir }, ix) => - h( - RowNormal, - { - key: `${name}-${dir}`, - active: ix === $.ix, - }, - [ - , - dir ? Folder : FiletypeIcon(name), - - h( - 'span', - { - style: { - color: dir && ix !== $.ix ? cvar('foreground-50') : undefined, - }, - }, - name - ), - ] - ) - ) - ), - ]) - -const ui = app({ name: 'explorer', state, actions, view }) - -api.onAction('explorer', async (customDir?: string) => { - const { cwd, bufferType } = api.nvim.state - const isTerminal = bufferType === BufferType.Terminal - const currentDir = isTerminal ? cwd : api.nvim.state.dir - const path = customDir || currentDir - - const paths = sortDirFiles(await getDirFiles(path)) - ui.show({ cwd, path, paths }) -}) diff --git a/src/components/extensions/buffers.tsx b/src/components/extensions/buffers.tsx new file mode 100644 index 00000000..4e146ac1 --- /dev/null +++ b/src/components/extensions/buffers.tsx @@ -0,0 +1,116 @@ +import FiletypeIcon, { Terminal } from '../filetype-icon' +import { Plugin } from '../plugin-container' +import { RowNormal } from '../row-container' +import { vimBlur, vimFocus } from '../../ui/uikit' +import { BufferInfo } from '../../neovim/types' +import Input from '../text-input' +import { filter } from 'fuzzaldrin-plus' +import { render } from 'inferno' +import api from '../../core/instance-api' + +let state = { + value: '', + buffers: [] as BufferInfo[], + cache: [] as BufferInfo[], + visible: false, + index: 0, + inputCallbacks: {}, +} + +type S = typeof state + +const resetState = { value: '', visible: false, index: 0 } + +const feather = require('feather-icons') +const Buffers = ({ visible, value, index, buffers, inputCallbacks }: S) => ( + + + +
+ {buffers.map((f, ix) => ( + + {f.terminal ? Terminal : FiletypeIcon(f.name)} + + {f.dir}/ + + {f.duplicate ? f.base : f.name} + + ))} +
+
+) + +const container = document.createElement('div') +container.id = 'buffers-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const select = () => { + vimFocus() + if (!state.buffers.length) { + assignStateAndRender(resetState) + return + } + + const { name } = state.buffers[state.index] + if (name) api.nvim.cmd(`b ${name}`) + assignStateAndRender(resetState) +} + +const change = (value: string) => + assignStateAndRender({ + value, + index: 0, + buffers: value + ? filter(state.cache, value, { key: 'name' }).slice(0, 10) + : state.cache.slice(0, 10), + }) + +const hide = () => (vimFocus(), assignStateAndRender(resetState)) + +const next = () => + assignStateAndRender({ + index: + state.index + 1 > Math.min(state.buffers.length - 1, 9) + ? 0 + : state.index + 1, + }) + +const prev = () => + assignStateAndRender({ + index: + state.index - 1 < 0 + ? Math.min(state.buffers.length - 1, 9) + : state.index - 1, + }) + +state.inputCallbacks = { + select, + change, + hide, + next, + prev, +} + +const show = (buffers: BufferInfo[]) => ( + vimBlur(), assignStateAndRender({ buffers, cache: buffers, visible: true }) +) + +api.onAction('buffers', async () => show(await api.nvim.getBufferInfo())) diff --git a/src/components/color-picker.ts b/src/components/extensions/color-picker.tsx similarity index 58% rename from src/components/color-picker.ts rename to src/components/extensions/color-picker.tsx index a38b3a28..9b63c55f 100644 --- a/src/components/color-picker.ts +++ b/src/components/extensions/color-picker.tsx @@ -1,14 +1,14 @@ -import * as windows from '../windows/window-manager' -import * as dispatch from '../messaging/dispatch' -import ColorPicker from '../ui/color-picker' -import Overlay from '../components/overlay' -import { debounce } from '../support/utils' -import { stealInput } from '../core/input' -import onLoseFocus from '../ui/lose-focus' +import * as windows from '../../windows/window-manager' +import * as dispatch from '../../messaging/dispatch' +import ColorPicker from '../../ui/color-picker' +import Overlay from '../overlay' +import { debounce } from '../../support/utils' +import { stealInput } from '../../core/input' +import onLoseFocus from '../../ui/lose-focus' import { basename, extname } from 'path' -import { cursor } from '../core/cursor' -import api from '../core/instance-api' -import { h, app } from '../ui/uikit' +import { cursor } from '../../core/cursor' +import { render } from 'inferno' +import api from '../../core/instance-api' let liveMode = false let restoreInput = () => {} @@ -46,38 +46,54 @@ const possiblyUpdateColorScheme = debounce(() => { dispatch.pub('colorscheme.modified') }, 300) -const state = { +let state = { x: 0, y: 0, visible: false, anchorBottom: false, + hideFunc: () => {}, // TODO(smolck) } -const actions = { - show: () => ({ visible: true, ...getPosition(cursor.row, cursor.col) }), - hide: () => ({ visible: false }), -} - -const view = ($: typeof state, a: typeof actions) => - Overlay( - { - x: $.x, - y: $.y, - zIndex: 900, - visible: $.visible, - anchorAbove: $.anchorBottom, - }, - [ - , - h('.show-cursor', { - onupdate: (e: HTMLElement) => - onLoseFocus(e, () => (a.hide(), restoreInput())), - oncreate: (e: HTMLElement) => e.appendChild(colorPicker.element), - }), - ] - ) - -const ui = app({ name: 'color-picker', state, actions, view }) +const WhyDiv = (props: any) =>
+ +let elref: HTMLElement | undefined +const ColorPickerView = ({ + x, + y, + visible, + anchorBottom, + hideFunc, +}: typeof state) => ( + + ( + e.appendChild(colorPicker.element), (elref = e) + )} + onComponentDidUpdate={(_lastProps: any, _nextProps: any) => { + if (elref) { + onLoseFocus(elref, () => (hideFunc(), restoreInput())) + } // TODO(smolck): Else . . . sadness? + }} + /> + +) + +const container = document.createElement('div') +container.id = 'color-picker-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), + render(, container) +) + +const uiShow = () => + assignStateAndRender({ + visible: true, + ...getPosition(cursor.row, cursor.col), + }) +state.hideFunc = () => assignStateAndRender({ visible: false }) const show = (color: string) => { // TODO: conditionally call setRGB or setHSL depending on input @@ -86,12 +102,12 @@ const show = (color: string) => { colorPicker.setHex(color) // colorPicker.setRGB(r, g, b, a) // colorPicker.setHSL(h, s, l, a) - ui.show() + uiShow() restoreInput = stealInput((keys) => { if (keys !== '') return restoreInput() - ui.hide() + state.hideFunc() }) } diff --git a/src/components/extensions/explorer.tsx b/src/components/extensions/explorer.tsx new file mode 100644 index 00000000..f50415a0 --- /dev/null +++ b/src/components/extensions/explorer.tsx @@ -0,0 +1,297 @@ +import { + getDirFiles, + pathRelativeToHome, + pathRelativeToCwd, + getDirs, + $HOME, +} from '../../support/utils' +import { RowNormal, RowImportant } from '../row-container' +import FiletypeIcon, { Folder } from '../filetype-icon' +import { vimBlur, vimFocus } from '../../ui/uikit' +import { Plugin } from '../plugin-container' +import { join, sep, basename, dirname } from 'path' +import Input from '../text-input' +import { BufferType } from '../../neovim/types' +import { filter } from 'fuzzaldrin-plus' +import api from '../../core/instance-api' +import { colors } from '../../ui/styles' +import { cvar } from '../../ui/css' +import { render } from 'inferno' + +interface FileDir { + name: string + file: boolean + dir: boolean +} + +let state = { + val: '', + cwd: '', + path: '', + paths: [] as FileDir[], + cache: [] as FileDir[], + vis: false, + ix: 0, + pathMode: false, + pathValue: '', + inputCallbacks: {}, + pathModeInputCallbacks: {}, +} + +const sortDirFiles = (filedirs: FileDir[]) => { + const dirs = filedirs.filter((f) => f.dir) + const files = filedirs.filter((f) => f.file) + return [...dirs, ...files] +} + +const absolutePath = (path: string) => path.replace(/^~\//, `${$HOME}/`) + +const pathExplore = async (path: string) => { + const fullpath = absolutePath(path) + const complete = fullpath.endsWith('/') + const dir = complete ? fullpath : dirname(fullpath) + const top = basename(fullpath) + const dirs = await getDirs(dir) + return complete ? dirs : filter(dirs, top, { key: 'name' }) +} + +const resetState = { val: '', path: '', vis: false, ix: 0 } + +type S = typeof state + +let listElRef: HTMLElement + +const WhyDiv = (props: any) =>
{props.children}
+ +const feather = require('feather-icons') +const Explorer = ({ + ix: index, + vis: visible, + val: value, + path, + pathMode, + inputCallbacks, + pathModeInputCallbacks, + pathValue, + paths, +}: S) => ( + + + + {!pathMode && ( + + {pathRelativeToHome(path)} + + )} + + {pathMode && ( + + )} + + (listElRef = e)} + style={{ 'max-height': '50vh', 'overflow-y': 'hidden' }} + > + {paths.map(({ name, dir }, ix) => ( + + {dir ? Folder : FiletypeIcon(name)} + + + {name} + + + ))} + + +) + +const container = document.createElement('div') +container.id = 'explorer-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const updatePaths = (paths: FileDir[]) => assignStateAndRender({ paths }) + +state.pathModeInputCallbacks = { + change: (pathValue: string) => { + pathExplore(pathValue).then(updatePaths) + assignStateAndRender({ pathValue }) + }, + + hide: () => assignStateAndRender({ pathMode: false }), + + select: () => { + if (!state.pathValue) { + assignStateAndRender({ pathMode: false, ix: 0 }) + return + } + getDirFiles(state.pathValue).then((paths) => + updatePaths(sortDirFiles(paths)) + ) + assignStateAndRender({ pathMode: false, path: state.pathValue, ix: 0 }) + }, + + tab: () => { + if (!state.paths.length) return + const dir = dirname(absolutePath(state.pathValue)) + const { name } = state.paths[state.ix] + const next = `${join(dir, name)}/` + pathExplore(next).then(updatePaths) + assignStateAndRender({ ix: 0, pathValue: next }) + }, + + next: () => { + const ix = state.ix + 1 >= state.paths.length ? 0 : state.ix + 1 + const fullpath = absolutePath(state.pathValue) + const goodPath = fullpath.endsWith('/') ? fullpath : dirname(fullpath) + const { name } = state.paths[ix] + const pathValue = `${join(goodPath, name)}` + assignStateAndRender({ ix, pathValue }) + }, + + prev: () => { + const ix = state.ix - 1 < 0 ? state.paths.length - 1 : state.ix - 1 + const fullpath = absolutePath(state.pathValue) + const goodPath = fullpath.endsWith('/') ? fullpath : dirname(fullpath) + const { name } = state.paths[ix] + const pathValue = `${join(goodPath, name)}` + assignStateAndRender({ ix, pathValue }) + }, +} + +const show = ({ paths, path, cwd }: any) => ( + vimBlur(), + assignStateAndRender({ + ...resetState, + path, + paths, + vis: true, + cache: paths, + cwd: cwd || state.cwd, + }) +) + +state.inputCallbacks = { + // TODO: when choosing custom path and go back, make sure it updates correctly + // like ~/proj/veonim/ -> OK + // but ~/proj/veonim -> DERP! + + ctrlG: () => + assignStateAndRender({ pathMode: true, ix: 0, val: '', pathValue: '' }), + + ctrlH: async () => { + const { cwd } = api.nvim.state + const filedirs = await getDirFiles(cwd) + const paths = sortDirFiles(filedirs) + show({ paths, cwd, path: cwd }) + }, + + select: () => { + vimFocus() + if (!state.paths.length) { + assignStateAndRender(resetState) + return + } + + const { name, file } = state.paths[state.ix] + if (!name) return + + if (file) { + api.nvim.cmd(`e ${pathRelativeToCwd(join(state.path, name), state.cwd)}`) + assignStateAndRender(resetState) + return + } + + const path = join(state.path, name) + getDirFiles(path).then((paths) => + show({ path, paths: sortDirFiles(paths) }) + ) + }, + + change: (val: string) => + assignStateAndRender({ + val, + ix: 0, + paths: val + ? sortDirFiles(filter(state.paths, val, { key: 'name' })) + : state.cache, + }), + + jumpPrev: () => { + const next = state.path.split(sep) + next.pop() + const path = join(sep, ...next) + getDirFiles(path).then((paths) => + show({ path, paths: sortDirFiles(paths) }) + ) + }, + + // TODO: be more precise than this? also depends on scaled devices + down: () => { + listElRef.scrollTop += 300 + assignStateAndRender({ + ix: Math.min(state.ix + 17, state.paths.length - 1), + }) + }, + + up: () => { + listElRef.scrollTop -= 300 + assignStateAndRender({ ix: Math.max(state.ix - 17, 0) }) + }, + + top: () => { + listElRef.scrollTop = 0 + }, + + bottom: () => { + listElRef.scrollTop = listElRef.scrollHeight + }, + + hide: () => (vimFocus(), assignStateAndRender(resetState)), + next: () => + assignStateAndRender({ + ix: state.ix + 1 >= state.paths.length ? 0 : state.ix + 1, + }), + prev: () => + assignStateAndRender({ + ix: state.ix - 1 < 0 ? state.paths.length - 1 : state.ix - 1, + }), +} + +api.onAction('explorer', async (customDir?: string) => { + const { cwd, bufferType } = api.nvim.state + const isTerminal = bufferType === BufferType.Terminal + const currentDir = isTerminal ? cwd : api.nvim.state.dir + const path = customDir || currentDir + + const paths = sortDirFiles(await getDirFiles(path)) + show({ cwd, path, paths }) +}) diff --git a/src/components/extensions/files.tsx b/src/components/extensions/files.tsx new file mode 100644 index 00000000..6f0b8978 --- /dev/null +++ b/src/components/extensions/files.tsx @@ -0,0 +1,151 @@ +import { Plugin } from '../plugin-container' +import { RowNormal } from '../row-container' +import { vimBlur, vimFocus } from '../../ui/uikit' +import FiletypeIcon from '../filetype-icon' +import { basename, dirname, join } from 'path' +import Input from '../text-input' +import Worker from '../../messaging/worker' +import api from '../../core/instance-api' +import { cvar } from '../../ui/css' +import { render } from 'inferno' + +interface FileDir { + dir: string + file: string +} + +const worker = Worker('project-file-finder') +const formatDir = (dir: string) => (dir === '.' ? '' : `${dir}/`) +const asDirFile = (files: string[], currentFile: string) => + files + .filter((m) => m !== currentFile) + .map((path) => ({ + dir: formatDir(dirname(path)), + file: basename(path), + })) + +let state = { + val: '', + files: [] as FileDir[], + cache: [] as FileDir[], + visible: false, + ix: 0, + currentFile: '', + loading: false, + inputCallbacks: {}, +} + +type S = typeof state + +const resetState = { + val: '', + visible: false, + ix: 0, + loading: false, + cache: [], + files: [], +} + +const feather = require('feather-icons') +// TODO: loading is so fast that setting `loading` on the Input flickers +// and looks janky use debounce or throttle to only show this if a +// loading operation has already been going for a few ms. e.g. 150ms or +// more, etc. +const Files = ({ visible, inputCallbacks, val, files, ix: index }: S) => ( + + + +
+ {files.map(({ dir, file }, ix) => ( + + {FiletypeIcon(file)} + + {dir} + + {file} + + + ))} +
+
+) + +const container = document.createElement('div') +container.id = 'files-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = (currentFile: string) => ( + vimBlur(), + assignStateAndRender({ + visible: true, + currentFile, + files: state.cache, + loading: true, + }) +) + +const loadingDone = () => assignStateAndRender({ loading: false }) + +const results = (files: string[]) => + assignStateAndRender({ + cache: !state.cache.length ? files.slice(0, 10) : state.cache, + files: asDirFile(files, state.currentFile), + }) + +state.inputCallbacks = { + hide: () => { + worker.call.stop() + vimFocus() + assignStateAndRender(resetState) + }, + + select: () => { + vimFocus() + if (!state.files.length) { + assignStateAndRender(resetState) + return + } + const { dir, file } = state.files[state.ix] + const path = join(dir, file) + if (file) api.nvim.cmd(`e ${path}`) + assignStateAndRender(resetState) + }, + + change: (val: string) => { + worker.call.query(val) + assignStateAndRender({ val, ix: 0 }) + }, + + next: () => + assignStateAndRender({ + ix: state.ix + 1 > Math.min(state.files.length - 1, 9) ? 0 : state.ix + 1, + }), + prev: () => + assignStateAndRender({ + ix: state.ix - 1 < 0 ? Math.min(state.files.length - 1, 9) : state.ix - 1, + }), +} + +worker.on.results((files: string[]) => results(files)) +worker.on.done(loadingDone) + +api.onAction('files', () => { + worker.call.load(api.nvim.state.cwd) + show(api.nvim.state.file) +}) diff --git a/src/components/extensions/future/change-project.tsx b/src/components/extensions/future/change-project.tsx new file mode 100644 index 00000000..17743928 --- /dev/null +++ b/src/components/extensions/future/change-project.tsx @@ -0,0 +1,204 @@ +import { getDirFiles, exists, pathRelativeToHome } from '../../../support/utils' +import { createVim, renameCurrentToCwd } from '../../../core/instance-manager' +import { RowNormal, RowImportant } from '../../row-container' +import { vimBlur, vimFocus } from '../../../ui/uikit' +import { Plugin } from '../../plugin-container' +import Input from '../../text-input' +import { join, sep, basename } from 'path' +import { filter } from 'fuzzaldrin-plus' +import api from '../../../core/instance-api' +import { homedir } from 'os' +import { render } from 'inferno' + +const $HOME = homedir() + +interface FileDir { + name: string + file: boolean + dir: boolean +} + +let state = { + value: '', + cwd: '', + path: '', + paths: [] as FileDir[], + cache: [] as FileDir[], + visible: false, + index: 0, + create: false, + inputCallbacks: {}, +} + +type S = typeof state + +const absPath = (path = '') => + path.startsWith('~') ? join($HOME, path.slice(1)) : path +const validPath = async (path = '') => { + if (!path) return '' + const fullpath = absPath(path) + return (await exists(fullpath)) ? fullpath : '' +} + +const filterDirs = (filedirs: FileDir[]) => filedirs.filter((f) => f.dir) + +let listElRef: HTMLElement + +const resetState = { value: '', path: '', visible: false, index: 0 } + +const WhyDiv = (props: any) =>
{props.children}
+ +const feather = require('feather-icons') +const ChangeProject = ({ + create, + value, + visible, + path, + paths, + index, + inputCallbacks, +}: S) => ( + + + + {pathRelativeToHome(path)} + + { + if (e) listElRef = e + }} + style={{ 'max-height': '50vh', 'overflow-y': 'hidden' }} + > + {paths.map(({ name }, ix) => ( + + {name} + + ))} + + +) + +const container = document.createElement('div') +container.id = 'change-project-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), + render(, container) +) + +const show = ({ paths, path, cwd, create }: any) => ( + vimBlur(), + assignStateAndRender({ + path, + paths, + create, + cwd: cwd || state.cwd, + index: 0, + value: '', + visible: true, + cache: paths, + }) +) + +state.inputCallbacks = { + select: () => { + vimFocus() + if (!state.paths.length) { + assignStateAndRender(resetState) + return + } + const { name } = state.paths[state.index] + if (!name) return + const dirpath = join(state.path, name) + state.create ? createVim(name, dirpath) : api.nvim.cmd(`cd ${dirpath}`) + assignStateAndRender(resetState) + }, + + change: (value: string) => + assignStateAndRender({ + value, + index: 0, + paths: value + ? filterDirs(filter(state.paths, value, { key: 'name' })) + : state.cache, + }), + + tab: () => { + if (!state.paths.length) { + assignStateAndRender(resetState) + return + } + const { name } = state.paths[state.index] + if (!name) return + const path = join(state.path, name) + getDirFiles(path).then((paths) => show({ path, paths: filterDirs(paths) })) + }, + + jumpNext: () => { + const { name, dir } = state.paths[state.index] + if (!dir) return + const path = join(state.path, name) + getDirFiles(path).then((paths) => show({ path, paths: filterDirs(paths) })) + }, + + jumpPrev: () => { + const next = state.path.split(sep) + next.pop() + const path = join(sep, ...next) + getDirFiles(path).then((paths) => show({ path, paths: filterDirs(paths) })) + }, + + // TODO: be more precise than this? also depends on scaled devices + down: () => { + listElRef.scrollTop += 300 + assignStateAndRender({ + index: Math.min(state.index + 17, state.paths.length - 1), + }) + }, + + up: () => { + listElRef.scrollTop -= 300 + assignStateAndRender({ index: Math.max(state.index - 17, 0) }) + }, + + top: () => { + listElRef.scrollTop = 0 + }, + bottom: () => { + listElRef.scrollTop = listElRef.scrollHeight + }, + hide: () => (vimFocus(), assignStateAndRender(resetState)), + next: () => + assignStateAndRender({ + index: state.index + 1 >= state.paths.length ? 0 : state.index + 1, + }), + prev: () => + assignStateAndRender({ + index: state.index - 1 < 0 ? state.paths.length - 1 : state.index - 1, + }), +} + +const go = async (userPath: string, create = false) => { + const cwd = (await validPath(userPath)) || api.nvim.state.cwd + const filedirs = await getDirFiles(cwd) + const paths = filterDirs(filedirs) + show({ paths, cwd, path: cwd, create }) +} + +api.onAction('change-dir', (path = '') => go(path, false)) +api.onAction('vim-create-dir', (path = '') => go(path, true)) + +api.nvim.watchState.cwd((cwd: string) => { + if (cwd && homedir() !== cwd) renameCurrentToCwd(basename(cwd)) +}) + +export const changeDir = () => go('', false) +export const createInstanceWithDir = () => go('', true) diff --git a/src/components/extensions/future/generic-menu.tsx b/src/components/extensions/future/generic-menu.tsx new file mode 100644 index 00000000..d21243b8 --- /dev/null +++ b/src/components/extensions/future/generic-menu.tsx @@ -0,0 +1,122 @@ +import { Plugin } from '../../plugin-container' +import { RowNormal } from '../../row-container' +import { vimBlur, vimFocus } from '../../../ui/uikit' +import { CreateTask } from '../../../support/utils' +import Input from '../../text-input' +import { filter } from 'fuzzaldrin-plus' +import { render } from 'inferno' + +export interface MenuOption { + key: any + value: string +} + +interface Props { + description: string + options: MenuOption[] + icon?: Component +} + +let state = { + visible: false, + value: '', + options: [] as MenuOption[], + cache: [] as MenuOption[], + description: '', + ix: 0, + task: CreateTask(), + inputCallbacks: {}, +} + +type S = typeof state + +const resetState = { value: '', visible: false, ix: 0 } + +const feather = require('feather-icons') +const GenericMenu = ({ + visible, + inputCallbacks, + value, + description, + options, + ix: index, +}: S) => ( + + + +
+ {options.map(({ key, value }, id) => ( + + {value} + + ))} +
+
+) + +const container = document.createElement('div') +container.id = 'generic-menu-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = ({ options, description, icon, task }: any) => ( + vimBlur(), + assignStateAndRender({ + description, + options, + task, + icon, + cache: options, + visible: true, + }) +) + +state.inputCallbacks = { + select: () => { + vimFocus() + if (!state.options.length) return resetState + state.task.done((state.options[state.ix] || {}).key) + return resetState + }, + + // TODO: not hardcoded 14 + change: (value: string) => + assignStateAndRender({ + value, + ix: 0, + options: value + ? filter(state.cache, value, { key: 'value' }).slice(0, 14) + : state.cache.slice(0, 14), + }), + hide: () => (vimFocus(), assignStateAndRender(resetState)), + next: () => + assignStateAndRender({ + ix: + state.ix + 1 > Math.min(state.options.length - 1, 13) + ? 0 + : state.ix + 1, + }), + prev: () => + assignStateAndRender({ + ix: + state.ix - 1 < 0 + ? Math.min(state.options.length - 1, 13) + : state.ix - 1, + }), +} + +export default function (props: Props) { + const task = CreateTask() + show({ ...props, task }) + return task.promise +} diff --git a/src/components/extensions/future/generic-prompt.tsx b/src/components/extensions/future/generic-prompt.tsx new file mode 100644 index 00000000..737863c5 --- /dev/null +++ b/src/components/extensions/future/generic-prompt.tsx @@ -0,0 +1,66 @@ +import { Plugin } from '../../plugin-container' +import { vimBlur, vimFocus } from '../../../ui/uikit' +import { CreateTask } from '../../../support/utils' +import Input from '../../text-input' +import { render } from 'inferno' + +let state = { + value: '', + desc: '', + visible: false, + task: CreateTask(), + inputCallbacks: {}, +} + +type S = typeof state + +const resetState = { value: '', visible: false, desc: '' } + +const feather = require('feather-icons') +const GenericPrompt = ({ visible, value, desc, inputCallbacks }: S) => ( + + + +) + +const container = document.createElement('div') +container.id = 'generic-prompt-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), + render(, container) +) + +const show = ({ desc, task }: any) => ( + vimBlur(), + assignStateAndRender({ + desc, + task, + value: '', + visible: true, + }) +) + +state.inputCallbacks = { + hide: () => (vimFocus(), assignStateAndRender(resetState)), + change: (value: string) => assignStateAndRender({ value }), + select: () => { + state.value && state.task.done(state.value) + vimFocus() + assignStateAndRender(resetState) + }, +} + +export default (question: string) => { + const task = CreateTask() + show({ task, desc: question }) + return task.promise +} diff --git a/src/components/extensions/future/vim-create.tsx b/src/components/extensions/future/vim-create.tsx new file mode 100644 index 00000000..ce06cdb8 --- /dev/null +++ b/src/components/extensions/future/vim-create.tsx @@ -0,0 +1,50 @@ +import { Plugin } from '../../plugin-container' +import { vimBlur, vimFocus } from '../../../ui/uikit' +import { createVim } from '../../../core/instance-manager' +import Input from '../../text-input' +import api from '../../../core/instance-api' +import { render } from 'inferno' + +let state = { + value: '', + visible: false, + inputCallbacks: {}, +} + +type S = typeof state + +const feather = require('feather-icons') +const VimCreate = ({ visible, value, inputCallbacks }: S) => ( + + + +) + +const container = document.createElement('div') +container.id = 'vim-create-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = () => (vimBlur(), assignStateAndRender({ visible: true })) + +state.inputCallbacks = { + hide: () => (vimFocus(), assignStateAndRender({ value: '', visible: false })), + change: (value: string) => assignStateAndRender({ value }), + select: () => { + vimFocus() + state.value && createVim(state.value) + assignStateAndRender({ value: '', visible: false }) + }, +} + +api.onAction('vim-create', show) diff --git a/src/components/extensions/future/vim-rename.tsx b/src/components/extensions/future/vim-rename.tsx new file mode 100644 index 00000000..543eaf79 --- /dev/null +++ b/src/components/extensions/future/vim-rename.tsx @@ -0,0 +1,52 @@ +import { renameCurrent, getCurrentName } from '../../../core/instance-manager' +import { Plugin } from '../../plugin-container' +import { vimBlur, vimFocus } from '../../../ui/uikit' +import Input from '../../text-input' +import api from '../../../core/instance-api' +import { render } from 'inferno' + +let state = { + value: '', + visible: false, + inputCallbacks: {}, +} + +type S = typeof state + +const feather = require('feather-icons') +const VimRename = ({ visible, value, inputCallbacks }: S) => ( + + + +) + +const container = document.createElement('div') +container.id = 'vim-rename-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = (value: string) => ( + vimBlur(), assignStateAndRender({ value, visible: true }) +) + +state.inputCallbacks = { + hide: () => (vimFocus(), assignStateAndRender({ value: '', visible: false })), + change: (value: string) => assignStateAndRender({ value }), + select: () => { + vimFocus() + state.value && renameCurrent(state.value) + assignStateAndRender({ value: '', visible: false }) + }, +} + +api.onAction('vim-rename', () => show(getCurrentName())) diff --git a/src/components/extensions/future/vim-switch.tsx b/src/components/extensions/future/vim-switch.tsx new file mode 100644 index 00000000..da4f7983 --- /dev/null +++ b/src/components/extensions/future/vim-switch.tsx @@ -0,0 +1,101 @@ +import { list, switchVim } from '../../../core/instance-manager' +import { Plugin } from '../../plugin-container' +import { RowNormal } from '../../row-container' +import { vimBlur, vimFocus } from '../../../ui/uikit' +import Input from '../../text-input' +import { filter } from 'fuzzaldrin-plus' +import api from '../../../core/instance-api' +import { render } from 'inferno' + +interface Instance { + id: number + name: string +} + +let state = { + value: '', + visible: false, + list: [] as Instance[], + cache: [] as Instance[], + index: 0, + inputCallbacks: {}, +} + +type S = typeof state + +const feather = require('feather-icons') +const VimSwitch = ({ visible, value, index, inputCallbacks, list }: S) => ( + + + +
+ {list.map(({ id, name }, ix) => ( + + {name} + + ))} +
+
+) + +const container = document.createElement('div') +container.id = 'vim-rename-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = (d: Instance[]) => ( + vimBlur(), assignStateAndRender({ list: d, cache: d, visible: true }) +) + +state.inputCallbacks = { + hide: () => ( + vimFocus(), assignStateAndRender({ value: '', visible: false, index: 0 }) + ), + change: (value: string) => + assignStateAndRender({ + value, + index: 0, + list: value + ? filter(state.list, value, { key: 'name' }).slice(0, 10) + : state.cache.slice(0, 10), + }), + + select: () => { + vimFocus() + if (!state.list.length) { + assignStateAndRender({ value: '', visible: false, index: 0 }) + return + } + const { id } = state.list[state.index] + if (id) switchVim(id) + assignStateAndRender({ value: '', visible: false, index: 0 }) + }, + + // TODO: don't limit list to 10 entries and scroll instead! + next: () => + assignStateAndRender({ + index: + state.index + 1 > Math.min(state.list.length - 1, 9) + ? 0 + : state.index + 1, + }), + prev: () => + assignStateAndRender({ + index: + state.index - 1 < 0 + ? Math.min(state.list.length - 1, 9) + : state.index - 1, + }), +} + +api.onAction('vim-switch', () => show(list())) diff --git a/src/components/extensions/grep.tsx b/src/components/extensions/grep.tsx new file mode 100644 index 00000000..2eab0d6d --- /dev/null +++ b/src/components/extensions/grep.tsx @@ -0,0 +1,347 @@ +import { RowNormal, RowHeader } from '../row-container' +import { PluginRight } from '../plugin-container' +import { vimBlur, vimFocus } from '../../ui/uikit' +import { showCursorline } from '../../core/cursor' +import Input from '../text-input' +import { badgeStyle } from '../../ui/styles' +import { render } from 'inferno' +import Worker from '../../messaging/worker' +import api from '../../core/instance-api' + +type Result = [string, SearchResult[]] + +enum FocusedElement { + Search, + Filter, +} + +interface SearchResult { + line: number + column: number + text: string +} + +let elref: HTMLElement +const SCROLL_AMOUNT = 0.25 +const worker = Worker('search-files') +const els = new Map() + +let state = { + value: '', + filterVal: '', + cwd: '', + results: [] as Result[], + visible: false, + ix: 0, + subix: -1, + loading: false, + focused: FocusedElement.Search, + mainSearchInputCallbacks: {}, + filterInputCallbacks: {}, +} + +type S = typeof state + +// scroll after next section has been rendered as expanded (a little hacky) +const scrollIntoView = (next: number) => + setTimeout(() => { + const { + top: containerTop, + bottom: containerBottom, + } = elref.getBoundingClientRect() + const e = els.get(next) + if (!e) return + + const { top, height } = e.getBoundingClientRect() + + if (top + height > containerBottom) { + const offset = top - containerBottom + + if (offset < containerTop) elref.scrollTop += top - containerTop + else elref.scrollTop += offset + height + containerTop + 50 + } else if (top < containerTop) elref.scrollTop += top - containerTop + }, 1) + +const selectResult = (results: Result[], ix: number, subix: number) => { + if (subix < 0) return + const [path, items] = results[ix] + const { line, column } = items[subix] + api.nvim.jumpTo({ path, line, column }) + showCursorline() +} + +const highlightPattern = ( + text: string, + pattern: string, + { + normal, + special, + }: { + normal: (text: any, last?: boolean) => any + special: (text: any, last?: boolean) => any + } +) => { + const stext = special(pattern) + return text + .trimLeft() + .split(pattern) + .reduce((grp, part, ix, arr) => { + if (!part && ix) return grp.push(stext), grp + if (!part) return grp + const last = ix === arr.length - 1 + ix ? grp.push(stext, normal(part, last)) : grp.push(normal(part, last)) + return grp + }, [] as any[]) +} + +const resetState = { visible: false, loading: false } + +const WhyDiv = (props: any) =>
{props.children}
+ +const feather = require('feather-icons') +const Grep = ({ + visible, + filterVal, + value, + focused, + loading, + mainSearchInputCallbacks, + filterInputCallbacks, + subix, + ix: index, + results, +}: S) => ( + + + + (elref = e)} + style={{ + 'max-height': '100%', + 'overflow-y': 'hidden', + }} + > + {results.map(([path, items], pos) => ( + els.set(pos, e)}> + + {path} +
+ {items.length} +
+
+ + {pos === index && ( +
+ {items.map((f, itemPos: number) => ( + + {highlightPattern(f.text, value, { + normal: (text, last) => ( + + {text} + + ), + + special: (text) => ( + + {text} + + ), + })} + + ))} +
+ )} +
+ ))} +
+
+) + +const container = document.createElement('div') +container.id = 'grep-container' +document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = ({ cwd, value, reset = true }: any) => + reset + ? (vimBlur(), + assignStateAndRender({ + visible: true, + cwd, + value, + ix: 0, + subix: -1, + results: [], + loading: !!value, + })) + : (vimBlur(), assignStateAndRender({ visible: true })) + +const results = (results: Result[]) => assignStateAndRender({ results }) + +const moreResults = (results: Result[]) => { + const merged = [...state.results, ...results] + const deduped = merged.filter( + (m, ix, arr) => arr.findIndex((e) => e[0] === m[0]) === ix + ) + assignStateAndRender({ results: deduped }) +} + +const loadingDone = ({ empty }: any) => + assignStateAndRender({ + loading: false, + results: empty ? [] : state.results, + }) + +const sharedCallbacks = { + hide: () => (vimFocus(), assignStateAndRender(resetState)), + select: () => { + vimFocus() + if (!state.results.length) { + assignStateAndRender(resetState) + return + } + selectResult(state.results, state.ix, state.subix) + assignStateAndRender(resetState) + }, + + nextGroup: () => { + const next = state.ix + 1 > state.results.length - 1 ? 0 : state.ix + 1 + scrollIntoView(next) + assignStateAndRender({ subix: -1, ix: next }) + }, + + prevGroup: () => { + const next = state.ix - 1 < 0 ? state.results.length - 1 : state.ix - 1 + scrollIntoView(next) + assignStateAndRender({ subix: -1, ix: next }) + }, + + next: () => { + const next = + state.subix + 1 < state.results[state.ix][1].length ? state.subix + 1 : 0 + selectResult(state.results, state.ix, next) + assignStateAndRender({ subix: next }) + }, + + prev: () => { + const prev = + state.subix - 1 < 0 + ? state.results[state.ix][1].length - 1 + : state.subix - 1 + selectResult(state.results, state.ix, prev) + assignStateAndRender({ subix: prev }) + }, + + down: () => { + const { height } = elref.getBoundingClientRect() + const maxScroll = elref.scrollHeight - height + // TODO: should wait until get results back before calling loadNext again... + if (elref.scrollTop === maxScroll) return worker.call.loadNext() + elref.scrollTop += Math.floor(height * SCROLL_AMOUNT) + }, + + up: () => { + const { height } = elref.getBoundingClientRect() + elref.scrollTop -= Math.floor(height * SCROLL_AMOUNT) + }, +} + +state.mainSearchInputCallbacks = { + ...sharedCallbacks, + focusFilter: () => assignStateAndRender({ focused: FocusedElement.Filter }), + + change: (value: string) => { + value && worker.call.query({ query: value, cwd: state.cwd }) + assignStateAndRender( + value + ? { + value, + loading: true, + } + : { + value, + results: [], + ix: 0, + subix: 0, + loading: false, + } + ) + }, +} + +state.filterInputCallbacks = { + ...sharedCallbacks, + focusSearch: () => assignStateAndRender({ focused: FocusedElement.Search }), + changeFilter: (filterVal: string) => { + worker.call.filter(filterVal) + assignStateAndRender({ filterVal }) + }, +} + +worker.on.results((resList: Result[]) => results(resList)) +worker.on.moreResults((results: Result[]) => moreResults(results)) +worker.on.done(loadingDone) + +api.onAction('grep-resume', () => show({ reset: false })) + +api.onAction('grep', async (query: string) => { + const { cwd } = api.nvim.state + show({ cwd }) + query && worker.call.query({ query, cwd }) +}) + +api.onAction('grep-word', async () => { + const { cwd } = api.nvim.state + const query = await api.nvim.call.expand('') + show({ cwd, value: query }) + worker.call.query({ query, cwd }) +}) + +// TODO: rename to grep-visual to be consistent with other actions +// operating from visual mode +api.onAction('grep-selection', async () => { + // TODO(smolck): This was `await`ed + api.nvim.feedkeys('gv"zy') + + const selection = await api.nvim.expr('@z') + const [query] = selection.split('\n') + const { cwd } = api.nvim.state + show({ cwd, value: query }) + worker.call.query({ query, cwd }) +}) diff --git a/src/components/buffer-search.ts b/src/components/extensions/legacy/buffer-search.ts similarity index 100% rename from src/components/buffer-search.ts rename to src/components/extensions/legacy/buffer-search.ts diff --git a/src/components/debug.ts b/src/components/extensions/legacy/debug.ts similarity index 100% rename from src/components/debug.ts rename to src/components/extensions/legacy/debug.ts diff --git a/src/components/divination.ts b/src/components/extensions/legacy/divination.ts similarity index 100% rename from src/components/divination.ts rename to src/components/extensions/legacy/divination.ts diff --git a/src/components/inventory-search.ts b/src/components/extensions/legacy/inventory-search.ts similarity index 100% rename from src/components/inventory-search.ts rename to src/components/extensions/legacy/inventory-search.ts diff --git a/src/components/inventory.ts b/src/components/extensions/legacy/inventory.ts similarity index 100% rename from src/components/inventory.ts rename to src/components/extensions/legacy/inventory.ts diff --git a/src/components/problem-info.ts b/src/components/extensions/legacy/problem-info.ts similarity index 100% rename from src/components/problem-info.ts rename to src/components/extensions/legacy/problem-info.ts diff --git a/src/components/spell-check.ts b/src/components/extensions/legacy/spell-check.ts similarity index 100% rename from src/components/spell-check.ts rename to src/components/extensions/legacy/spell-check.ts diff --git a/src/components/user-menu.ts b/src/components/extensions/legacy/user-menu.ts similarity index 100% rename from src/components/user-menu.ts rename to src/components/extensions/legacy/user-menu.ts diff --git a/src/components/user-overlay-menu.ts b/src/components/extensions/legacy/user-overlay-menu.ts similarity index 100% rename from src/components/user-overlay-menu.ts rename to src/components/extensions/legacy/user-overlay-menu.ts diff --git a/src/components/viewport-search.ts b/src/components/extensions/legacy/viewport-search.ts similarity index 98% rename from src/components/viewport-search.ts rename to src/components/extensions/legacy/viewport-search.ts index 84fe7438..29fd8f1a 100644 --- a/src/components/viewport-search.ts +++ b/src/components/extensions/legacy/viewport-search.ts @@ -1,4 +1,4 @@ -import { divinationSearch } from '../components/divination' +import { divinationSearch } from '../components/legacy/divination' import { app, h, vimBlur, vimFocus } from '../ui/uikit' import * as windows from '../windows/window-manager' import { WindowOverlay } from '../windows/window' diff --git a/src/components/extensions/lsp-code-action.tsx b/src/components/extensions/lsp-code-action.tsx new file mode 100644 index 00000000..5d33a290 --- /dev/null +++ b/src/components/extensions/lsp-code-action.tsx @@ -0,0 +1,135 @@ +import { RowNormal } from '../row-container' +import { vimBlur, vimFocus } from '../../ui/uikit' +import * as windows from '../../windows/window-manager' +import Input from '../text-input' +import Overlay from '../overlay' +import { filter } from 'fuzzaldrin-plus' +import { render } from 'inferno' +import api from '../../core/instance-api' +import { cursor } from '../../core/cursor' + +type CodeAction = { + title: string + kind?: string + isPreferred?: boolean + edit?: any + command?: any + arguments: any +} + +let state = { + x: 0, + y: 0, + value: '', + visible: false, + actions: [] as CodeAction[], + cache: [] as CodeAction[], + index: 0, +} + +type S = typeof state + +const resetState = { value: '', visible: false } + +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +container.id = 'code-action-container' +plugins?.appendChild(container) + +const feather = require('feather-icons') +const CodeAction = ({ x, y, visible, value, actions, index }: S) => ( + +
+ + {actions.map((s, ix) => ( + + {s.title} + + ))} +
+
+) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const show = ({ x, y, actions }: any) => { + vimBlur() + assignStateAndRender({ x, y, actions, cache: actions, visible: true }) +} + +const hide = () => { + vimFocus() + assignStateAndRender(resetState) +} + +const change = (value: string) => + assignStateAndRender({ + value, + index: 0, + actions: value + ? filter(state.actions, value, { key: 'title' }) + : state.cache, + }) + +const select = () => { + vimFocus() + if (!state.actions.length) return resetState + const action = state.actions[state.index] + if (action) + // @ts-ignore <- without this get an error about luaeval not being a + // property + + // roundtrip through vimscript since TS dict looks like a vimscript dict + // TODO: see if action can be converted to a Lua table to allow direct call to lua + api.nvim.call.luaeval( + "require'uivonim/lsp'.handle_chosen_code_action(_A)", + action + ) + assignStateAndRender(resetState) +} + +const next = () => + assignStateAndRender({ + index: state.index + 1 > state.actions.length - 1 ? 0 : state.index + 1, + }) + +const prev = () => + assignStateAndRender({ + index: state.index - 1 < 0 ? state.actions.length - 1 : state.index - 1, + }) + +api.onAction('code-action', (actions) => { + const { x, y } = windows.pixelPosition(cursor.row + 1, cursor.col) + show({ + x, + y, + actions: actions.map((x: any) => ({ + title: x.title, + kind: x.kind, + edit: x.edit, + command: x.command, + arguments: x.arguments, + })), + }) +}) diff --git a/src/components/extensions/lsp-hover.tsx b/src/components/extensions/lsp-hover.tsx new file mode 100644 index 00000000..cee5ea15 --- /dev/null +++ b/src/components/extensions/lsp-hover.tsx @@ -0,0 +1,115 @@ +import * as windows from '../../windows/window-manager' +import { ColorData } from '../../services/colorizer' +import { sub } from '../../messaging/dispatch' +import { debounce } from '../../support/utils' +import Overlay from '../overlay' +import { docStyle } from '../../ui/styles' +import { cursor } from '../../core/cursor' +import { parse as stringToMarkdown, setOptions } from 'marked' +import { render } from 'inferno' +import api from '../../core/instance-api' +import { cell, size as workspaceSize } from '../../core/workspace' + +setOptions({ + highlight: (code, lang, _) => { + const hljs = require('highlight.js/lib/core') + hljs.registerLanguage(lang, require(`highlight.js/lib/languages/${lang}`)) + + const highlightedCode = hljs.highlight(lang, code).value + return highlightedCode + }, +}) + +interface ShowParams { + hoverHeight: number + maxWidth: number + data: ColorData[][] + doc?: string +} + +// TODO(smolck): Should sanitize this HTML probably because safety. +const docs = (data: string) => ( +
${stringToMarkdown(data)}` }} + /> +) + +const getPosition = (row: number, col: number, heightOfHover: number) => + heightOfHover > row + ? { ...windows.pixelPosition(row + 1, col), anchorBottom: false } + : { ...windows.pixelPosition(row, col), anchorBottom: true } + +let state = { + value: [[]] as ColorData[][], + visible: false, + anchorBottom: true, + hoverHeight: 2, + maxWidth: 400, // TODO(smolck): Sane default? Is this even necessary? + doc: '', + x: 0, + y: 0, +} + +type S = typeof state + +const Hover = ({ doc, visible, x, y, anchorBottom, maxWidth }: S) => ( + + {doc && !anchorBottom && docs(doc)} + {doc && anchorBottom && docs(doc)} + +) + +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +container.id = 'hover-container' +plugins?.appendChild(container) + +const hide = () => ( + (state.visible = false), render(, container) +) +const show = ({ data, doc, hoverHeight, maxWidth }: ShowParams) => { + if (doc) state.doc = doc + Object.assign(state, { + hoverHeight, + maxWidth, + value: data, + visible: true, + ...getPosition(cursor.row, cursor.col, hoverHeight), + }) + + render(, container) +} +const updatePosition = () => { + if (state.visible) + Object.assign(state, getPosition(cursor.row, cursor.col, state.hoverHeight)) + + render(, container) +} + +api.onAction('hover', (_, markdownLines) => { + const doc = markdownLines.join('\n') + + const maxWidth = + cell.width * + (markdownLines.reduce( + (acc: number, item: string[]) => (item.length > acc ? item.length : acc), + markdownLines[0].length + ) + + 2) // Add 2 to prevent wrapping unless necessary. + + show({ data: [[]], doc, maxWidth, hoverHeight: markdownLines.length }) +}) + +api.onAction('hover-close', hide) + +sub('redraw', () => { + if (state.visible) debounce(updatePosition, 50) +}) diff --git a/src/components/extensions/lsp-references.tsx b/src/components/extensions/lsp-references.tsx new file mode 100644 index 00000000..d2cbe56a --- /dev/null +++ b/src/components/extensions/lsp-references.tsx @@ -0,0 +1,307 @@ +import { RowNormal, RowHeader } from '../row-container' +import { PluginRight } from '../plugin-container' +import { vimBlur, vimFocus } from '../../ui/uikit' +import { simplifyPath } from '../../support/utils' +import { showCursorline } from '../../core/cursor' +import { badgeStyle } from '../../ui/styles' +import { render } from 'inferno' +import Input from '../text-input' +import api from '../../core/instance-api' + +type Reference = { + lineNum: number + column: number + text: string +} + +type Refs = [string, Reference[]] + +let elref: HTMLElement +const SCROLL_AMOUNT = 0.25 +const els = new Map() + +let state = { + val: '', + referencedSymbol: '', + references: [] as Refs[], + cache: [] as Refs[], + vis: false, + ix: 0, + subix: -1, + loading: false, +} + +type S = typeof state + +// scroll after next section has been rendered as expanded (a little hacky) +const scrollIntoView = (next: number) => + setTimeout(() => { + const { + top: containerTop, + bottom: containerBottom, + } = elref.getBoundingClientRect() + const e = els.get(next) + if (!e) return + + const { top, height } = e.getBoundingClientRect() + + if (top + height > containerBottom) { + const offset = top - containerBottom + + if (offset < containerTop) elref.scrollTop += top - containerTop + else elref.scrollTop += offset + height + containerTop + 50 + } else if (top < containerTop) elref.scrollTop += top - containerTop + }, 1) + +const scrollSubitemsIntoView = (parentIx: number, next: number) => + setTimeout(() => { + const { + top: containerTop, + bottom: containerBottom, + } = elref.getBoundingClientRect() + const e = els.get(parentIx)?.children[1].children[next] + if (!e) return + + const { top, height } = e.getBoundingClientRect() + + if (top + height > containerBottom) { + const offset = top - containerBottom + + if (offset < containerTop) elref.scrollTop += top - containerTop + else elref.scrollTop += offset + height + containerTop + 50 + } else if (top < containerTop) elref.scrollTop += top - containerTop + }) + +const selectResult = (references: Refs[], ix: number, subix: number) => { + if (subix < 0) return + const [path, items] = references[ix] + const { lineNum, column } = items[subix] + + api.nvim.jumpTo({ + path, + line: lineNum - 1, + column: column - 1, + }) + showCursorline() +} + +const highlightPattern = ( + text: string, + pattern: string, + { + normal, + special, + }: { + normal: (text: any, last?: boolean) => any + special: (text: any, last?: boolean) => any + } +) => { + const stext = special(pattern) + return text + .trimLeft() + .split(pattern) + .reduce((grp, part, ix, arr) => { + if (!part && ix) return grp.push(stext), grp + if (!part) return grp + const last = ix === arr.length - 1 + ix ? grp.push(stext, normal(part, last)) : grp.push(normal(part, last)) + return grp + }, [] as any[]) +} + +const resetState = { vis: false, references: [] } + +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +container.id = 'references-container' +plugins?.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), + render(, container) +) + +const hide = () => { + vimFocus() + assignStateAndRender(resetState) +} + +const show = ({ references, referencedSymbol }: any) => { + vimBlur() + + assignStateAndRender({ + references, + referencedSymbol, + cache: references, + vis: true, + val: '', + ix: 0, + subix: -1, + loading: false, + }) +} + +const select = () => { + vimFocus() + if (!state.references.length) { + assignStateAndRender(resetState) + } + selectResult(state.references, state.ix, state.subix) + + assignStateAndRender(resetState) +} + +const change = (val: string) => + assignStateAndRender({ + val, + references: val + ? state.cache.map((m) => [ + m[0], + m[1].filter((x) => x.text.toLowerCase().includes(val)), + ]) + : state.cache, + }) + +const nextGroup = () => { + const next = state.ix + 1 > state.references.length - 1 ? 0 : state.ix + 1 + scrollIntoView(next) + assignStateAndRender({ subix: -1, ix: next }) +} + +const prevGroup = () => { + const next = state.ix - 1 < 0 ? state.references.length - 1 : state.ix - 1 + scrollIntoView(next) + assignStateAndRender({ subix: -1, ix: next }) +} + +const next = () => { + const next = + state.subix + 1 < state.references[state.ix][1].length ? state.subix + 1 : 0 + selectResult(state.references, state.ix, next) + scrollSubitemsIntoView(state.ix, next) + assignStateAndRender({ subix: next }) +} + +const prev = () => { + const previous = + state.subix - 1 < 0 + ? state.references[state.ix][1].length - 1 + : state.subix - 1 + selectResult(state.references, state.ix, previous) + scrollSubitemsIntoView(state.ix, previous) + assignStateAndRender({ subix: previous }) +} + +const down = () => { + const { height } = elref.getBoundingClientRect() + elref.scrollTop += Math.floor(height * SCROLL_AMOUNT) +} + +const up = () => { + const { height } = elref.getBoundingClientRect() + elref.scrollTop -= Math.floor(height * SCROLL_AMOUNT) +} + +// TODO(smolck): Is this really necessary just to get 'onComponentDidMount'? +const WhyDiv = (props: any) =>
{props.children}
+ +const feather = require('feather-icons') +const References = ($: S) => ( + + + (elref = e)} + style={{ 'max-height': '100%', overflow: 'hidden' }} + > + {$.references.map(([path, items], pos) => ( + els.set(pos, e)} + > + + {simplifyPath(path, api.nvim.state.cwd)} +
+ {items.length} +
+
+ {pos === $.ix && ( +
+ {items.map((f, itemPos) => ( + + {highlightPattern(f.text, $.referencedSymbol, { + normal: (text, last) => ( + + {text} + + ), + + special: (text) => ( + + {text} + + ), + })} + + ))} +
+ )} +
+ ))} +
+
+) + +api.onAction('references', (_, items) => { + // TODO(smolck): Efficiency? This works but probably isn't the most + // performant. Ideally could remove the intermediate map. + // + // This code essentially takes a series of code reference objects from Lua, + // sorts them by filename (leveraging the map), and then turns that into + // an array for use above. + const itemsMap = items.reduce((map: Map, x: any) => { + const ref = { + lineNum: x.lnum, + column: x.col, + text: x.text, + } as Reference + + let maybeArr = map.get(x.filename) + if (maybeArr) maybeArr.push(ref) + else map.set(x.filename, [ref]) + + return map + }, new Map()) + + let stuffToShow = [] as Refs[] + itemsMap.forEach((value: Reference[], key: string) => + stuffToShow.push([key, value]) + ) + + show({ references: stuffToShow }) +}) diff --git a/src/components/extensions/lsp-signature-help.tsx b/src/components/extensions/lsp-signature-help.tsx new file mode 100644 index 00000000..39e2efd4 --- /dev/null +++ b/src/components/extensions/lsp-signature-help.tsx @@ -0,0 +1,211 @@ +import { docStyle, resetMarkdownHTMLStyle } from '../../ui/styles' +import * as windows from '../../windows/window-manager' +import Overlay from '../overlay' +import { cvar } from '../../ui/css' +import { render } from 'inferno' +import api from '../../core/instance-api' +import { parse as stringToMarkdown } from 'marked' + +interface ShowParams { + row: number + col: number + label: string + activeParam: string | [number, number] + documentation?: string + paramDoc?: string + totalSignatures: number + selectedSignature: number +} + +const fadedStyle: CSSProperties = { + color: cvar('foreground'), + filter: 'opacity(60%)', +} + +const strongStyle: CSSProperties = { + color: cvar('foreground'), + 'font-weight': 'bold', +} + +// TODO(smolck): Inner HTML sanitization (?) +const docs = (data: string) => ( +
${stringToMarkdown( + data + )}
`, + }} + /> +) + +const sliceAndDiceLabel = ( + label: string, + activeParam: string | [number, number] +) => { + let x, labelStart, labelEnd + + if (typeof activeParam === 'string') { + const paramStart = label.indexOf(activeParam) + labelStart = label.slice(0, paramStart) + x = label.slice(paramStart, paramStart + activeParam.length) + labelEnd = label.slice(paramStart + activeParam.length) + } else { + labelStart = label.slice(0, activeParam[0]) + x = label.slice(activeParam[0], activeParam[1]) + labelEnd = label.slice(activeParam[1]) + } + + return { labelStart, labelEnd, activeParam: x } +} + +const fresh = ({ + row, + col, + documentation, + selectedSignature, + totalSignatures, +}: any) => ({ + row, + col, + documentation, + selectedSignature, + totalSignatures, +}) + +let state = { + label: '', + labelStart: '', + labelEnd: '', + activeParam: '', + documentation: '', + paramDoc: '', + anchorBottom: true, + totalSignatures: 0, + selectedSignature: 0, + visible: false, + row: 0, + col: 0, +} + +type S = typeof state + +const SignatureHelp = ({ + documentation, + paramDoc, + anchorBottom, + visible, + row, + col, + labelStart, + labelEnd, + activeParam, + totalSignatures, + selectedSignature, +}: S) => ( + 2 ? row : row + 1, col - 1)} + zIndex={200} + maxWidth={600} + visible={visible} + anchorAbove={anchorBottom} + > +
+
+ {documentation && docs(documentation)} + {paramDoc && docs(paramDoc)} +
+ +
+
+ + {labelStart} + + + + {activeParam} + + + + {labelEnd} + +
+ + {totalSignatures > 1 && ( + // TODO, smolck: With hyperapp, there was this sort of property: + // `render: totalSignatures > 1`. What did that do? +
+ {selectedSignature}/{totalSignatures} +
+ )} +
+
+
+) + +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +container.id = 'signature-help-container' +plugins?.appendChild(container) + +const hide = () => ( + (state = Object.assign(state, { visible: false, label: '', row: 0 })), + render(, container) +) + +const show = ({ + row, + col, + label, + activeParam: x, + documentation, + paramDoc, + selectedSignature, + totalSignatures, +}: ShowParams) => { + const { labelStart, labelEnd, activeParam } = sliceAndDiceLabel(label, x) + const same = state.label === label && state.row === row + const stuff = same + ? {} + : fresh({ row, col, documentation, selectedSignature, totalSignatures }) + + Object.assign(state, { + ...stuff, + label, + labelStart, + labelEnd, + paramDoc, + anchorBottom: row > 2, + activeParam: activeParam, + visible: true, + }) + + render(, container) +} + +// See runtime/lua/uivonim.lua +api.onAction('signature-help', (_, showParams) => { + show(showParams) +}) + +api.onAction('signature-help-close', hide) diff --git a/src/components/files.ts b/src/components/files.ts deleted file mode 100644 index 7ee4ca50..00000000 --- a/src/components/files.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { Plugin } from '../components/plugin-container' -import { RowNormal } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import FiletypeIcon from '../components/filetype-icon' -import { basename, dirname, join } from 'path' -import Input from '../components/text-input' -import Worker from '../messaging/worker' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' -import { cvar } from '../ui/css' - -interface FileDir { - dir: string - file: string -} - -const worker = Worker('project-file-finder') -const formatDir = (dir: string) => (dir === '.' ? '' : `${dir}/`) -const asDirFile = (files: string[], currentFile: string) => - files - .filter((m) => m !== currentFile) - .map((path) => ({ - dir: formatDir(dirname(path)), - file: basename(path), - })) - -const state = { - val: '', - files: [] as FileDir[], - cache: [] as FileDir[], - vis: false, - ix: 0, - currentFile: '', - loading: false, -} - -type S = typeof state - -const resetState = { - val: '', - vis: false, - ix: 0, - loading: false, - cache: [], - files: [], -} - -const actions = { - show: (currentFile: string) => (s: S) => ( - vimBlur(), - { - vis: true, - currentFile, - files: s.cache, - loading: true, - } - ), - - hide: () => { - worker.call.stop() - vimFocus() - return resetState - }, - - select: () => (s: S) => { - vimFocus() - if (!s.files.length) return resetState - const { dir, file } = s.files[s.ix] - const path = join(dir, file) - if (file) api.nvim.cmd(`e ${path}`) - return resetState - }, - - change: (val: string) => { - worker.call.query(val) - return { val, ix: 0 } - }, - - results: (files: string[]) => (s: S) => ({ - cache: !s.cache.length ? files.slice(0, 10) : s.cache, - files: asDirFile(files, s.currentFile), - }), - - loadingDone: () => ({ loading: false }), - - next: () => (s: S) => ({ - ix: s.ix + 1 > Math.min(s.files.length - 1, 9) ? 0 : s.ix + 1, - }), - prev: () => (s: S) => ({ - ix: s.ix - 1 < 0 ? Math.min(s.files.length - 1, 9) : s.ix - 1, - }), -} - -const view = ($: S, a: typeof actions) => - Plugin($.vis, [ - , - Input({ - hide: a.hide, - select: a.select, - change: a.change, - next: a.next, - prev: a.prev, - value: $.val, - focus: true, - icon: Icon.FileText, - desc: 'open file', - // TODO: loading is so fast that this flickers and looks janky - // use debounce or throttle to only show this if a loading operation - // has already been going for a few ms. e.g. 150ms or more, etc. - //loading: $.loading, - }), - - h( - 'div', - $.files.map(({ dir, file }, ix) => - RowNormal( - { - active: ix === $.ix, - }, - [ - , - FiletypeIcon(file), - - h('span', { style: { color: cvar('foreground-50') } }, dir), - - h( - 'span', - { - style: { - color: - ix === $.ix - ? cvar('foreground-b20') - : cvar('foreground-30'), - }, - }, - file - ), - ] - ) - ) - ), - ]) - -const ui = app({ name: 'files', state, actions, view }) - -worker.on.results((files: string[]) => ui.results(files)) -worker.on.done(ui.loadingDone) - -api.onAction('files', () => { - worker.call.load(api.nvim.state.cwd) - ui.show(api.nvim.state.file) -}) - -export const show = () => {} diff --git a/src/components/filetype-icon.ts b/src/components/filetype-icon.ts deleted file mode 100644 index 6177ff88..00000000 --- a/src/components/filetype-icon.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as FeatherIcon from 'hyperapp-feather' -import { pascalCase } from '../support/utils' -import { basename, extname } from 'path' -import * as Icons from 'hyperapp-seti' -import { h } from '../ui/uikit' - -const findIcon = (id: string) => id && Reflect.get(Icons, pascalCase(id)) - -const customMappings = new Map([ - ['readme.md', 'info'], - ['gif', 'image'], - ['jpg', 'image'], - ['jpeg', 'image'], - ['png', 'image'], - ['svg', 'image'], -]) - -const findIconCustom = (filename: string, extension: string) => { - const mapping = customMappings.get(extension) || customMappings.get(filename) - return mapping && findIcon(mapping) -} - -const getIcon = (path = '') => { - const filename = basename(path).toLowerCase() - const extension = extname(filename).replace(/^\./, '').toLowerCase() - - return ( - findIconCustom(filename, extension) || - findIcon(extension) || - findIcon(filename) || - findIcon(path.toLowerCase()) || - Icons.Shell - ) -} - -const featherStyle = { - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - marginRight: '8px', - marginLeft: '3px', - fontSize: '1.1rem', -} - -export const Folder = h( - 'div', - { - style: featherStyle, - }, - [, h(FeatherIcon.Folder)] -) - -export const Terminal = h( - 'div', - { - style: featherStyle, - }, - [, h(FeatherIcon.Terminal)] -) - -export default (fileTypeOrPath: string) => - h( - 'div', - { - style: { - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - marginRight: '6px', - marginTop: '2px', - fontSize: '1.5rem', - color: '#ccc', - }, - }, - [, h(getIcon(fileTypeOrPath))] - ) diff --git a/src/components/filetype-icon.tsx b/src/components/filetype-icon.tsx new file mode 100644 index 00000000..d1fd2136 --- /dev/null +++ b/src/components/filetype-icon.tsx @@ -0,0 +1,66 @@ +import { basename, extname } from 'path' +// TODO(smolck): import * as Icons from 'hyperapp-seti' +import Icon from './icon' + +const customMappings = new Map([ + ['readme.md', 'info'], + ['gif', 'image'], + ['jpg', 'image'], + ['jpeg', 'image'], + ['png', 'image'], + ['svg', 'image'], +]) + +const feather = require('feather-icons') +const findIconCustom = (filename: string, extension: string) => { + const mapping = customMappings.get(extension) || customMappings.get(filename) + return mapping && +} + +const getIcon = (path = '') => { + const filename = basename(path).toLowerCase() + const extension = extname(filename).replace(/^\./, '').toLowerCase() + + return ( + findIconCustom(filename, extension) || ( + + ) + ) +} + +const featherStyle: CSSProperties = { + display: 'flex', + 'justify-content': 'center', + 'align-items': 'center', + 'margin-right': '8px', + 'margin-left': '3px', + 'font-size': '1.1rem', +} + +export const Folder = ( +
+ +
+) + +export const Terminal = ( +
+ +
+) + +export default (fileTypeOrPath: string) => ( +
+ {getIcon(fileTypeOrPath)} +
+) diff --git a/src/components/generic-menu.ts b/src/components/generic-menu.ts deleted file mode 100644 index 33aeed99..00000000 --- a/src/components/generic-menu.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Plugin } from '../components/plugin-container' -import { RowNormal } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import { CreateTask } from '../support/utils' -import Input from '../components/text-input' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import { Component } from 'hyperapp' - -export interface MenuOption { - key: any - value: string -} - -interface Props { - description: string - options: MenuOption[] - icon?: Component -} - -const state = { - visible: false, - value: '', - options: [] as MenuOption[], - cache: [] as MenuOption[], - description: '', - ix: 0, - icon: Icon.User, - task: CreateTask(), -} - -type S = typeof state - -const resetState = { value: '', visible: false, ix: 0 } - -const actions = { - select: () => (s: S) => { - vimFocus() - if (!s.options.length) return resetState - s.task.done((s.options[s.ix] || {}).key) - return resetState - }, - - // TODO: not hardcoded 14 - change: (value: string) => (s: S) => ({ - value, - ix: 0, - options: value - ? filter(s.cache, value, { key: 'value' }).slice(0, 14) - : s.cache.slice(0, 14), - }), - - show: ({ options, description, icon, task }: any) => ( - vimBlur(), - { - description, - options, - task, - icon, - cache: options, - visible: true, - } - ), - - hide: () => (vimFocus(), resetState), - next: () => (s: S) => ({ - ix: s.ix + 1 > Math.min(s.options.length - 1, 13) ? 0 : s.ix + 1, - }), - prev: () => (s: S) => ({ - ix: s.ix - 1 < 0 ? Math.min(s.options.length - 1, 13) : s.ix - 1, - }), -} - -const view = ($: S, a: typeof actions) => - Plugin($.visible, [ - , - Input({ - select: a.select, - change: a.change, - hide: a.hide, - next: a.next, - prev: a.prev, - value: $.value, - desc: $.description, - focus: true, - icon: $.icon, - }), - - h( - 'div', - $.options.map(({ key, value }, id) => - h( - RowNormal, - { - key, - active: id === $.ix, - }, - [, h('span', value)] - ) - ) - ), - ]) - -const ui = app({ name: 'generic-menu', state, actions, view }) - -export default (props: Props) => { - const task = CreateTask() - ui.show({ ...props, task }) - return task.promise -} diff --git a/src/components/generic-prompt.ts b/src/components/generic-prompt.ts deleted file mode 100644 index 20e68cab..00000000 --- a/src/components/generic-prompt.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Plugin } from '../components/plugin-container' -import { app, vimBlur, vimFocus } from '../ui/uikit' -import { CreateTask } from '../support/utils' -import Input from '../components/text-input' -import * as Icon from 'hyperapp-feather' - -const state = { - value: '', - desc: '', - visible: false, - task: CreateTask(), -} - -type S = typeof state - -const resetState = { value: '', visible: false, desc: '' } - -const actions = { - show: ({ desc, task }: any) => ( - vimBlur(), - { - desc, - task, - value: '', - visible: true, - } - ), - hide: () => (vimFocus(), resetState), - change: (value: string) => ({ value }), - select: () => (s: S) => { - s.value && s.task.done(s.value) - vimFocus() - return resetState - }, -} - -type A = typeof actions - -const view = ($: S, a: A) => - Plugin($.visible, [ - , - Input({ - focus: true, - icon: Icon.HelpCircle, - hide: a.hide, - select: a.select, - change: a.change, - value: $.value, - desc: $.desc, - }), - ]) - -const ui = app({ name: 'generic-prompt', state, actions, view }) - -export default (question: string) => { - const task = CreateTask() - ui.show({ task, desc: question }) - return task.promise -} diff --git a/src/components/grep.ts b/src/components/grep.ts deleted file mode 100644 index 1fa14fa1..00000000 --- a/src/components/grep.ts +++ /dev/null @@ -1,356 +0,0 @@ -import { RowNormal, RowHeader } from '../components/row-container' -import { PluginRight } from '../components/plugin-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import { showCursorline } from '../core/cursor' -import Input from '../components/text-input' -import { badgeStyle } from '../ui/styles' -import Worker from '../messaging/worker' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' - -type TextTransformer = (text: string, last?: boolean) => string -type Result = [string, SearchResult[]] - -enum FocusedElement { - Search, - Filter, -} - -interface SearchResult { - line: number - column: number - text: string -} - -let elref: HTMLElement -const SCROLL_AMOUNT = 0.25 -const worker = Worker('search-files') -const els = new Map() - -const state = { - value: '', - filterVal: '', - cwd: '', - results: [] as Result[], - visible: false, - ix: 0, - subix: -1, - loading: false, - focused: FocusedElement.Search, -} - -type S = typeof state - -// scroll after next section has been rendered as expanded (a little hacky) -const scrollIntoView = (next: number) => - setTimeout(() => { - const { - top: containerTop, - bottom: containerBottom, - } = elref.getBoundingClientRect() - const e = els.get(next) - if (!e) return - - const { top, height } = e.getBoundingClientRect() - - if (top + height > containerBottom) { - const offset = top - containerBottom - - if (offset < containerTop) elref.scrollTop += top - containerTop - else elref.scrollTop += offset + height + containerTop + 50 - } else if (top < containerTop) elref.scrollTop += top - containerTop - }, 1) - -const selectResult = (results: Result[], ix: number, subix: number) => { - if (subix < 0) return - const [path, items] = results[ix] - const { line, column } = items[subix] - api.nvim.jumpTo({ path, line, column }) - showCursorline() -} - -const highlightPattern = ( - text: string, - pattern: string, - { - normal, - special, - }: { - normal: TextTransformer - special: TextTransformer - } -) => { - const stext = special(pattern) - return text - .trimLeft() - .split(pattern) - .reduce((grp, part, ix, arr) => { - if (!part && ix) return grp.push(stext), grp - if (!part) return grp - const last = ix === arr.length - 1 - ix ? grp.push(stext, normal(part, last)) : grp.push(normal(part, last)) - return grp - }, [] as string[]) -} - -const resetState = { visible: false, loading: false } - -const actions = { - focusSearch: () => ({ focused: FocusedElement.Search }), - focusFilter: () => ({ focused: FocusedElement.Filter }), - - hide: () => (vimFocus(), resetState), - show: ({ cwd, value, reset = true }: any) => - reset - ? (vimBlur(), - { - visible: true, - cwd, - value, - ix: 0, - subix: -1, - results: [], - loading: !!value, - }) - : (vimBlur(), { visible: true }), - - select: () => (s: S) => { - vimFocus() - if (!s.results.length) return resetState - selectResult(s.results, s.ix, s.subix) - return resetState - }, - - change: (value: string) => (s: S) => { - value && worker.call.query({ query: value, cwd: s.cwd }) - return value - ? { - value, - loading: true, - } - : { - value, - results: [], - ix: 0, - subix: 0, - loading: false, - } - }, - - changeFilter: (filterVal: string) => { - worker.call.filter(filterVal) - return { filterVal } - }, - - results: (results: Result[]) => ({ results }), - - moreResults: (results: Result[]) => (s: S) => { - const merged = [...s.results, ...results] - const deduped = merged.filter( - (m, ix, arr) => arr.findIndex((e) => e[0] === m[0]) === ix - ) - return { results: deduped } - }, - - nextGroup: () => (s: S) => { - const next = s.ix + 1 > s.results.length - 1 ? 0 : s.ix + 1 - scrollIntoView(next) - return { subix: -1, ix: next } - }, - - prevGroup: () => (s: S) => { - const next = s.ix - 1 < 0 ? s.results.length - 1 : s.ix - 1 - scrollIntoView(next) - return { subix: -1, ix: next } - }, - - next: () => (s: S) => { - const next = s.subix + 1 < s.results[s.ix][1].length ? s.subix + 1 : 0 - selectResult(s.results, s.ix, next) - return { subix: next } - }, - - prev: () => (s: S) => { - const prev = s.subix - 1 < 0 ? s.results[s.ix][1].length - 1 : s.subix - 1 - selectResult(s.results, s.ix, prev) - return { subix: prev } - }, - - down: () => { - const { height } = elref.getBoundingClientRect() - const maxScroll = elref.scrollHeight - height - // TODO: should wait until get results back before calling loadNext again... - if (elref.scrollTop === maxScroll) return worker.call.loadNext() - elref.scrollTop += Math.floor(height * SCROLL_AMOUNT) - }, - - up: () => { - const { height } = elref.getBoundingClientRect() - elref.scrollTop -= Math.floor(height * SCROLL_AMOUNT) - }, - - loadingDone: ({ empty }: any) => (s: S) => ({ - loading: false, - results: empty ? [] : s.results, - }), -} - -const view = ($: S, a: typeof actions) => - PluginRight($.visible, [ - , - Input({ - value: $.value, - change: a.change, - hide: a.hide, - tab: a.focusFilter, - select: a.select, - nextGroup: a.nextGroup, - prevGroup: a.prevGroup, - next: a.next, - prev: a.prev, - down: a.down, - up: a.up, - focus: $.focused === FocusedElement.Search, - icon: Icon.Search, - desc: 'find in project', - loading: $.loading, - }), - - , - Input({ - value: $.filterVal, - change: a.changeFilter, - hide: a.hide, - tab: a.focusSearch, - select: a.select, - nextGroup: a.nextGroup, - prevGroup: a.prevGroup, - next: a.next, - prev: a.prev, - down: a.down, - up: a.up, - focus: $.focused === FocusedElement.Filter, - icon: Icon.Filter, - small: true, - desc: 'filter files', - }), - - , - h( - 'div', - { - oncreate: (e: HTMLElement) => (elref = e), - style: { - maxHeight: '100%', - overflowY: 'hidden', - }, - }, - $.results.map(([path, items], pos) => - h( - 'div', - { - oncreate: (e: HTMLElement) => els.set(pos, e), - }, - [ - , - h( - RowHeader, - { - active: pos === $.ix, - }, - [ - , - h('span', path), - , - h( - 'div', - { - style: { - ...badgeStyle, - marginLeft: '12px', - }, - }, - [, h('span', items.length)] - ), - ] - ), - - pos === $.ix && - h( - 'div', - items.map((f, itemPos) => - h( - RowNormal, - { - active: pos === $.ix && itemPos === $.subix, - style: { - fontFamily: 'var(--font)', - fontSize: 'var(--font-size)px', - }, - }, - highlightPattern(f.text, $.value, { - normal: (text, last) => - h( - 'span', - { - style: { - whiteSpace: 'pre', - textOverflow: last ? 'ellipsis' : undefined, - overflow: last ? 'inherit' : undefined, - }, - }, - text - ), - - special: (text) => - h( - 'span', - { - style: { - color: '#aaa', - background: 'rgba(255, 255, 255, 0.1)', - }, - }, - text - ), - }) - ) - ) - ), - ] - ) - ) - ), - ]) - -const ui = app({ name: 'grep', state, actions, view }) - -worker.on.results((results: Result[]) => ui.results(results)) -worker.on.moreResults((results: Result[]) => ui.moreResults(results)) -worker.on.done(ui.loadingDone) - -api.onAction('grep-resume', () => ui.show({ reset: false })) - -api.onAction('grep', async (query: string) => { - const { cwd } = api.nvim.state - ui.show({ cwd }) - query && worker.call.query({ query, cwd }) -}) - -api.onAction('grep-word', async () => { - const { cwd } = api.nvim.state - const query = await api.nvim.call.expand('') - ui.show({ cwd, value: query }) - worker.call.query({ query, cwd }) -}) - -// TODO: rename to grep-visual to be consistent with other actions -// operating from visual mode -api.onAction('grep-selection', async () => { - await api.nvim.feedkeys('gv"zy') - const selection = await api.nvim.expr('@z') - const [query] = selection.split('\n') - const { cwd } = api.nvim.state - ui.show({ cwd, value: query }) - worker.call.query({ query, cwd }) -}) diff --git a/src/components/hint.ts b/src/components/hint.ts deleted file mode 100644 index bf9d6a92..00000000 --- a/src/components/hint.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { docStyle, resetMarkdownHTMLStyle } from '../ui/styles' -import * as windows from '../windows/window-manager' -import Overlay from '../components/overlay' -import { h, app } from '../ui/uikit' -import { cvar } from '../ui/css' -import api from '../core/instance-api' -import { parse as stringToMarkdown } from 'marked' - -interface ShowParams { - row: number - col: number - label: string - activeParam: string | [number, number] - documentation?: string - paramDoc?: string - totalSignatures: number - selectedSignature: number -} - -const fadedStyle = { - color: cvar('foreground'), - filter: 'opacity(60%)', -} - -const strongStyle = { - color: cvar('foreground'), - fontWeight: 'bold', -} - -const docs = (data: string) => - h('div', { - style: { - ...docStyle, - // RowNormal gives us display: flex but this causes things - // to be flex-flow: row. we just want the standard no fancy pls kthx - display: 'block', - }, - oncreate: (e: HTMLElement) => - (e.innerHTML = `
${stringToMarkdown( - data - )}
`), - }) - -const sliceAndDiceLabel = ( - label: string, - activeParam: string | [number, number] -) => { - let x, labelStart, labelEnd - - if (typeof activeParam === 'string') { - const paramStart = label.indexOf(activeParam) - labelStart = label.slice(0, paramStart) - x = label.slice(paramStart, paramStart + activeParam.length) - labelEnd = label.slice(paramStart + activeParam.length) - } else { - labelStart = label.slice(0, activeParam[0]) - x = label.slice(activeParam[0], activeParam[1]) - labelEnd = label.slice(activeParam[1]) - } - - return { labelStart, labelEnd, activeParam: x } -} - -const fresh = ({ - row, - col, - documentation, - selectedSignature, - totalSignatures, -}: any) => ({ - row, - col, - documentation, - selectedSignature, - totalSignatures, -}) - -const state = { - label: '', - labelStart: '', - labelEnd: '', - activeParam: '', - documentation: '', - paramDoc: '', - anchorBottom: true, - totalSignatures: 0, - selectedSignature: 0, - visible: false, - row: 0, - col: 0, -} - -type S = typeof state - -const actions = { - hide: () => ({ visible: false, label: '', row: 0 }), - show: ({ - row, - col, - label, - activeParam: x, - documentation, - paramDoc, - selectedSignature, - totalSignatures, - }: ShowParams) => (s: S) => { - const { labelStart, labelEnd, activeParam } = sliceAndDiceLabel(label, x) - const same = s.label === label && s.row === row - const stuff = same - ? {} - : fresh({ row, col, documentation, selectedSignature, totalSignatures }) - - return { - ...stuff, - label, - labelStart, - labelEnd, - paramDoc, - anchorBottom: row > 2, - activeParam: activeParam, - visible: true, - } - }, -} - -type A = typeof actions - -const view = ($: S) => - Overlay( - { - ...windows.pixelPosition($.row > 2 ? $.row : $.row + 1, $.col - 1), - zIndex: 200, - maxWidth: 600, - visible: $.visible, - anchorAbove: $.anchorBottom, - }, - [ - , - h( - 'div', - { - style: { - background: cvar('background-30'), - }, - }, - [ - , - h( - 'div', - { - style: { - background: cvar('background-45'), - paddingBottom: - $.documentation || $.paramDoc ? '2px' : undefined, - }, - }, - [ - , - $.documentation && docs($.documentation), - $.paramDoc && docs($.paramDoc), - ] - ), - - h( - 'div', - { - style: { - display: 'flex', - padding: '8px', - fontFamily: 'var(--font)', - fontSize: 'var(--font-size)px', - }, - }, - [ - , - h('div', [ - , - h('span', { style: fadedStyle }, [h('span', $.labelStart)]), - h('span', { style: strongStyle }, [h('span', $.activeParam)]), - h('span', { style: fadedStyle }, [h('span', $.labelEnd)]), - ]), - - h( - 'div', - { - render: $.totalSignatures > 1, - style: { - paddingLeft: '4px', - color: cvar('foreground'), - }, - }, - `${$.selectedSignature}/${$.totalSignatures}` - ), - ] - ), - ] - ), - ] - ) - -const ui = app({ name: 'hint', state, actions, view }) - -// See runtime/lua/uivonim.lua -api.onAction('signature-help', (_, showParams) => { - ui.show(showParams) -}) - -api.onAction('signature-help-close', () => ui.hide()) diff --git a/src/components/hover.ts b/src/components/hover.ts deleted file mode 100644 index 981a5ab6..00000000 --- a/src/components/hover.ts +++ /dev/null @@ -1,106 +0,0 @@ -import * as windows from '../windows/window-manager' -import { ColorData } from '../services/colorizer' -import { sub } from '../messaging/dispatch' -import { debounce } from '../support/utils' -import Overlay from '../components/overlay' -import { docStyle } from '../ui/styles' -import { cursor } from '../core/cursor' -import { h, app } from '../ui/uikit' -import { parse as stringToMarkdown, setOptions } from 'marked' -import api from '../core/instance-api' -import { cell, size as workspaceSize } from '../core/workspace' - -setOptions({ - highlight: (code, lang, _) => { - const hljs = require('highlight.js/lib/core') - hljs.registerLanguage(lang, require(`highlight.js/lib/languages/${lang}`)) - - const highlightedCode = hljs.highlight(lang, code).value - return highlightedCode - }, -}) - -interface ShowParams { - hoverHeight: number - maxWidth: number - data: ColorData[][] - doc?: string -} - -// TODO(smolck): Should sanitize this HTML probably because safety. -const docs = (data: string) => - h('div', { - style: docStyle, - oncreate: (e: HTMLElement) => - (e.innerHTML = `
${stringToMarkdown(data)}
`), - onupdate: (e: HTMLElement, _: any) => - (e.innerHTML = `
${stringToMarkdown(data)}
`), - }) - -const getPosition = (row: number, col: number, heightOfHover: number) => - heightOfHover > row - ? { ...windows.pixelPosition(row + 1, col), anchorBottom: false } - : { ...windows.pixelPosition(row, col), anchorBottom: true } - -const state = { - value: [[]] as ColorData[][], - visible: false, - anchorBottom: true, - hoverHeight: 2, - maxWidth: 400, // TODO(smolck): Sane default? Is this even necessary? - doc: '', - x: 0, - y: 0, -} - -type S = typeof state - -const actions = { - hide: () => ({ visible: false }), - show: ({ data, doc, hoverHeight, maxWidth }: ShowParams) => ({ - doc, - hoverHeight, - maxWidth, - value: data, - visible: true, - ...getPosition(cursor.row, cursor.col, hoverHeight), - }), - updatePosition: () => (s: S) => - s.visible ? getPosition(cursor.row, cursor.col, s.hoverHeight) : undefined, -} - -type A = typeof actions - -const view = ($: S) => - Overlay( - { - x: $.x, - y: $.y, - maxWidth: Math.max(0, Math.min($.maxWidth, workspaceSize.width)), - visible: $.visible, - anchorAbove: $.anchorBottom, - }, - [ - $.doc && !$.anchorBottom && docs($.doc), - $.doc && $.anchorBottom && docs($.doc), - ] - ) - -const ui = app({ name: 'hover', state, actions, view }) - -api.onAction('hover', (_, markdownLines) => { - const doc = markdownLines.join('\n') - - const maxWidth = - cell.width * - (markdownLines.reduce( - (acc, item) => (item.length > acc ? item.length : acc), - markdownLines[0].length - ) + - 2) // Add 2 to prevent wrapping unless necessary. - ui.show({ data: [[]], doc, maxWidth, hoverHeight: markdownLines.length }) -}) - -api.onAction('hover-close', () => ui.hide()) - -sub('redraw', debounce(ui.updatePosition, 50)) diff --git a/src/components/icon.tsx b/src/components/icon.tsx new file mode 100644 index 00000000..cd2ef017 --- /dev/null +++ b/src/components/icon.tsx @@ -0,0 +1,8 @@ +type Props = { + iconHtml: string + style?: any +} + +export default ({ iconHtml, style }: Props) => ( +
+) diff --git a/src/components/loading.ts b/src/components/loading.ts deleted file mode 100644 index 4bd9c115..00000000 --- a/src/components/loading.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as workspace from '../core/workspace' -import { Loader } from 'hyperapp-feather' -import { h } from '../ui/uikit' - -interface LoaderParams { - size?: number - color?: string -} - -export default ( - { color, size = workspace.font.size + 2 } = {} as LoaderParams -) => - h( - 'div', - { - style: { - color: color || 'rgba(255, 255, 255, 0.3)', - animation: 'spin 2.5s linear infinite', - height: `${size}px`, - width: `${size}px`, - }, - }, - [, h(Loader, { size })] - ) diff --git a/src/components/loading.tsx b/src/components/loading.tsx new file mode 100644 index 00000000..dc1cb28c --- /dev/null +++ b/src/components/loading.tsx @@ -0,0 +1,25 @@ +import * as workspace from '../core/workspace' +import Icon from './icon' + +interface LoaderParams { + size?: number + color?: string +} + +// [, h(Loader, { size })] + +const feather = require('feather-icons') +export default ( + { color, size = workspace.font.size + 2 } = {} as LoaderParams +) => ( +
+ +
+) diff --git a/src/components/memes/nc.tsx b/src/components/memes/nc.tsx new file mode 100644 index 00000000..e48884c5 --- /dev/null +++ b/src/components/memes/nc.tsx @@ -0,0 +1,45 @@ +import { stealInput } from '../../core/input' +import { render } from 'inferno' +import api from '../../core/instance-api' + +let state = { + visible: false, +} + +type S = typeof state + +const Nyancat = ({ visible }: S) => ( +
+) + +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +plugins?.appendChild(container) + +const show = () => ( + (state.visible = true), render(, container) +) +const hide = () => { + if (state.visible) { + state.visible = false + render(, container) + } +} + +api.onAction('nc', () => { + show() + const restoreInput = stealInput(() => { + restoreInput() + hide() + }) +}) diff --git a/src/components/message-history.ts b/src/components/message-history.ts deleted file mode 100644 index 4fd363b9..00000000 --- a/src/components/message-history.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { MessageKind, Message } from '../protocols/veonim' -import { RowNormal } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import Input from '../components/text-input' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import { colors } from '../ui/styles' - -const state = { - query: '', - messages: [] as Message[], - cache: [] as Message[], - vis: false, - ix: 0, -} - -type S = typeof state - -let elref: HTMLElement -const SCROLL_AMOUNT = 0.4 - -const iconStyle = { fontSize: '1.2rem' } - -const icons = new Map([ - [ - MessageKind.Error, - h(Icon.XCircle, { color: colors.error, style: iconStyle }), - ], - [ - MessageKind.Warning, - h(Icon.AlertTriangle, { color: colors.warning, style: iconStyle }), - ], - [ - MessageKind.Success, - h(Icon.CheckCircle, { color: colors.success, style: iconStyle }), - ], - [ - MessageKind.Info, - h(Icon.MessageCircle, { color: colors.info, style: iconStyle }), - ], - [ - MessageKind.Hidden, - h(Icon.MessageCircle, { color: colors.info, style: iconStyle }), - ], - [ - MessageKind.System, - h(Icon.AlertCircle, { color: colors.system, style: iconStyle }), - ], -]) - -const getIcon = (kind: MessageKind) => - icons.get(kind) || icons.get(MessageKind.Info) - -const actions = { - show: (messages: Message[]) => ( - vimBlur(), { messages, cache: messages, vis: true } - ), - hide: () => (vimFocus(), { vis: false, query: '', ix: 0 }), - - change: (query: string) => (s: S) => ({ - query, - ix: 0, - messages: query ? filter(s.messages, query, { key: 'message' }) : s.cache, - }), - - next: () => (s: S) => ({ ix: s.ix + 1 >= s.messages.length ? 0 : s.ix + 1 }), - prev: () => (s: S) => ({ - ix: s.ix - 1 < 0 ? s.messages.length - 1 : s.ix - 1, - }), - - down: () => { - const { height } = elref.getBoundingClientRect() - elref.scrollTop += Math.floor(height * SCROLL_AMOUNT) - }, - - up: () => { - const { height } = elref.getBoundingClientRect() - elref.scrollTop -= Math.floor(height * SCROLL_AMOUNT) - }, -} - -const view = ($: S, a: typeof actions) => - h( - 'div', - { - style: { - background: 'var(--background-45)', - color: '#eee', - display: $.vis ? 'flex' : 'none', - flexFlow: 'column', - position: 'absolute', - alignSelf: 'flex-end', - maxHeight: '85vh', - width: '100%', - }, - }, - [ - , - Input({ - next: a.next, - prev: a.prev, - up: a.up, - hide: a.hide, - down: a.down, - change: a.change, - value: $.query, - focus: true, - small: true, - icon: Icon.Filter, - desc: 'filter messages', - }), - - h( - 'div', - { - oncreate: (e: HTMLElement) => { - if (e) elref = e - }, - style: { overflowY: 'hidden' }, - }, - $.messages.map(({ kind, message }, pos) => - h( - RowNormal, - { - active: pos === $.ix, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - alignItems: 'center', - paddingRight: '10px', - }, - }, - [, getIcon(kind)] - ), - - h( - 'div', - { - style: { - display: 'flex', - alignItems: 'center', - color: (icons.get(kind) || icons.get(MessageKind.Info))! - .color, - }, - }, - message - ), - ] - ) - ) - ), - ] - ) - -const ui = app({ name: 'message-history', state, actions, view }) - -export const showMessageHistory = (messages: Message[]) => ui.show(messages) diff --git a/src/components/messages.ts b/src/components/messages.ts deleted file mode 100644 index 1a6b93ec..00000000 --- a/src/components/messages.ts +++ /dev/null @@ -1,416 +0,0 @@ -import { - MessageKind, - Message, - MessageReturn, - MessageStatusUpdate, -} from '../protocols/veonim' -import { uuid, CreateTask, arrReplace } from '../support/utils' -import { registerOneTimeUseShortcuts } from '../core/input' -import * as Icon from 'hyperapp-feather' -import { colors } from '../ui/styles' -import { h, app } from '../ui/uikit' -import { cvar } from '../ui/css' -export { MessageKind } from '../protocols/veonim' - -interface MessageAction { - label: string - shortcut: string - shortcutLabel: string -} - -interface IMessage { - id: string - kind: MessageKind - message: string - actions: MessageAction[] - onAction: (action: string) => void - stealsFocus: boolean - progress?: number - progressStatus?: string -} - -interface IMessageStatusUpdate extends MessageStatusUpdate { - id: string -} - -const state = { - messages: [] as IMessage[], -} - -type S = typeof state - -const renderIcons = new Map([ - [MessageKind.Error, Icon.XCircle], - [MessageKind.Warning, Icon.AlertTriangle], - [MessageKind.Success, Icon.CheckCircle], - [MessageKind.Info, Icon.MessageCircle], - [MessageKind.System, Icon.AlertCircle], - [MessageKind.Progress, Icon.Clock], -]) - -const getIcon = (kind: MessageKind) => renderIcons.get(kind)! - -const actions = { - showMessage: (message: IMessage) => (s: S) => ({ - messages: [message, ...s.messages], - }), - setMessageProgress: ({ id, percentage, status }: IMessageStatusUpdate) => ( - s: S - ) => { - const messages = arrReplace(s.messages, (m) => m.id, { - progress: percentage, - progressStatus: status, - }) - - if (!messages) - return console.error( - `can not update message progress because it does not exist ${id}` - ) - return { messages } - }, - appendMessage: (message: IMessage) => (s: S) => { - const [firstMessage, ...nextMessages] = s.messages - const firstNvimMessage = firstMessage ? firstMessage : null - if (!firstNvimMessage) { - message.actions = addDefaultDismissAction(message) - return { messages: [message, ...s.messages] } - } - - firstMessage.message += message.message - return { messages: [firstMessage, ...nextMessages] } - }, - removeMessage: (id: string) => (s: S) => ({ - messages: s.messages.filter((m) => m.id !== id), - }), - clearMessages: (clearFn?: (message: IMessage) => boolean) => (s: S) => ({ - messages: clearFn ? s.messages.filter((m) => clearFn(m)) : [], - }), -} - -type A = typeof actions - -const MessageView = ($: IMessage, last: boolean) => - h( - 'div', - { - style: { - display: 'flex', - marginTop: '4px', - padding: '16px 18px', - background: cvar('background-30'), - borderLeft: '4px solid', - borderColor: Reflect.get(colors, $.kind), - fontSize: '1.2rem', - }, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - paddingRight: '14px', - fontSize: '1.6rem', - color: Reflect.get(colors, $.kind), - }, - }, - [, h(getIcon($.kind))] - ), - - h( - 'div', - { - style: { - display: 'flex', - flexFlow: 'column', - width: '100%', - }, - }, - [ - , - h( - 'div', - { - style: { - color: cvar('foreground-10'), - }, - }, - $.message.split('\n').map((line) => h('div', line)) - ), - - $.kind === MessageKind.Progress && - h( - 'div', - { - style: { - marginTop: '20px', - display: 'flex', - }, - }, - [ - , - h('div', { - style: { - height: '5px', - background: highlightColorBrighter, - filter: 'brighten(90%)', - borderRadius: '2px', - width: `${$.progress || 1}%`, - transition: 'width 0.5s', - }, - }), - ] - ), - - $.progressStatus && - h( - 'div', - { - style: { - display: 'flex', - marginTop: '6px', - fontSize: '0.9rem', - }, - }, - [ - , - h( - 'div', - { - style: { - color: 'var(--foreground-40)', - }, - }, - $.progressStatus - ), - ] - ), - - last && - !!$.actions.length && - h( - 'div', - { - style: { - marginTop: '12px', - display: 'flex', - justifyContent: 'flex-end', - }, - }, - $.actions.map((a) => Action(a.label, a.shortcutLabel)) - ), - ] - ), - ] - ) - -// TODO: create a highlight color from vim colorscheme -// const highlightColor = 'rgb(87, 52, 121)' -const highlightColor = 'rgb(78, 56, 100)' -const highlightColorBrighter = 'rgb(129, 84, 174)' - -const Action = (label: string, shortcut: string) => - h( - 'div', - { - style: { - marginLeft: '10px', - }, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - }, - }, - [ - , - h( - 'div', - { - style: { - borderRadius: '2px', - borderTopRightRadius: 0, - borderBottomRightRadius: 0, - padding: '5px 10px', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - background: highlightColor, - color: cvar('foreground'), - border: 'none', - clipPath: - 'polygon(0 0, 100% 0, calc(100% - 12px) 100%, 0 100%)', - paddingRight: '20px', - marginRight: '-12px', - fontSize: '1rem', - }, - }, - label - ), - - h( - 'div', - { - style: { - clipPath: 'polygon(12px 0, 100% 0, 100% 100%, 0 100%)', - color: cvar('foreground-20'), - borderRadius: '2px', - borderTopLeftRadius: 0, - borderBottomLeftRadius: 0, - background: 'none', - padding: '5px 10px', - border: '1px solid', - borderColor: highlightColor, - display: 'flex', - borderLeft: 'none', - alignItems: 'center', - justifyContent: 'center', - fontSize: '0.86rem', - fontWeight: 'bold', - paddingLeft: '20px', - }, - }, - shortcut - ), - ] - ), - ] - ) - -const view = ($: S) => - h( - 'div', - { - style: { - display: 'flex', - height: '100%', - width: '100%', - alignItems: 'flex-end', - justifyContent: 'flex-end', - }, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - flexFlow: 'column', - maxWidth: '500px', - minWidth: '350px', - }, - }, - [ - , - void registerFirstMessageShortcuts($.messages[$.messages.length - 1]), - $.messages.map((m, ix) => - MessageView(m, ix === $.messages.length - 1) - ), - ] - ), - ] - ) - -// will there be more than 6 message actions? -const availableShortcuts = [ - { shortcutLabel: 'C S Y', shortcut: '' }, - { shortcutLabel: 'C S T', shortcut: '' }, - { shortcutLabel: 'C S U', shortcut: '' }, - { shortcutLabel: 'C S R', shortcut: '' }, - { shortcutLabel: 'C S E', shortcut: '' }, - { shortcutLabel: 'C S W', shortcut: '' }, -] - -const getShortcut = (index: number) => - availableShortcuts[index] || { - shortcutLabel: '???', - shortcut: '', - } - -const registerFirstMessageShortcuts = (message: IMessage) => { - if (!message || message.stealsFocus) return - - const shortcuts = message.actions.map((m) => m.shortcut) - registerOneTimeUseShortcuts(shortcuts, (shortcut) => { - const action = message.actions.find((m) => m.shortcut === shortcut) - if (action) message.onAction(action.label) - }) -} - -const ui = app({ name: 'messages', state, actions, view }) - -// generic close/dismiss message functionality - like the (x) button in the prompt -const addDefaultDismissAction = (msg: IMessage | Message) => - !msg.stealsFocus - ? [ - { - label: 'Dismiss', - shortcutLabel: 'C S N', - shortcut: '', - }, - ] - : [] - -const showMessage = (message: Message): MessageReturn => { - const id = uuid() - const task = CreateTask() - - const registeredActions = message.actions || [] - if (registeredActions.length > 6) - console.error('messages: more than 6 actions - not enough shortcuts!') - const definedActions = registeredActions.map((label, ix) => ({ - ...getShortcut(ix), - label, - })) - const actions = [...definedActions, ...addDefaultDismissAction(message)] - - if (message.progressCancellable) - actions.push({ - label: 'Cancel', - shortcutLabel: 'C S C', - shortcut: '', - }) - - const callback = (action: string) => { - ui.removeMessage(id) - task.done(action) - } - - ui.showMessage({ - ...message, - id, - actions, - onAction: callback, - progress: message.progress || 1, - stealsFocus: message.stealsFocus || false, - }) - - const setProgress = (update: MessageStatusUpdate) => - ui.setMessageProgress({ ...update, id }) - const remove = () => ui.removeMessage(id) - - return { remove, setProgress, promise: task.promise } -} - -export default { - show: (message: Message) => showMessage(message), - append: (message: Message) => { - const id = uuid() - ui.appendMessage({ - ...message, - id, - actions: [], - onAction: () => ui.removeMessage(id), - stealsFocus: message.stealsFocus || false, - }) - }, - clear: (matcher?: (message: IMessage) => boolean) => { - ui.clearMessages(matcher) - }, -} diff --git a/src/components/nc.ts b/src/components/nc.ts deleted file mode 100644 index 0cdbe3c9..00000000 --- a/src/components/nc.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { stealInput } from '../core/input' -import api from '../core/instance-api' -import { h, app } from '../ui/uikit' - -const state = { - visible: false, -} - -type S = typeof state - -const actions = { - show: () => ({ visible: true }), - hide: () => (s: S) => { - if (s.visible) return { visible: false } - }, -} - -const view = ($: S) => - h('div', { - style: { - background: `url('../assets/nc.gif')`, - display: $.visible ? 'block' : 'none', - backgroundRepeat: 'no-repeat', - backgroundSize: '75vw', - position: 'absolute', - height: '100%', - width: '100%', - }, - }) - -const ui = app({ name: 'nc', state, actions, view }) - -api.onAction('nc', () => { - ui.show() - const restoreInput = stealInput(() => { - restoreInput() - ui.hide() - }) -}) diff --git a/src/components/nvim/autocomplete.tsx b/src/components/nvim/autocomplete.tsx new file mode 100644 index 00000000..32450f70 --- /dev/null +++ b/src/components/nvim/autocomplete.tsx @@ -0,0 +1,345 @@ +import { RowNormal, RowComplete } from '../row-container' +import { resetMarkdownHTMLStyle } from '../../ui/styles' +import * as windows from '../../windows/window-manager' +import * as dispatch from '../../messaging/dispatch' +import * as workspace from '../../core/workspace' +import { PopupMenu } from '../../render/events' +import { paddingVH, cvar } from '../../ui/css' +import Overlay from '../overlay' +import { cursor } from '../../core/cursor' +import { parse as stringToMarkdown } from 'marked' +import { render } from 'inferno' +import Icon from '../icon' +const feather = require('feather-icons') + +export interface CompletionShow { + row: number + col: number + options: CompletionOption[] +} + +export interface CompletionOption { + /** Display text for the UI */ + text: string + /** Text that will be inserted in the buffer */ + insertText: string + /** An enum used to display a fancy icon and color in the completion menu UI */ + kind: CompletionItemKind + /** The entire CompletionItem object. Is used by the UI to get/show documentation. If this does not exist the program will query a completion item provider from a relevant extensions */ + raw?: CompletionItem +} + +// TODO(smolck): Should this be here or somewhere else? +export class CompletionItem { + label: string + kind: CompletionItemKind | undefined + // @ts-ignore + detail: string + // @ts-ignore + documentation: string | MarkdownString + // @ts-ignore + sortText: string + // @ts-ignore + filterText: string + // @ts-ignore + preselect: boolean + // @ts-ignore + insertText: string | SnippetString + keepWhitespace?: boolean + // @ts-ignore + range: Range + // @ts-ignore + commitCharacters: string[] + // @ts-ignore + textEdit: TextEdit + // @ts-ignore + additionalTextEdits: TextEdit[] + // @ts-ignore + + constructor(label: string, kind?: CompletionItemKind) { + this.label = label + this.kind = kind + } + + toJSON(): any { + return { + label: this.label, + kind: this.kind && CompletionItemKind[this.kind], + detail: this.detail, + documentation: this.documentation, + sortText: this.sortText, + filterText: this.filterText, + preselect: this.preselect, + insertText: this.insertText, + textEdit: this.textEdit, + } + } +} + +export enum CompletionItemKind { + Text = 0, + Method = 1, + Function = 2, + Constructor = 3, + Field = 4, + Variable = 5, + Class = 6, + Interface = 7, + Module = 8, + Property = 9, + Unit = 10, + Value = 11, + Enum = 12, + Keyword = 13, + Snippet = 14, + Color = 15, + File = 16, + Reference = 17, + Folder = 18, + EnumMember = 19, + Constant = 20, + Struct = 21, + Event = 22, + Operator = 23, + TypeParameter = 24, +} + +const MAX_VISIBLE_OPTIONS = 12 + +let state = { + x: 0, + y: 0, + ix: 0, + anchorAbove: false, + options: [] as CompletionOption[], + visible: false, + documentation: {} as any, + visibleOptions: MAX_VISIBLE_OPTIONS, +} + +type S = typeof state + +const icon = (name: string, color?: string) => { + return ( + + ) +} + +const icons = new Map([ + [CompletionItemKind.Text, icon('chevrons-right')], + [CompletionItemKind.Method, icon('box')], + [CompletionItemKind.Property, icon('disc', '#54c8ff')], + [CompletionItemKind.Function, icon('share-2', '#6da7ff')], + [CompletionItemKind.Constructor, icon('aperture', '#c9ff56')], + [CompletionItemKind.Field, icon('feather', '#9866ff')], + [CompletionItemKind.Variable, icon('database', '#ff70e4')], + [CompletionItemKind.Class, icon('compass', '#ffeb5b')], + [CompletionItemKind.Interface, icon('map', '#ffa354')], + [CompletionItemKind.Module, icon('grid', '#ff5f54')], + [CompletionItemKind.Unit, icon('cpu', '#ffadc5')], + [CompletionItemKind.Value, icon('bell', '#ffa4d0')], + [CompletionItemKind.Enum, icon('award', '#84ff54')], + [CompletionItemKind.Keyword, icon('navigation', '#ff0c53')], + [CompletionItemKind.Snippet, icon('paperclip', '#0c2dff')], + [CompletionItemKind.Color, icon('eye', '#54ffe5')], + [CompletionItemKind.File, icon('file', '#a5c3ff')], + [CompletionItemKind.Reference, icon('link', '#ffdca3')], + // TODO: we need some colors pls + [CompletionItemKind.Folder, icon('folder', '#ccc')], + [CompletionItemKind.EnumMember, icon('menu', '#ccc')], + [CompletionItemKind.Constant, icon('save', '#ccc')], + [CompletionItemKind.Struct, icon('layers', '#ccc')], + [CompletionItemKind.Event, icon('video', '#ccc')], + [CompletionItemKind.Operator, icon('anchor', '#ccc')], + [CompletionItemKind.TypeParameter, icon('type', '#ccc')], +]) + +const getCompletionIcon = (kind: CompletionItemKind) => + icons.get(kind) || icon('code') + +// TODO: move to common place. used in other places like signature-hint +const parseDocs = (docs?: string): string | undefined => { + if (!docs) return + return stringToMarkdown(docs) +} + +const docs = (data: string) => ( + // @ts-ignore TS wants children but there are none so ignore + ${data}
`} + active={false} + style={{ + ...paddingVH(6, 4), + // RowNormal gives us display: flex but this causes things + // to be flex-flow: row. we just want the standard no fancy pls kthx + display: 'block', + 'padding-top': '6px', + overflow: 'visible', + 'white-space': 'normal', + color: cvar('foreground-20'), + background: cvar('background-45'), + 'font-size': `${workspace.font.size - 2}px`, + }} + /> +) + +const Autocomplete = ({ + documentation, + x, + y, + visible, + visibleOptions, + ix, + anchorAbove, + options, +}: S) => ( + + {documentation && anchorAbove && docs(documentation)} +
+ {options.map(({ text, kind }, id) => ( + +
+ {getCompletionIcon(kind)} +
+
{text}
+
+ ))} +
+ {documentation && !anchorAbove && docs(documentation)} +
+) + +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +container.id = 'autocomplete-container' +plugins?.appendChild(container) + +export const hide = () => { + state.visible = false + state.ix = 0 + + render(, container) +} + +export const select = (index: number) => { + const completionItem = (state.options[index] || {}).raw + state.ix = index + + // raw could be missing if not semantic completions + if (!completionItem) { + state.documentation = undefined + render(, container) + return + } + + const { detail, documentation } = completionItem + // TODO: what are we doing with detail and documentation? + // show both? or one or the other? + + if (documentation) { + // TODO(smolck): Not sure why, but I get "32" as the doc sometimes, and so + // I just convert this to a string to make sure that doesn't break stuff. + // :shrug: + state.documentation = parseDocs(documentation.toString()) + render(, container) + } else { + // TODO(smolck): parseDocs(detail)? + state.documentation = detail + render(, container) + } +} +export const show = ({ row, col, options }: CompletionShow) => { + const visibleOptions = Math.min(MAX_VISIBLE_OPTIONS, options.length) + const anchorAbove = cursor.row + visibleOptions > workspace.size.rows + + // TODO(smolck): Feels too imperative + state.visibleOptions = visibleOptions + state.anchorAbove = anchorAbove + state.options = options + const { x, y } = windows.pixelPosition(anchorAbove ? row : row + 1, col) + state.x = x + state.y = y + state.options = options.slice(0, visibleOptions) + state.visible = true + state.documentation = undefined + // TODO(smolck) + // default + state.ix = -1 + + render(, container) +} + +dispatch.sub('pmenu.select', (ix) => select(ix)) +dispatch.sub('pmenu.hide', hide) +dispatch.sub('pmenu.show', ({ items, index, row, col }: PopupMenu) => { + const options = items.map( + (m) => + ({ + text: `${m.word} ${m.menu}`, + insertText: m.word, + kind: stringToKind(m.kind), + raw: { + documentation: m.info, + }, + } as CompletionOption) + ) + + show({ row, col, options }) + select(index) +}) + +// TODO(smolck): Support more kinds. +// Names and things taken from: +// https://github.com/vhakulinen/gnvim/blob/1afac027e15623affd3e5435b88e056e0394c2f8/src/nvim_bridge/mod.rs#L276 +const completionKindMappings = new Map([ + ['Variable', CompletionItemKind.Variable], + ['variable', CompletionItemKind.Variable], + ['V', CompletionItemKind.Variable], + + ['function', CompletionItemKind.Function], + ['Function', CompletionItemKind.Function], + + ['property', CompletionItemKind.Property], + ['Property', CompletionItemKind.Property], + ['method', CompletionItemKind.Property], + ['Method', CompletionItemKind.Property], + ['f', CompletionItemKind.Property], + + ['type paramter', CompletionItemKind.TypeParameter], + ['Type Parameter', CompletionItemKind.TypeParameter], + ['T', CompletionItemKind.TypeParameter], + + ['interface', CompletionItemKind.Interface], + ['I', CompletionItemKind.Interface], + ['Interface', CompletionItemKind.Interface], +]) + +const stringToKind = (kind: string): CompletionItemKind => { + return completionKindMappings.get(kind) || CompletionItemKind.Text +} diff --git a/src/components/nvim/command-line.tsx b/src/components/nvim/command-line.tsx new file mode 100644 index 00000000..e3ea72a7 --- /dev/null +++ b/src/components/nvim/command-line.tsx @@ -0,0 +1,135 @@ +import { + enableCursor, + disableCursor, + hideCursor, + showCursor, +} from '../../core/cursor' +import { CommandType, CommandUpdate } from '../../render/events' +import { Plugin } from '../plugin-container' +import { RowNormal } from '../row-container' +import Input from '../text-input' +import { sub } from '../../messaging/dispatch' +import { is } from '../../support/utils' +import { render } from 'inferno' +const feather = require('feather-icons') + +const modeSwitch = new Map([ + [CommandType.Ex, feather.icons.command.toSvg()], + [CommandType.Prompt, feather.icons['chevrons-right'].toSvg()], +]) + +let state = { + options: [] as string[], + visible: false, + value: '', + ix: 0, + position: 0, + prompt: '', + kind: CommandType.Ex, +} + +type S = typeof state + +const CommandLine = ({ + options, + position, + value, + prompt, + visible, + kind, + ix: stateIx, +}: S) => { + const maybePrompt = prompt && ( +
+
{prompt}
+
+ ) + + return ( + // @ts-ignore + + {maybePrompt} + +
+ {options.map((name, ix) => ( + +
{name}
+
+ ))} +
+
+ ) +} + +// TODO(smolck): Is this slow? Necessary? Done in other files as well, since +// otherwise Inferno overwrites the DOM and that causes issues. +const plugins = document.getElementById('plugins') +const container = document.createElement('div') +container.id = 'command-line-container' +plugins?.appendChild(container) + +// TODO: use export cns. this component is a high priority so it should be loaded early +// because someone might open cmdline early +sub('wildmenu.show', (opts: any[]) => { + state.options = [...new Set(opts)] + + render(, container) +}) +sub('wildmenu.select', (ix) => { + state.ix = ix + + render(, container) +}) + +sub('wildmenu.hide', () => { + ;(state.options = [...new Set([])]), + render(, container) +}) + +sub('cmd.hide', () => { + enableCursor() + showCursor() + + state.visible = false + + render(, container) +}) + +sub('cmd.update', ({ cmd, kind, position, prompt }: CommandUpdate) => { + hideCursor() + disableCursor() + + state.kind = kind + if (prompt) state.prompt = prompt + state.position = position + state.visible = true + state.options = cmd ? state.options : [] + state.value = is.string(cmd) && state.value !== cmd ? cmd : state.value + + render(, container) +}) diff --git a/src/components/nvim/message-history.tsx b/src/components/nvim/message-history.tsx new file mode 100644 index 00000000..aafffe6b --- /dev/null +++ b/src/components/nvim/message-history.tsx @@ -0,0 +1,167 @@ +import { MessageKind, Message } from '../../protocols/veonim' +import { RowNormal } from '../row-container' +import { vimBlur, vimFocus } from '../../ui/uikit' +import Input from '../text-input' +import { filter } from 'fuzzaldrin-plus' +import Icon from '../icon' +import { colors } from '../../ui/styles' +import { render } from 'inferno' + +let state = { + query: '', + messages: [] as Message[], + cache: [] as Message[], + vis: false, + ix: 0, + inputCallbacks: {}, +} + +type S = typeof state + +let elref: HTMLElement +const SCROLL_AMOUNT = 0.4 + +const iconStyle = { fontSize: '1.2rem' } + +const feather = require('feather-icons') +// TODO(smolck): equivalent to h(Icon.*, { color: colors.*, style: iconStyle })? +const createIcon = (name: string, color: string) => ({ + icon: ( + + ), + color: color, +}) + +const icons = new Map([ + [MessageKind.Error, createIcon('x-circle', colors.error)], + [MessageKind.Warning, createIcon('alert-triangle', colors.warning)], + [MessageKind.Success, createIcon('check-circle', colors.success)], + [MessageKind.Info, createIcon('message-circle', colors.info)], + [MessageKind.Hidden, createIcon('message-circle', colors.info)], + [MessageKind.System, createIcon('alert-circle', colors.system)], +]) + +const getIcon = (kind: MessageKind) => + icons.get(kind) || icons.get(MessageKind.Info) + +const WhyDiv = (props: any) =>
{props.children}
+ +const MessageHistory = ({ + vis: visible, + messages, + ix: index, + inputCallbacks, + query, +}: S) => ( +
+ + + (elref = e)} + style={{ overflow: 'hidden' }} + > + {messages.map(({ kind, message }, pos) => ( + +
+ {getIcon(kind)?.icon} +
+ +
+ {message} +
+
+ ))} +
+
+) + +const container = document.createElement('div') +container.id = 'message-history-container' +document.getElementById('plugins')?.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), + render(, container) +) + +const show = (messages: Message[]) => ( + vimBlur(), assignStateAndRender({ messages, cache: messages, vis: true }) +) + +const hide = () => ( + vimFocus(), assignStateAndRender({ vis: false, query: '', ix: 0 }) +) + +const next = () => + assignStateAndRender({ + ix: state.ix + 1 >= state.messages.length ? 0 : state.ix + 1, + }) + +const prev = () => + assignStateAndRender({ + ix: state.ix - 1 < 0 ? state.messages.length - 1 : state.ix - 1, + }) + +const down = () => { + const { height } = elref.getBoundingClientRect() + elref.scrollTop += Math.floor(height * SCROLL_AMOUNT) +} + +const up = () => { + const { height } = elref.getBoundingClientRect() + elref.scrollTop -= Math.floor(height * SCROLL_AMOUNT) +} + +const change = (query: string) => + assignStateAndRender({ + query, + ix: 0, + messages: query + ? filter(state.messages, query, { key: 'message' }) + : state.cache, + }) + +state.inputCallbacks = { + hide, + next, + prev, + down, + up, + change, +} + +export const showMessageHistory = (messages: Message[]) => show(messages) diff --git a/src/components/nvim/messages.tsx b/src/components/nvim/messages.tsx new file mode 100644 index 00000000..0ab5cd93 --- /dev/null +++ b/src/components/nvim/messages.tsx @@ -0,0 +1,367 @@ +import { + MessageKind, + Message, + MessageReturn, + MessageStatusUpdate, +} from '../../protocols/veonim' +import { uuid, CreateTask, arrReplace } from '../../support/utils' +import { registerOneTimeUseShortcuts } from '../../core/input' +import { colors } from '../../ui/styles' +import { cvar } from '../../ui/css' +import { render } from 'inferno' +import Icon from '../icon' + +export { MessageKind } from '../../protocols/veonim' + +interface MessageAction { + label: string + shortcut: string + shortcutLabel: string +} + +interface IMessage { + id: string + kind: MessageKind + message: string + actions: MessageAction[] + onAction: (action: string) => void + stealsFocus: boolean + progress?: number + progressStatus?: string +} + +interface IMessageStatusUpdate extends MessageStatusUpdate { + id: string +} + +let state = { + messages: [] as IMessage[], +} + +type S = typeof state + +const feather = require('feather-icons') +const createIcon = (name: string) => ( + +) +const renderIcons = new Map([ + [MessageKind.Error, createIcon('x-circle')], + [MessageKind.Warning, createIcon('alert-triangle')], + [MessageKind.Success, createIcon('check-circle')], + [MessageKind.Info, createIcon('message-circle')], + [MessageKind.System, createIcon('alert-circle')], + [MessageKind.Progress, createIcon('clock')], +]) + +const getIcon = (kind: MessageKind) => renderIcons.get(kind)! + +type ActionParams = { + label: string + shortcut: string +} +const Action = ({ label, shortcut }: ActionParams) => ( +
+
+
+ {label} +
+ +
+ {shortcut} +
+
+
+) + +const MessageView = ({ + progressStatus, + actions, + progress, + message, + kind, + isLast, +}: IMessage & { isLast: boolean }) => ( +
+
{getIcon(kind)}
+ +
+
+ {message.split('\n').map((line) => ( +
{line}
+ ))} +
+ + {kind === MessageKind.Progress && ( +
+
+
+ )} + + {progressStatus && ( +
+
{progressStatus}
+
+ )} + + {isLast && + // TODO(smolck): Why the double exclamation mark? + !!actions.length && ( +
+ {actions.map((a) => ( + + ))} +
+ )} +
+
+) + +// TODO: create a highlight color from vim colorscheme +// const highlightColor = 'rgb(87, 52, 121)' +const highlightColor = 'rgb(78, 56, 100)' +const highlightColorBrighter = 'rgb(129, 84, 174)' + +const Messages = ({ messages }: S) => ( +
+
+ {void registerFirstMessageShortcuts(messages[messages.length - 1])} + {messages.map((m, ix) => ( + + ))} +
+
+) + +// will there be more than 6 message actions? +const availableShortcuts = [ + { shortcutLabel: 'C S Y', shortcut: '' }, + { shortcutLabel: 'C S T', shortcut: '' }, + { shortcutLabel: 'C S U', shortcut: '' }, + { shortcutLabel: 'C S R', shortcut: '' }, + { shortcutLabel: 'C S E', shortcut: '' }, + { shortcutLabel: 'C S W', shortcut: '' }, +] + +const getShortcut = (index: number) => + availableShortcuts[index] || { + shortcutLabel: '???', + shortcut: '', + } + +const registerFirstMessageShortcuts = (message: IMessage) => { + if (!message || message.stealsFocus) return + + const shortcuts = message.actions.map((m) => m.shortcut) + registerOneTimeUseShortcuts(shortcuts, (shortcut) => { + const action = message.actions.find((m) => m.shortcut === shortcut) + if (action) message.onAction(action.label) + }) +} + +// generic close/dismiss message functionality - like the (x) button in the prompt +const addDefaultDismissAction = (msg: IMessage | Message) => + !msg.stealsFocus + ? [ + { + label: 'Dismiss', + shortcutLabel: 'C S N', + shortcut: '', + }, + ] + : [] + +const container = document.createElement('div') +container.id = 'messages-container' +document.getElementById('plugins')!.appendChild(container) +const assignStateAndRender = (newState: S) => ( + Object.assign(state, newState), render(, container) +) + +const uiShowMessage = (message: IMessage) => + assignStateAndRender({ messages: [message, ...state.messages] }) + +const setMessageProgress = ({ + id, + percentage, + status, +}: IMessageStatusUpdate) => { + const messages = arrReplace(state.messages, (m) => m.id, { + progress: percentage, + progressStatus: status, + }) + + if (!messages) + return console.error( + `can not update message progress because it does not exist ${id}` + ) + assignStateAndRender({ messages }) +} + +const appendMessage = (message: IMessage) => { + const [firstMessage, ...nextMessages] = state.messages + const firstNvimMessage = firstMessage ? firstMessage : null + if (!firstNvimMessage) { + message.actions = addDefaultDismissAction(message) + assignStateAndRender({ messages: [message, ...state.messages] }) + return + } + + firstMessage.message += message.message + assignStateAndRender({ messages: [firstMessage, ...nextMessages] }) +} + +const removeMessage = (id: string) => + assignStateAndRender({ + messages: state.messages.filter((m) => m.id !== id), + }) + +const clearMessages = (clearFn?: (message: IMessage) => boolean) => + assignStateAndRender({ + messages: clearFn ? state.messages.filter((m) => clearFn(m)) : [], + }) + +const showMessage = (message: Message): MessageReturn => { + const id = uuid() + const task = CreateTask() + + const registeredActions = message.actions || [] + if (registeredActions.length > 6) + console.error('messages: more than 6 actions - not enough shortcuts!') + const definedActions = registeredActions.map((label, ix) => ({ + ...getShortcut(ix), + label, + })) + const actions = [...definedActions, ...addDefaultDismissAction(message)] + + if (message.progressCancellable) + actions.push({ + label: 'Cancel', + shortcutLabel: 'C S C', + shortcut: '', + }) + + const callback = (action: string) => { + removeMessage(id) + task.done(action) + } + + uiShowMessage({ + ...message, + id, + actions, + onAction: callback, + progress: message.progress || 1, + stealsFocus: message.stealsFocus || false, + }) + + const setProgress = (update: MessageStatusUpdate) => + setMessageProgress({ ...update, id }) + const remove = () => removeMessage(id) + + return { remove, setProgress, promise: task.promise } +} + +export default { + show: (message: Message) => showMessage(message), + append: (message: Message) => { + const id = uuid() + appendMessage({ + ...message, + id, + actions: [], + onAction: () => removeMessage(id), + stealsFocus: message.stealsFocus || false, + }) + }, + clear: (matcher?: (message: IMessage) => boolean) => { + clearMessages(matcher) + }, +} diff --git a/src/components/nvim/search.tsx b/src/components/nvim/search.tsx new file mode 100644 index 00000000..52bc4ef7 --- /dev/null +++ b/src/components/nvim/search.tsx @@ -0,0 +1,105 @@ +import { + hideCursor, + showCursor, + disableCursor, + enableCursor, +} from '../../core/cursor' +import { CommandType, CommandUpdate } from '../../render/events' +import * as windows from '../../windows/window-manager' +import { WindowOverlay } from '../../windows/window' +import Input from '../text-input' +import { sub } from '../../messaging/dispatch' +import { rgba, paddingV } from '../../ui/css' +import { is } from '../../support/utils' +import { makel } from '../../ui/vanilla' +import { render } from 'inferno' + +let state = { + visible: false, + value: '', + position: 0, + kind: CommandType.Ex, + inputCallbacks: {}, +} + +type S = typeof state +let winOverlay: WindowOverlay + +const printCommandType = (kind: CommandType) => { + if (kind === CommandType.SearchForward) return 'forward search' + if (kind === CommandType.SearchBackward) return 'backward search' + // should never happen + else return 'search' +} + +const feather = require('feather-icons') +const VimSearch = ({ visible, kind, value, position }: S) => ( +
+
+ {printCommandType(kind)} +
+ + +
+) + +const container = makel({ + position: 'absolute', + width: '100%', + display: 'flex', + background: 'var(--background-30)', + visible: state.visible, +}) +container.id = 'vim-search-container' +// TODO(smolck): Shouldn't be necessary, right? +// document.getElementById('plugins')!.appendChild(container) + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const hide = () => { + enableCursor() + showCursor() + if (winOverlay) winOverlay.remove() + assignStateAndRender({ value: '', visible: false }) +} + +const updateQuery = ({ cmd, kind, position }: CommandUpdate) => { + const cmdKind = kind || state.kind + hideCursor() + disableCursor() + + !state.visible && + setImmediate(() => { + winOverlay = windows.getActive().addOverlayElement(container) + }) + + assignStateAndRender({ + position, + kind: cmdKind, + visible: true, + value: is.string(cmd) && state.value !== cmd ? cmd : state.value, + }) +} + +state.inputCallbacks = { hide, select: hide } + +sub('search.hide', hide) +sub('search.update', updateQuery) diff --git a/src/components/nvim/statusline.tsx b/src/components/nvim/statusline.tsx new file mode 100644 index 00000000..9c972c5b --- /dev/null +++ b/src/components/nvim/statusline.tsx @@ -0,0 +1,456 @@ +import { onSwitchVim, getCurrentName } from '../../core/instance-manager' +import { getColorByName } from '../../render/highlight-attributes' +import { sub, processAnyBuffered } from '../../messaging/dispatch' +import { darken, brighten, cvar } from '../../ui/css' +import { ExtContainer } from '../../neovim/protocol' +import Icon from '../icon' +import api from '../../core/instance-api' +import { colors } from '../../ui/styles' +import { basename } from 'path' +import { homedir } from 'os' +import { render } from 'inferno' + +interface Tab { + tab: ExtContainer + name: string +} + +interface TabInfo { + id: number + name: string +} + +interface TabView { + id: number + label: number + active: boolean +} + +let state = { + tabs: [] as TabInfo[], + active: -1, + filetype: '', + // TODO(smolck): No longer necessary? runningServers: new Set(), + message: '', + controlMessage: '', + line: 0, + column: 0, + cwd: '', + errors: 0, + warnings: 0, + branch: '', + additions: 0, + deletions: 0, + baseColor: '#4e415a', +} + +type S = typeof state + +const statusGroupStyle: CSSProperties = { + display: 'flex', + 'flex-direction': 'row', + 'align-items': 'center', +} + +const itemStyle = { + color: cvar('foreground-40'), + display: 'flex', + height: '100%', + 'align-items': 'center', + 'padding-left': '20px', + 'padding-right': '20px', +} + +const iconBoxStyle: CSSProperties = { + display: 'flex', + 'padding-right': '4px', + 'align-items': 'center', +} + +const container = document.getElementById('statusline') as HTMLElement + +Object.assign(container.style, { + height: '24px', + display: 'flex', + 'z-index': 900, +}) + +const feather = require('feather-icons') +const Statusline = ({ + baseColor, + cwd, + branch, + additions, + deletions, + message, + controlMessage, + errors, + warnings, + line, + column, + tabs, + active, +}: S) => { + const additionsIcon = ( +
0 ? colors.success : undefined, + }} + > + +
+ ) + + const additionsText = ( +
0 ? colors.success : undefined, + 'padding-bottom': '1px', + }} + > + {additions} +
+ ) + + const deletionsIcon = ( +
0 ? colors.error : undefined, + 'margin-left': '12px', + }} + > + +
+ ) + + const deletionsText = ( +
0 ? colors.error : undefined, + 'padding-bottom': '1px', + }} + > + {deletions} +
+ ) + + const left = ( +
+
+
+ +
+ +
+ + {branch && ( +
+
+ +
+ +
+ )} + + {branch && ( +
+ {additionsIcon} + {additionsText} + + {deletionsIcon} + {deletionsText} +
+ )} + +
+
+ {message} +
+
+
+ ) + + const errorsIcon = ( +
0 ? colors.error : undefined, + }} + > + +
+ ) + + const errorsText = ( +
0 ? colors.error : undefined, + }} + > + {errors} +
+ ) + + const warningsIcon = ( +
0 ? colors.warning : undefined, + 'margin-left': '12px', + }} + > + +
+ ) + + const warningsText = ( +
0 ? colors.warning : undefined, + 'padding-bottom': '1px', + }} + > + {warnings} +
+ ) + + const right = ( +
+
+
+ {controlMessage} +
+
+ +
+ {errorsIcon} + {errorsText} + + {warningsIcon} + {warningsText} +
+ +
+
+ {line + 1}:{column + 1} +
+
+ +
+ {tabs.map(({ id }, ix) => ( + + ))} +
+
+ ) + + return ( +
+ {left} + {right} +
+ ) +} + +const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, container) +) + +const iconStyle = { 'font-size': '16px' } + +const Label = ({ label }: { label: string }) => ( +
{label}
+) + +const Tab = ({ id, label, active }: TabView) => ( +
+ {label} +
+) + +api.nvim.watchState.filetype((filetype) => assignStateAndRender({ filetype })) +api.nvim.watchState.line((line) => assignStateAndRender({ line })) +api.nvim.watchState.column((column) => assignStateAndRender({ column })) +api.nvim.watchState.cwd((cwd: string) => { + const next = homedir() === cwd ? getCurrentName() : basename(cwd) + assignStateAndRender({ cwd: next }) +}) + +sub('tabs', async ({ curtab, tabs }: { curtab: ExtContainer; tabs: Tab[] }) => { + const mtabs: TabInfo[] = tabs.map((t) => ({ id: t.tab.id, name: t.name })) + mtabs.length > 1 + ? assignStateAndRender({ active: curtab.id, tabs: mtabs }) + : assignStateAndRender({ active: -1, tabs: [] }) +}) + +api.git.onBranch((branch) => assignStateAndRender({ branch })) +api.git.onStatus((status) => + assignStateAndRender({ + additions: status.additions, + deletions: status.deletions, + }) +) +// sub('ai.diagnostics.count', (count) => ui.setDiagnostics(count)) +// sub('ai.start', (opts) => ui.aiStart(opts)) +sub('message.status', (msg) => assignStateAndRender({ message: msg })) +sub('message.control', (msg) => assignStateAndRender({ controlMessage: msg })) +onSwitchVim(() => assignStateAndRender({ active: -1, tabs: [] })) + +api.nvim.watchState.colorscheme(async () => { + const { background } = await getColorByName('StatusLine') + if (background) assignStateAndRender({ baseColor: background }) +}) + +setImmediate(async () => { + processAnyBuffered('tabs') + const { background } = await getColorByName('StatusLine') + if (background) assignStateAndRender({ baseColor: background }) +}) diff --git a/src/components/overlay.ts b/src/components/overlay.ts deleted file mode 100644 index e652812f..00000000 --- a/src/components/overlay.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { h } from '../ui/uikit' - -interface Props { - visible: boolean - x: number - y: number - maxWidth?: number - anchorAbove: boolean - zIndex?: number - onElement?: (element: HTMLElement) => void -} - -export default ($: Props, content: any[]) => - h( - 'div', - { - style: { - zIndex: $.zIndex, - display: $.visible ? 'flex' : 'none', - height: '100%', - width: '100%', - flexFlow: $.anchorAbove ? 'column-reverse' : 'column', - position: 'absolute', - }, - oncreate: $.onElement, - }, - [ - , - h('.spacer', { - style: { - height: $.anchorAbove ? `calc(100% - ${$.y}px)` : `${$.y}px`, - }, - }), - - h( - 'div', - { - style: { - display: 'flex', - flexFlow: 'row nowrap', - }, - }, - [ - , - h('.col', { - style: { - width: `${$.x}px`, - }, - }), - - h( - 'div', - { - style: { - flexShrink: '0', - maxWidth: $.maxWidth && `${$.maxWidth}px`, - }, - }, - content - ), - ] - ), - ] - ) diff --git a/src/components/overlay.tsx b/src/components/overlay.tsx new file mode 100644 index 00000000..a25f19ed --- /dev/null +++ b/src/components/overlay.tsx @@ -0,0 +1,40 @@ +interface Props { + visible: boolean + x: number + y: number + maxWidth?: number + anchorAbove: boolean + zIndex?: number + children?: any + id?: string +} + +export default ($: Props) => ( +
+
+
+
+
+ {$.children} +
+
+
+) diff --git a/src/components/plugin-container.ts b/src/components/plugin-container.ts deleted file mode 100644 index e35fb003..00000000 --- a/src/components/plugin-container.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { is } from '../support/utils' -import { h } from '../ui/uikit' - -type PluginFnNormal = (visible: boolean, children: any[]) => any -type PluginFnWithStyles = ( - visible: boolean, - styles: object, - children: any[] -) => any -type PluginFn = PluginFnNormal & PluginFnWithStyles - -const base = { - zIndex: 99, - display: 'flex', - width: '100%', - height: '100%', - justifyContent: 'center', -} - -const normal = { ...base, alignItems: 'flex-start' } -const top = { ...base, alignItems: 'flex-start' } -const bottom = { ...base, alignItems: 'flex-end' } -const right = { ...base, alignItems: 'stretch', justifyContent: 'flex-end' } - -const dialog = { - background: 'var(--background-30)', - marginTop: '15%', - flexFlow: 'column', -} - -export const Plugin = (visible: boolean, ...args: any[]) => - h( - 'div', - { - style: normal, - }, - [ - , - h( - 'div', - { - style: { - ...dialog, - width: '600px', - display: visible ? 'flex' : 'none', - ...args.find(is.object), - }, - }, - args.find(is.array) - ), - ] - ) - -export const PluginTop: PluginFn = (visible: boolean, ...args: any[]) => - h( - 'div', - { - style: top, - }, - [ - , - h( - 'div', - { - style: { - ...dialog, - width: '400px', - display: visible ? 'flex' : 'none', - ...args.find(is.object), - }, - }, - args.find(is.array) - ), - ] - ) - -export const PluginBottom: PluginFn = (visible: boolean, ...args: any[]) => - h( - 'div', - { - style: bottom, - }, - [ - , - h( - 'div', - { - style: { - width: '100%', - height: '100%', - flexFlow: 'column', - background: 'var(--background-40)', - display: visible ? 'flex' : 'none', - ...args.find(is.object), - }, - }, - args.find(is.array) - ), - ] - ) - -export const PluginRight = (visible: boolean, ...args: any[]) => - h( - 'div', - { - style: right, - }, - [ - , - h( - 'div', - { - style: { - ...dialog, - width: '500px', - height: '100%', - flexFlow: 'column', - marginTop: 0, - background: 'var(--background-40)', - display: visible ? 'flex' : 'none', - ...args.find(is.object), - }, - }, - args.find(is.array) - ), - ] - ) diff --git a/src/components/plugin-container.tsx b/src/components/plugin-container.tsx new file mode 100644 index 00000000..3de210d0 --- /dev/null +++ b/src/components/plugin-container.tsx @@ -0,0 +1,121 @@ +// TODO(smolck): Should this be used? Is it pointless now? +// type PluginFnNormal = (visible: boolean, children: any[]) => any +// type PluginFnWithStyles = ( +// visible: boolean, +// styles: object, +// children: any[] +// ) => any +// type PluginFn = PluginFnNormal & PluginFnWithStyles + +const base = { + 'z-index': 99, + 'justify-content': 'center', + display: 'flex', + width: '100%', + height: '100%', +} + +const normal = { ...base, 'align-items': 'flex-start' } +const top = { ...base, 'align-items': 'flex-start' } +const bottom = { ...base, 'align-items': 'flex-end' } +const right = { + ...base, + 'align-items': 'stretch', + 'justify-content': 'flex-end', +} + +const dialog = { + background: 'var(--background-30)', + 'margin-top': '15%', + 'flex-flow': 'column', +} + +type PluginProps = { + visible: boolean + extraStyle?: any + children?: any + id?: string +} + +// TODO(smolck): Consolidate all of these. + +export const Plugin = ({ id, visible, extraStyle, children }: PluginProps) => ( +
+
+ {children} +
+
+) + +export const PluginTop = ({ + visible, + id, + extraStyle, + children, +}: PluginProps) => ( +
+
+ {children} +
+
+) + +export const PluginBottom = ({ + visible, + id, + extraStyle, + children, +}: PluginProps) => ( +
+
+ {children} +
+
+) + +export const PluginRight = ({ + visible, + id, + extraStyle, + children, +}: PluginProps) => ( +
+
+ {children} +
+
+) diff --git a/src/components/references.ts b/src/components/references.ts deleted file mode 100644 index 7d4428e0..00000000 --- a/src/components/references.ts +++ /dev/null @@ -1,321 +0,0 @@ -import { RowNormal, RowHeader } from '../components/row-container' -import { PluginRight } from '../components/plugin-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import { simplifyPath } from '../support/utils' -import { showCursorline } from '../core/cursor' -import { badgeStyle } from '../ui/styles' -import Input from '../components/text-input' - -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' - -type Reference = { - lineNum: number - column: number - text: string -} - -type References = [string, Reference[]] - -type TextTransformer = (text: string, last?: boolean) => string - -let elref: HTMLElement -const SCROLL_AMOUNT = 0.25 -const els = new Map() - -const state = { - val: '', - referencedSymbol: '', - references: [] as References[], - cache: [] as References[], - vis: false, - ix: 0, - subix: -1, - loading: false, -} - -type S = typeof state - -// scroll after next section has been rendered as expanded (a little hacky) -const scrollIntoView = (next: number) => - setTimeout(() => { - const { - top: containerTop, - bottom: containerBottom, - } = elref.getBoundingClientRect() - const e = els.get(next) - if (!e) return - - const { top, height } = e.getBoundingClientRect() - - if (top + height > containerBottom) { - const offset = top - containerBottom - - if (offset < containerTop) elref.scrollTop += top - containerTop - else elref.scrollTop += offset + height + containerTop + 50 - } else if (top < containerTop) elref.scrollTop += top - containerTop - }, 1) - -const scrollSubitemsIntoView = (parentIx: number, next: number) => - setTimeout(() => { - const { - top: containerTop, - bottom: containerBottom, - } = elref.getBoundingClientRect() - const e = els.get(parentIx)?.children[1].children[next] - if (!e) return - - const { top, height } = e.getBoundingClientRect() - - if (top + height > containerBottom) { - const offset = top - containerBottom - - if (offset < containerTop) elref.scrollTop += top - containerTop - else elref.scrollTop += offset + height + containerTop + 50 - } else if (top < containerTop) elref.scrollTop += top - containerTop - }) - -const selectResult = (references: References[], ix: number, subix: number) => { - if (subix < 0) return - const [path, items] = references[ix] - const { lineNum, column } = items[subix] - - api.nvim.jumpTo({ - path, - line: lineNum - 1, - column: column - 1, - }) - showCursorline() -} - -const highlightPattern = ( - text: string, - pattern: string, - { - normal, - special, - }: { - normal: TextTransformer - special: TextTransformer - } -) => { - const stext = special(pattern) - return text - .trimLeft() - .split(pattern) - .reduce((grp, part, ix, arr) => { - if (!part && ix) return grp.push(stext), grp - if (!part) return grp - const last = ix === arr.length - 1 - ix ? grp.push(stext, normal(part, last)) : grp.push(normal(part, last)) - return grp - }, [] as string[]) -} - -const resetState = { vis: false, references: [] } - -const actions = { - hide: () => (vimFocus(), resetState), - - show: ({ references, referencedSymbol }: any) => { - vimBlur() - - return { - references, - referencedSymbol, - cache: references, - vis: true, - val: '', - ix: 0, - subix: -1, - loading: false, - } - }, - - select: () => (s: S) => { - vimFocus() - if (!s.references.length) return resetState - selectResult(s.references, s.ix, s.subix) - return resetState - }, - - change: (val: string) => (s: S) => ({ - val, - references: val - ? s.cache.map((m) => [ - m[0], - m[1].filter((x) => x.text.toLowerCase().includes(val)), - ]) - : s.cache, - }), - - nextGroup: () => (s: S) => { - const next = s.ix + 1 > s.references.length - 1 ? 0 : s.ix + 1 - scrollIntoView(next) - return { subix: -1, ix: next } - }, - - prevGroup: () => (s: S) => { - const next = s.ix - 1 < 0 ? s.references.length - 1 : s.ix - 1 - scrollIntoView(next) - return { subix: -1, ix: next } - }, - - next: () => (s: S) => { - const next = s.subix + 1 < s.references[s.ix][1].length ? s.subix + 1 : 0 - selectResult(s.references, s.ix, next) - scrollSubitemsIntoView(s.ix, next) - return { subix: next } - }, - - prev: () => (s: S) => { - const prev = - s.subix - 1 < 0 ? s.references[s.ix][1].length - 1 : s.subix - 1 - selectResult(s.references, s.ix, prev) - scrollSubitemsIntoView(s.ix, prev) - return { subix: prev } - }, - - down: () => { - const { height } = elref.getBoundingClientRect() - elref.scrollTop += Math.floor(height * SCROLL_AMOUNT) - }, - - up: () => { - const { height } = elref.getBoundingClientRect() - elref.scrollTop -= Math.floor(height * SCROLL_AMOUNT) - }, -} - -const view = ($: S, a: typeof actions) => - PluginRight($.vis, [ - , - Input({ - up: a.up, - hide: a.hide, - next: a.next, - prev: a.prev, - down: a.down, - select: a.select, - change: a.change, - nextGroup: a.nextGroup, - prevGroup: a.prevGroup, - value: $.val, - focus: true, - icon: Icon.Filter, - desc: 'filter references', - }), - - , - h( - 'div', - { - oncreate: (e: HTMLElement) => (elref = e), - style: { - maxHeight: '100%', - overflow: 'hidden', - }, - }, - $.references.map(([path, items], pos) => - h( - 'div', - { - key: path, - oncreate: (e: HTMLElement) => els.set(pos, e), - }, - [ - , - h( - RowHeader, - { - active: pos === $.ix, - }, - [ - , - h('span', simplifyPath(path, api.nvim.state.cwd)), - , - h( - 'div', - { - style: { - ...badgeStyle, - marginLeft: '12px', - }, - }, - [, h('span', items.length)] - ), - ] - ), - - pos === $.ix && - h( - 'div', - items.map((f, itemPos) => - h( - RowNormal, - { - active: pos === $.ix && itemPos === $.subix, - }, - highlightPattern(f.text, $.referencedSymbol, { - normal: (text, last) => - h( - 'span', - { - style: { - whiteSpace: 'pre', - textOverflow: last ? 'ellipsis' : undefined, - overflow: last ? 'inherit' : undefined, - }, - }, - text - ), - - special: (text) => - h( - 'span', - { - style: { - color: '#aaa', - background: 'rgba(255, 255, 255, 0.1)', - }, - }, - text - ), - }) - ) - ) - ), - ] - ) - ) - ), - ]) - -export const ui = app({ name: 'references', state, actions, view }) - -api.onAction('references', (_, items) => { - // TODO(smolck): Efficiency? This works but probably isn't the most - // performant. Ideally could remove the intermediate map. - // - // This code essentially takes a series of code reference objects from Lua, - // sorts them by filename (leveraging the map), and then turns that into - // an array for use above. - const itemsMap = items.reduce((map: Map, x: any) => { - const ref = { - lineNum: x.lnum, - column: x.col, - text: x.text, - } as Reference - - let maybeArr = map.get(x.filename) - if (maybeArr) maybeArr.push(ref) - else map.set(x.filename, [ref]) - - return map - }, new Map()) - - let stuffToShow = [] as References[] - itemsMap.forEach((value, key) => stuffToShow.push([key, value])) - - ui.show({ references: stuffToShow }) -}) diff --git a/src/components/row-container.ts b/src/components/row-container.ts deleted file mode 100644 index dd4bb53c..00000000 --- a/src/components/row-container.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { cvar, paddingVH, paddingH } from '../ui/css' -import { colors } from '../ui/styles' -import { h } from '../ui/uikit' - -const row = { - alignItems: 'center', - paddingTop: '4px', - paddingBottom: '4px', - paddingLeft: '12px', - paddingRight: '12px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - display: 'flex', - color: cvar('foreground-30'), - minHeight: '1.4rem', - fontSize: '1.1rem', -} - -const activeRow = { - ...row, - fontWeight: 'bold', - color: cvar('foreground-b20'), - background: cvar('background-10'), -} - -interface Options { - key?: any - active: boolean - [key: string]: any -} - -const removePropsIntendedForThisComponent = (stuff: Options) => { - const { active, ...rest } = stuff - return rest -} - -export const RowNormal = (o: Options, children: any[]) => - h( - 'div', - { - ...removePropsIntendedForThisComponent(o), - style: { - ...row, - ...(o.active ? activeRow : undefined), - ...o.style, - }, - }, - children - ) - -export const RowDesc = (o: Options, children: any[]) => - h( - 'div', - { - ...removePropsIntendedForThisComponent(o), - style: { - ...(o.active ? activeRow : row), - whiteSpace: 'normal', - overflow: 'normal', - ...o.style, - }, - }, - children - ) - -export const RowComplete = (o: Options, children: any[]) => - h( - 'div', - { - ...removePropsIntendedForThisComponent(o), - style: { - ...(o.active ? activeRow : row), - ...paddingVH(0, 0), - paddingRight: '8px', - lineHeight: cvar('line-height'), - fontFamily: 'var(--font)', - fontSize: 'var(--font-size)px', - ...o.style, - }, - }, - children - ) - -export const RowHeader = (o: Options, children: any[]) => - h( - 'div', - { - ...removePropsIntendedForThisComponent(o), - style: { - ...(o.active ? activeRow : row), - ...paddingH(6), - alignItems: 'center', - color: colors.hint, - background: cvar('background-20'), - ...(o.active - ? { - color: '#fff', - fontWeight: 'normal', - background: cvar('background-b10'), - } - : 0), - ...o.style, - }, - }, - children - ) - -export const RowImportant = (opts = {} as any, children: any[]) => - h( - 'div', - { - ...removePropsIntendedForThisComponent(opts), - style: { - ...opts.style, - ...row, - ...paddingH(8), - color: cvar('important'), - background: cvar('background-50'), - }, - }, - children - ) diff --git a/src/components/row-container.tsx b/src/components/row-container.tsx new file mode 100644 index 00000000..55e2aedc --- /dev/null +++ b/src/components/row-container.tsx @@ -0,0 +1,120 @@ +import { cvar, paddingVH, paddingH } from '../ui/css' +import { colors } from '../ui/styles' + +// TODO(smolck): Consolidate all of these Row* components into one? + +const row = { + 'align-items': 'center', + 'padding-top': '4px', + 'padding-bottom': '4px', + 'padding-left': '12px', + 'padding-right': '12px', + 'white-space': 'nowrap', + overflow: 'hidden', + 'text-overflow': 'ellipsis', + display: 'flex', + color: cvar('foreground-30'), + 'min-height': '1.4rem', + 'font-size': '1.1rem', +} + +const activeRow = { + ...row, + 'font-weight': 'bold', + color: cvar('foreground-b20'), + background: cvar('background-10'), +} + +interface RowProps { + key?: any + active: boolean + [key: string]: any + children?: any +} + +const removePropsIntendedForThisComponent = (stuff: RowProps) => { + const { active, ...rest } = stuff + return rest +} + +export const RowNormal = (props: RowProps) => ( +
+ {props.children} +
+) + +export const RowDesc = (props: RowProps) => ( +
+ {props.children} +
+) + +export const RowComplete = (props: RowProps) => ( +
+ {props.children} +
+) + +export const RowHeader = (props: RowProps) => ( +
+ {props.children} +
+) + +export const RowImportant = (props: RowProps = {} as any) => ( +
+ {props.children} +
+) diff --git a/src/components/statusline.ts b/src/components/statusline.ts deleted file mode 100644 index 68141218..00000000 --- a/src/components/statusline.ts +++ /dev/null @@ -1,479 +0,0 @@ -import { onSwitchVim, getCurrentName } from '../core/instance-manager' -import { getColorByName } from '../render/highlight-attributes' -import { sub, processAnyBuffered } from '../messaging/dispatch' -import { darken, brighten, cvar } from '../ui/css' -import { ExtContainer } from '../neovim/protocol' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' -import { colors } from '../ui/styles' -import { h, app } from '../ui/uikit' -import { basename } from 'path' -import { homedir } from 'os' - -interface Tab { - tab: ExtContainer - name: string -} - -interface TabInfo { - id: number - name: string -} - -interface TabView { - id: number - label: number - active: boolean -} - -const state = { - tabs: [] as TabInfo[], - active: -1, - filetype: '', - runningServers: new Set(), - message: '', - controlMessage: '', - line: 0, - column: 0, - cwd: '', - errors: 0, - warnings: 0, - branch: '', - additions: 0, - deletions: 0, - baseColor: '#4e415a', -} - -type S = typeof state - -const statusGroupStyle = { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', -} - -const itemStyle = { - color: cvar('foreground-40'), - display: 'flex', - height: '100%', - alignItems: 'center', - paddingLeft: '20px', - paddingRight: '20px', -} - -const iconBoxStyle = { - display: 'flex', - paddingRight: '4px', - alignItems: 'center', -} - -const container = document.getElementById('statusline') as HTMLElement - -Object.assign(container.style, { - height: '24px', - display: 'flex', - zIndex: 900, -}) - -const actions = { - setMessage: (message: string) => ({ message }), - setControlMessage: (controlMessage: string) => ({ controlMessage }), - updateTabs: ({ active, tabs }: any) => ({ active, tabs }), - setFiletype: (filetype: any) => ({ filetype }), - setLine: (line: any) => ({ line }), - setColumn: (column: any) => ({ column }), - setCwd: (cwd: string) => ({ cwd }), - setDiagnostics: ({ errors = 0, warnings = 0 }: any) => ({ errors, warnings }), - setGitBranch: (branch: any) => ({ branch }), - setGitStatus: ({ additions, deletions }: any) => ({ additions, deletions }), - setColor: (baseColor: any) => ({ baseColor }), - aiStart: ({ cwd, filetype }: any) => (s: S) => ({ - runningServers: new Set([...s.runningServers, cwd + filetype]), - }), -} - -const iconStyle = { style: { fontSize: '16px' } } - -const Label = (label: string) => - h( - 'div', - { - style: { - paddingBottom: '1px', - }, - }, - label - ) - -const Tab = ({ id, label, active }: TabView) => - h( - 'div', - { - key: id, - style: { - ...itemStyle, - paddingLeft: '20px', - paddingRight: '20px', - marginRight: '-14px', - paddingBottom: '1px', - clipPath: 'polygon(15px 0, 100% 0, calc(100% - 15px) 100%, 0 100%)', - color: cvar('foreground-40'), - ...(active - ? { - background: cvar('background-10'), - color: cvar('foreground'), - } - : undefined), - }, - }, - label - ) - -const view = ($: S) => - h( - 'div', - { - style: { - flex: '1', - display: 'flex', - justifyContent: 'space-between', - background: cvar('background-30'), - zIndex: '999', - }, - }, - [ - , - // LEFT - h( - 'div', - { - style: statusGroupStyle, - }, - [ - , - h( - 'div', - { - style: { - ...itemStyle, - paddingLeft: '15px', - color: brighten($.baseColor, 90), - background: darken($.baseColor, 20), - paddingRight: '30px', - marginRight: '-15px', - clipPath: - 'polygon(0 0, calc(100% - 15px) 0, 100% 100%, 0 100%)', - }, - }, - [ - , - h( - 'div', - { - style: iconBoxStyle, - }, - [, h(Icon.HardDrive, iconStyle)] - ), - - Label($.cwd || 'main'), - ] - ), - - $.branch && - h( - 'div', - { - style: { - ...itemStyle, - paddingLeft: '30px', - paddingRight: '30px', - marginRight: '-15px', - color: brighten($.baseColor, 40), - background: darken($.baseColor, 35), - clipPath: - 'polygon(0 0, calc(100% - 15px) 0, 100% 100%, 15px 100%)', - }, - }, - [ - , - h( - 'div', - { - style: { - ...iconBoxStyle, - paddingTop: '4px', - display: $.branch ? '' : 'none', - }, - }, - [h(Icon.GitBranch, iconStyle)] - ), - - Label($.branch), - ] - ), - - $.branch && - h( - 'div', - { - style: { - ...itemStyle, - paddingLeft: '30px', - paddingRight: '30px', - marginRight: '-15px', - color: brighten($.baseColor, 10), - background: darken($.baseColor, 50), - clipPath: - 'polygon(0 0, calc(100% - 15px) 0, 100% 100%, 15px 100%)', - }, - }, - [ - , - // ADDITIONS - h( - 'div', - { - style: { - ...iconBoxStyle, - color: $.additions > 0 ? colors.success : undefined, - }, - }, - [, h(Icon.PlusSquare, iconStyle)] - ), - - h( - 'div', - { - style: { - color: $.additions > 0 ? colors.success : undefined, - paddingBottom: '1px', - }, - }, - `${$.additions}` - ), - - // DELETIONS - h( - 'div', - { - style: { - ...iconBoxStyle, - marginLeft: '12px', - color: $.deletions > 0 ? colors.error : undefined, - }, - }, - [, h(Icon.MinusSquare, iconStyle)] - ), - - h( - 'div', - { - style: { - color: $.deletions > 0 ? colors.error : undefined, - paddingBottom: '1px', - }, - }, - `${$.deletions}` - ), - ] - ), - - // STATUSBAR MESSAGE - h('div', [ - , - h( - 'div', - { - style: { - marginLeft: '26px', - color: cvar('foreground-60'), - paddingBottom: '1px', - }, - }, - $.message - ), - ]), - ] - ), - - // RIGHT - h( - 'div', - { - style: statusGroupStyle, - }, - [ - , - // STATUSBAR CONTROL MESSAGE - h('div', [ - , - h( - 'div', - { - style: { - marginRight: '10px', - color: cvar('foreground-60'), - paddingBottom: '1px', - }, - }, - $.controlMessage - ), - ]), - - $.runningServers.has(api.nvim.state.cwd + $.filetype) && - h( - 'div', - { - style: itemStyle, - }, - [, h('div', [, h(Icon.Zap, { color: '#555', ...iconStyle })])] - ), - - h( - 'div', - { - style: { - ...itemStyle, - paddingLeft: '30px', - paddingRight: '30px', - color: brighten($.baseColor, 10), - background: darken($.baseColor, 50), - marginRight: '-15px', - clipPath: - 'polygon(15px 0, 100% 0, calc(100% - 15px) 100%, 0 100%)', - }, - }, - [ - , - // ERRORS - h( - 'div', - { - style: { - ...iconBoxStyle, - color: $.errors > 0 ? colors.error : undefined, - }, - }, - [, h(Icon.XCircle, iconStyle)] - ), - - h( - 'div', - { - style: { - color: $.errors > 0 ? colors.error : undefined, - paddingBottom: '1px', - }, - }, - `${$.errors}` - ), - - // WARNINGS - h( - 'div', - { - style: { - ...iconBoxStyle, - marginLeft: '12px', - color: $.warnings > 0 ? colors.warning : undefined, - }, - }, - [, h(Icon.AlertTriangle, iconStyle)] - ), - - h( - 'div', - { - style: { - color: $.warnings > 0 ? colors.warning : undefined, - paddingBottom: '1px', - }, - }, - `${$.warnings}` - ), - ] - ), - - h( - 'div', - { - style: { - ...itemStyle, - paddingLeft: '30px', - paddingRight: '30px', - color: brighten($.baseColor, 60), - background: darken($.baseColor, 30), - marginRight: '-15px', - clipPath: - 'polygon(15px 0, 100% 0, calc(100% - 15px) 100%, 0 100%)', - paddingBottom: '1px', - }, - }, - [, h('div', `${$.line + 1}:${$.column + 1}`)] - ), - - h( - 'div', - { - style: { - display: 'flex', - height: '100%', - }, - }, - [ - , - $.tabs.map(({ id }, ix) => - Tab({ - id, - label: ix + 1, - active: $.active === id, - }) - ), - ] - ), - ] - ), - ] - ) - -const ui = app({ - name: 'statusline', - state, - actions, - view, - element: container, -}) - -api.nvim.watchState.filetype(ui.setFiletype) -api.nvim.watchState.line(ui.setLine) -api.nvim.watchState.column(ui.setColumn) -api.nvim.watchState.cwd((cwd: string) => { - const next = homedir() === cwd ? getCurrentName() : basename(cwd) - ui.setCwd(next) -}) - -sub('tabs', async ({ curtab, tabs }: { curtab: ExtContainer; tabs: Tab[] }) => { - const mtabs: TabInfo[] = tabs.map((t) => ({ id: t.tab.id, name: t.name })) - mtabs.length > 1 - ? ui.updateTabs({ active: curtab.id, tabs: mtabs }) - : ui.updateTabs({ active: -1, tabs: [] }) -}) - -api.git.onBranch((branch) => ui.setGitBranch(branch)) -api.git.onStatus((status) => ui.setGitStatus(status)) -sub('ai.diagnostics.count', (count) => ui.setDiagnostics(count)) -sub('ai.start', (opts) => ui.aiStart(opts)) -sub('message.status', (msg) => ui.setMessage(msg)) -sub('message.control', (msg) => ui.setControlMessage(msg)) -onSwitchVim(() => ui.updateTabs({ active: -1, tabs: [] })) - -api.nvim.watchState.colorscheme(async () => { - const { background } = await getColorByName('StatusLine') - if (background) ui.setColor(background) -}) - -setImmediate(async () => { - processAnyBuffered('tabs') - const { background } = await getColorByName('StatusLine') - if (background) ui.setColor(background) -}) diff --git a/src/components/text-input.ts b/src/components/text-input.ts deleted file mode 100644 index 51e1d3eb..00000000 --- a/src/components/text-input.ts +++ /dev/null @@ -1,222 +0,0 @@ -import Loading from '../components/loading' -import { paddingVH, cvar } from '../ui/css' -import { xfrmUp } from '../core/input' -import { Component } from 'hyperapp' -import { h } from '../ui/uikit' - -interface Props { - value: string - icon: Component - background: string - color: string - small: boolean - desc: string - focus: boolean - position: number - change: (val: string) => void - select: (val: string) => void - hide: () => void - next: () => void - prev: () => void - nextGroup: () => void - prevGroup: () => void - down: () => void - up: () => void - top: () => void - bottom: () => void - jumpPrev: () => void - jumpNext: () => void - tab: () => void - ctrlH: () => void - ctrlG: () => void - ctrlL: () => void - ctrlC: () => void - yank: () => void - loading: boolean - loadingSize: number - loadingColor: string - pathMode: boolean -} - -interface TextInputProps extends Partial { - value: string - icon: Component -} - -const setPosition = (e?: HTMLInputElement, position?: number) => { - if (!e || !position) return - position > -1 && e.setSelectionRange(position, position) -} - -const setFocus = (e: HTMLInputElement, shouldFocus: boolean) => { - if (e && e !== document.activeElement && shouldFocus) e.focus() - if (!shouldFocus) e && e.blur() -} - -const nopMaybe = (obj: object) => - new Proxy(obj, { - get: (_, key) => Reflect.get(obj, key) || (() => {}), - }) as Props - -const keToStr = (e: KeyboardEvent) => - [ - e.key, - (e.ctrlKey) | 0, - (e.metaKey) | 0, - (e.altKey) | 0, - (e.shiftKey) | 0, - ].join('') - -// TODO: could be better? it's global so will be shared between different -// inputs. however only one input will have focus at a time, so perhaps -// it's not a big deal -// -// the reason this has to live outside the function is because the view -// function will be triggered on re-render. pressing keys will potentially -// trigger re-renders, thus reseting the value of lastDown when inside -// the function. -let lastDown = '' - -const view = ( - { - desc, - icon, - color, - background, - loadingSize, - loadingColor, - value = '', - position = -1, - small = false, - focus = false, - loading = false, - pathMode = false, - }: TextInputProps, - $: Props -) => - h( - 'div', - { - style: { - background, - ...paddingVH(12, small ? 5 : 10), - display: 'flex', - flex: 1, - alignItems: 'center', - maxHeight: small ? '1.8rem' : '2.1rem', - minHeight: small ? '1.8rem' : '2.1rem', - }, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - alignItems: 'center', - paddingRight: '8px', - }, - }, - [ - , - h(icon, { - style: !small ? { fontSize: '1.7rem' } : undefined, - color: cvar('foreground-70'), - }), - ] - ), - - h( - 'div', - { - style: { - flex: 1, - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - }, - }, - [ - , - h('input', { - value, - style: { - color, - fontSize: small ? '1rem' : '1.4rem', - }, - type: 'text', - oncreate: (e: HTMLInputElement) => { - setFocus(e, focus) - setPosition(e, position) - }, - // TODO: hack to get hack to get dead keys working working - onblur: (e: HTMLInputElement) => { - document.getElementById('hacky-textarea')?.focus() - }, - onupdate: (e: HTMLInputElement) => { - setFocus(e, focus) - setPosition(e, position) - }, - placeholder: desc, - onkeyup: (e: KeyboardEvent) => { - const prevKeyAndThisOne = lastDown + keToStr(e) - - if (xfrmUp.has(prevKeyAndThisOne)) { - const { key } = xfrmUp.get(prevKeyAndThisOne)!(e) - if (key.toLowerCase() === '') { - lastDown = '' - const target = e.target as HTMLInputElement - target.blur() - return $.hide() - } - } - }, - onkeydown: (e: KeyboardEvent) => { - const { ctrlKey: ctrl, metaKey: meta, key } = e - const cm = ctrl || meta - - lastDown = keToStr(e) - - if (key === 'Tab') { - e.preventDefault() - return $.tab() - } - - if (key === 'Escape') return $.hide() - if (key === 'Enter') return $.select(value) - if (key === 'Backspace') return $.change(value.slice(0, -1)) - - if (cm && key === 'w') - return pathMode - ? $.change(value.split('/').slice(0, -1).join('/')) - : $.change(value.split(' ').slice(0, -1).join(' ')) - - if (cm && key === 'g') return $.ctrlG() - if (cm && key === 'h') return $.ctrlH() - if (cm && key === 'l') return $.ctrlL() - if (cm && key === 'c') return $.ctrlC() - if (cm && key === 'j') return $.next() - if (cm && key === 'k') return $.prev() - if (cm && key === 'n') return $.nextGroup() - if (cm && key === 'p') return $.prevGroup() - if (cm && key === 'd') return $.down() - if (cm && key === 'u') return $.up() - if (cm && key === 'i') return $.jumpNext() - if (cm && key === 'o') return $.jumpPrev() - if (cm && key === 'y') return $.yank() - if (cm && e.shiftKey && key === 'D') return $.bottom() - if (cm && e.shiftKey && key === 'U') return $.top() - - const nextVal = value + (key.length > 1 ? '' : key) - if (nextVal !== value) $.change(nextVal) - }, - }), - - loading && Loading({ color: loadingColor, size: loadingSize }), - ] - ), - ] - ) - -export default (props: TextInputProps) => view(props, nopMaybe(props)) diff --git a/src/components/text-input.tsx b/src/components/text-input.tsx new file mode 100644 index 00000000..ea654f73 --- /dev/null +++ b/src/components/text-input.tsx @@ -0,0 +1,228 @@ +import Loading from './loading' +import { paddingVH, cvar } from '../ui/css' +import { xfrmUp } from '../core/input' +import { FormEvent } from 'inferno' +import Icon from './icon' + +interface Props { + value: string + icon: string + background: string + color: string + small: boolean + desc: string + focus: boolean + position: number + change: (val: string) => void + select: (val: string) => void + hide: () => void + next: () => void + prev: () => void + nextGroup: () => void + prevGroup: () => void + down: () => void + up: () => void + top: () => void + bottom: () => void + jumpPrev: () => void + jumpNext: () => void + tab: () => void + ctrlH: () => void + ctrlG: () => void + ctrlL: () => void + ctrlC: () => void + yank: () => void + loading: boolean + loadingSize: number + loadingColor: string + pathMode: boolean +} + +interface TextInputProps extends Partial { + id: string + value: string + icon: string +} + +const setPosition = (e?: HTMLInputElement, position?: number) => { + if (!e || !position) return + position > -1 && e.setSelectionRange(position, position) +} + +const setFocus = (e: HTMLInputElement, shouldFocus: boolean) => { + if (e && e !== document.activeElement && shouldFocus) e.focus() + if (!shouldFocus) e && e.blur() +} + +const nopMaybe = (obj: object) => + new Proxy(obj, { + get: (_, key) => Reflect.get(obj, key) || (() => {}), + }) as Props + +const keToStr = (e: KeyboardEvent) => + [ + e.key, + (e.ctrlKey as any) | 0, + (e.metaKey as any) | 0, + (e.altKey as any) | 0, + (e.shiftKey as any) | 0, + ].join('') + +// TODO: could be better? it's global so will be shared between different +// inputs. however only one input will have focus at a time, so perhaps +// it's not a big deal +// +// the reason this has to live outside the function is because the view +// function will be triggered on re-render. pressing keys will potentially +// trigger re-renders, thus reseting the value of lastDown when inside +// the function. +let lastDown = '' + +// TODO(smolck): But why though? Has to be another way to get access to +// `onComponentDidMount` with normal stuff like +const WhyInput = (props: any) => + +const textInput = ( + { + desc, + icon, + color, + background, + loadingSize, + loadingColor, + value = '', + position = -1, + small = false, + focus = false, + loading = false, + pathMode = false, + id, + }: TextInputProps, + $: Props +) => ( +
+
+ +
+
+ { + // document.getElementById('keycomp-textarea')?.focus() + // }} + // onComponentDidUpdate={(_: any, nextProps: any) => + // nextProps.visible + // ? document.getElementById('hacky-textarea')?.focus() + // : undefined + // } + onComponentDidUpdate={(_lastProps: any, _nextProps: any) => { + const e = document.getElementById(id)! as HTMLInputElement + setFocus(e, focus) + setPosition(e, position) + }} + onComponentDidMount={(e: HTMLInputElement) => { + setFocus(e, focus) + setPosition(e, position) + }} + onInput={(e: FormEvent) => { + setFocus(e.currentTarget, focus) + setPosition(e.currentTarget, position) + }} + onKeyUp={(e: KeyboardEvent) => { + const prevKeyAndThisOne = lastDown + keToStr(e) + + if (xfrmUp.has(prevKeyAndThisOne)) { + const { key } = xfrmUp.get(prevKeyAndThisOne)!(e) + if (key.toLowerCase() === '') { + lastDown = '' + ;(e.target as HTMLInputElement).blur() + return $.hide() + } + } + }} + onKeyDown={(e: KeyboardEvent) => { + const { ctrlKey: ctrl, metaKey: meta, key } = e + const cm = ctrl || meta + + lastDown = keToStr(e) + + if (key === 'Tab') { + e.preventDefault() + return $.tab() + } + + if (key === 'Escape') return $.hide() + if (key === 'Enter') return $.select(value) + if (key === 'Backspace') return $.change(value.slice(0, -1)) + + if (cm && key === 'w') + return pathMode + ? $.change(value.split('/').slice(0, -1).join('/')) + : $.change(value.split(' ').slice(0, -1).join(' ')) + + if (cm && key === 'g') return $.ctrlG() + if (cm && key === 'h') return $.ctrlH() + if (cm && key === 'l') return $.ctrlL() + if (cm && key === 'c') return $.ctrlC() + if (cm && key === 'j') return $.next() + if (cm && key === 'k') return $.prev() + if (cm && key === 'n') return $.nextGroup() + if (cm && key === 'p') return $.prevGroup() + if (cm && key === 'd') return $.down() + if (cm && key === 'u') return $.up() + if (cm && key === 'i') return $.jumpNext() + if (cm && key === 'o') return $.jumpPrev() + if (cm && key === 'y') return $.yank() + if (cm && e.shiftKey && key === 'D') return $.bottom() + if (cm && e.shiftKey && key === 'U') return $.top() + + const nextVal = value + (key.length > 1 ? '' : key) + if (nextVal !== value) $.change(nextVal) + }} + /> +
+ + {loading && } +
+) + +export default (props: TextInputProps) => textInput(props, nopMaybe(props)) diff --git a/src/components/vim-create.ts b/src/components/vim-create.ts deleted file mode 100644 index 55137033..00000000 --- a/src/components/vim-create.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Plugin } from '../components/plugin-container' -import { app, vimBlur, vimFocus } from '../ui/uikit' -import { createVim } from '../core/instance-manager' -import Input from '../components/text-input' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' - -const state = { - value: '', - visible: false, -} - -type S = typeof state - -const actions = { - show: () => (vimBlur(), { visible: true }), - hide: () => (vimFocus(), { value: '', visible: false }), - change: (value: string) => ({ value }), - select: () => (s: S) => { - vimFocus() - s.value && createVim(s.value) - return { value: '', visible: false } - }, -} - -const view = ($: S, a: typeof actions) => - Plugin($.visible, [ - , - Input({ - hide: a.hide, - select: a.select, - change: a.change, - value: $.value, - focus: true, - icon: Icon.FolderPlus, - desc: 'create new vim instance', - }), - ]) - -const ui = app({ name: 'vim-create', state, actions, view }) -api.onAction('vim-create', ui.show) diff --git a/src/components/vim-rename.ts b/src/components/vim-rename.ts deleted file mode 100644 index eb2dc0e3..00000000 --- a/src/components/vim-rename.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { renameCurrent, getCurrentName } from '../core/instance-manager' -import { Plugin } from '../components/plugin-container' -import { app, vimBlur, vimFocus } from '../ui/uikit' -import Input from '../components/text-input' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' - -const state = { - value: '', - visible: false, -} - -type S = typeof state - -const actions = { - show: (value: string) => (vimBlur(), { value, visible: true }), - hide: () => (vimFocus(), { value: '', visible: false }), - change: (value: string) => ({ value }), - select: () => (s: S) => { - vimFocus() - s.value && renameCurrent(s.value) - return { value: '', visible: false } - }, -} - -const view = ($: S, a: typeof actions) => - Plugin($.visible, [ - , - Input({ - hide: a.hide, - select: a.select, - change: a.change, - value: $.value, - focus: true, - icon: Icon.Edit, - desc: 'rename vim instance', - }), - ]) - -const ui = app({ name: 'vim-rename', state, actions, view }) -api.onAction('vim-rename', () => ui.show(getCurrentName())) diff --git a/src/components/vim-search.ts b/src/components/vim-search.ts deleted file mode 100644 index 203a9573..00000000 --- a/src/components/vim-search.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - hideCursor, - showCursor, - disableCursor, - enableCursor, -} from '../core/cursor' -import { CommandType, CommandUpdate } from '../render/events' -import * as windows from '../windows/window-manager' -import { WindowOverlay } from '../windows/window' -import Input from '../components/text-input' -import { sub } from '../messaging/dispatch' -import { rgba, paddingV } from '../ui/css' -import * as Icon from 'hyperapp-feather' -import { is } from '../support/utils' -import { makel } from '../ui/vanilla' -import { app, h } from '../ui/uikit' - -const state = { - visible: false, - value: '', - position: 0, - kind: CommandType.Ex, -} - -type S = typeof state -let winOverlay: WindowOverlay - -const actions = { - hide: () => { - enableCursor() - showCursor() - if (winOverlay) winOverlay.remove() - return { value: '', visible: false } - }, - updateQuery: ({ cmd, kind, position }: CommandUpdate) => (s: S) => { - const cmdKind = kind || s.kind - hideCursor() - disableCursor() - - !s.visible && - setImmediate(() => { - winOverlay = windows.getActive().addOverlayElement(containerEl) - }) - - return { - position, - kind: cmdKind, - visible: true, - value: is.string(cmd) && s.value !== cmd ? cmd : s.value, - } - }, -} - -type A = typeof actions - -const printCommandType = (kind: CommandType) => { - if (kind === CommandType.SearchForward) return 'forward search' - if (kind === CommandType.SearchBackward) return 'backward search' - // should never happen - else return 'search' -} - -const view = ($: S, a: A) => - h( - 'div', - { - style: { - display: $.visible ? 'flex' : 'none', - flex: 1, - }, - }, - [ - , - h( - 'div', - { - style: { - ...paddingV(20), - display: 'flex', - alignItems: 'center', - // TODO: figure out a good color from the colorscheme... StatusLine? - background: rgba(217, 150, 255, 0.17), - }, - }, - [, h('span', printCommandType($.kind))] - ), - - Input({ - small: true, - focus: $.visible, - desc: 'search query', - value: $.value, - icon: Icon.Search, - position: $.position, - hide: a.hide, - select: a.hide, - }), - ] - ) - -const containerEl = makel({ - position: 'absolute', - width: '100%', - display: 'flex', - background: 'var(--background-30)', -}) - -const ui = app({ - name: 'vim-search', - state, - actions, - view, - element: containerEl, -}) - -sub('search.hide', ui.hide) -sub('search.update', ui.updateQuery) diff --git a/src/components/vim-switch.ts b/src/components/vim-switch.ts deleted file mode 100644 index 62feaed0..00000000 --- a/src/components/vim-switch.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { list, switchVim } from '../core/instance-manager' -import { Plugin } from '../components/plugin-container' -import { RowNormal } from '../components/row-container' -import { h, app, vimBlur, vimFocus } from '../ui/uikit' -import Input from '../components/text-input' -import { filter } from 'fuzzaldrin-plus' -import * as Icon from 'hyperapp-feather' -import api from '../core/instance-api' - -interface Instance { - id: number - name: string -} - -const state = { - value: '', - visible: false, - list: [] as Instance[], - cache: [] as Instance[], - index: 0, -} - -type S = typeof state - -const actions = { - show: (d: Instance[]) => (vimBlur(), { list: d, cache: d, visible: true }), - hide: () => (vimFocus(), { value: '', visible: false, index: 0 }), - change: (value: string) => (s: S) => ({ - value, - index: 0, - list: value - ? filter(s.list, value, { key: 'name' }).slice(0, 10) - : s.cache.slice(0, 10), - }), - - select: () => (s: S) => { - vimFocus() - if (!s.list.length) return { value: '', visible: false, index: 0 } - const { id } = s.list[s.index] - if (id) switchVim(id) - return { value: '', visible: false, index: 0 } - }, - - // TODO: don't limit list to 10 entries and scroll instead! - next: () => (s: S) => ({ - index: s.index + 1 > Math.min(s.list.length - 1, 9) ? 0 : s.index + 1, - }), - prev: () => (s: S) => ({ - index: s.index - 1 < 0 ? Math.min(s.list.length - 1, 9) : s.index - 1, - }), -} - -const view = ($: S, a: typeof actions) => - Plugin($.visible, [ - , - Input({ - hide: a.hide, - change: a.change, - select: a.select, - next: a.next, - prev: a.prev, - value: $.value, - focus: true, - icon: Icon.Grid, - desc: 'switch vim instance', - }), - - h( - 'div', - $.list.map(({ id, name }, ix) => - h( - RowNormal, - { - key: `${id}-${name}`, - active: ix === $.index, - }, - [, h('span', name)] - ) - ) - ), - ]) - -const ui = app({ name: 'vim-switch', state, actions, view }) -api.onAction('vim-switch', () => ui.show(list())) diff --git a/src/core/cursor.ts b/src/core/cursor.ts index 5a6245ee..a68e2a14 100644 --- a/src/core/cursor.ts +++ b/src/core/cursor.ts @@ -27,31 +27,31 @@ let cursorCharVisible = true Object.assign(cursorline.style, { background: 'rgba(var(--background-alpha), 0.2)', position: 'absolute', - mixBlendMode: 'screen', + 'mix-blend-mode': 'screen', height: `${cell.height}px`, - zIndex: 60, + 'z-index': 60, }) Object.assign(debugline.style, { display: 'none', position: 'absolute', - mixBlendMode: 'screen', + 'mix-blend-mode': 'screen', height: `${cell.height}px`, - zIndex: 60, + 'z-index': 60, }) Object.assign(cursorEl.style, { - zIndex: 70, + 'z-index': 70, position: 'absolute', display: 'none', - justifyContent: 'center', - alignItems: 'center', + 'justify-content': 'center', + 'align-items': 'center', }) Object.assign(cursorChar.style, { filter: 'invert(1) grayscale(1)', - fontFamily: 'var(--font)', - fontSize: 'calc(var(--font-size) * 1px)', + 'font-family': 'var(--font)', + 'font-size': 'calc(var(--font-size) * 1px)', }) cursorEl.appendChild(cursorChar) diff --git a/src/core/input.ts b/src/core/input.ts index dacafdd0..5b480e48 100644 --- a/src/core/input.ts +++ b/src/core/input.ts @@ -227,7 +227,7 @@ export const registerOneTimeUseShortcuts = ( shortcuts.forEach((s) => globalShortcuts.set(s, () => done(s))) } -let textarea = document.getElementById('hacky-textarea') +let textarea = document.getElementById('keycomp-textarea') const sendKeys = async (e: KeyboardEvent, inputType: InputType) => { const key = bypassEmptyMod(e.key) @@ -241,7 +241,7 @@ const sendKeys = async (e: KeyboardEvent, inputType: InputType) => { keyListener(inputKeys, inputType) } -const keydownHandler = (e) => { +const keydownHandler = (e: KeyboardEvent) => { if (!windowHasFocus || !isCapturing) return const es = keToStr(e) @@ -268,7 +268,7 @@ const keydownHandler = (e) => { sendKeys(e, InputType.Down) } -const keyupHandler = (e) => { +const keyupHandler = (e: KeyboardEvent) => { if (!windowHasFocus || !isCapturing) return // one of the observed ways in which we can have a 'keyup' event without a @@ -293,8 +293,8 @@ const keyupHandler = (e) => { } // Need to handle key events from window for GUI elements like the external -// cmdline, so if the hacky textarea isn't focused (which it won't be when -// those elements are in use), handle the event from the window. +// cmdline, so if the key composition textarea isn't focused (which it won't +// be when those elements are in use), handle the event from the window. window.addEventListener('keydown', (e) => { if (textarea) if (textarea === document.activeElement) return diff --git a/src/core/instance-api.ts b/src/core/instance-api.ts index 716dfd1e..3bf1e045 100644 --- a/src/core/instance-api.ts +++ b/src/core/instance-api.ts @@ -41,7 +41,7 @@ onCreateVim((info) => { instance.on.showNeovimMessage(async (...a: any[]) => { if (!isActive()) return - const msg = require('../components/messages').default.show(...a) + const msg = require('../components/nvim/messages').default.show(...a) return msg.promise }) instance.on.showStatusBarMessage((message: string) => { diff --git a/src/core/master-control.ts b/src/core/master-control.ts index 1b75fc88..5ebee3b8 100644 --- a/src/core/master-control.ts +++ b/src/core/master-control.ts @@ -142,7 +142,11 @@ export const onExit = (fn: ExitFn) => { onExitFn = fn } export const onRedraw = (fn: RedrawFn) => onEvent('redraw', fn) -export const input = (keys: string) => api.input(keys) +export const input = (keys: string) => { + // TODO: get hack to get hack to get dead keys working working working better + document.getElementById('keycomp-textarea')?.focus() + api.input(keys) +} export const getMode = () => req.getMode() as Promise<{ mode: string; blocking: boolean }> diff --git a/src/dev/recorder.ts b/src/dev/recorder.ts index ab14e521..8a4ebb88 100644 --- a/src/dev/recorder.ts +++ b/src/dev/recorder.ts @@ -1,5 +1,5 @@ import * as storage from '../support/local-storage' -import messages, { MessageKind } from '../components/messages' +import messages, { MessageKind } from '../components/nvim/messages' import { is } from '../support/utils' import { makel } from '../ui/vanilla' const finder = require('@medv/finder').default diff --git a/src/inventory/actions.ts b/src/inventory/actions.ts index d874d8e7..208c9ca2 100644 --- a/src/inventory/actions.ts +++ b/src/inventory/actions.ts @@ -49,7 +49,7 @@ const actions: InventoryAction[] = [ name: 'Files', description: 'Find files in project', // TODO: should we do something like this instead? - // onAction: () => import('../components/files').then(m => m.show()) + // onAction: () => import('../components/extensions/files').then(m => m.show()) onAction: modc('files'), }, { diff --git a/src/neovim/api.ts b/src/neovim/api.ts index f29af761..2b37cabb 100644 --- a/src/neovim/api.ts +++ b/src/neovim/api.ts @@ -108,17 +108,17 @@ const api = { // trying to do dynamic introspection (obj vs arr) messy with typings. (also a bit slower) const as = { buf: (p: Promise): Promise => - p.then((e) => Buffer(e.id)), + p.then((e) => createBuffer(e.id)), bufl: (p: Promise): Promise => - p.then((m) => m.map((e) => Buffer(e.id))), + p.then((m) => m.map((e) => createBuffer(e.id))), win: (p: Promise): Promise => - p.then((e) => Window(e.id)), + p.then((e) => createWindow(e.id)), winl: (p: Promise): Promise => - p.then((m) => m.map((e) => Window(e.id))), + p.then((m) => m.map((e) => createWindow(e.id))), tab: (p: Promise): Promise => - p.then((e) => Tabpage(e.id)), + p.then((e) => createTabpage(e.id)), tabl: (p: Promise): Promise => - p.then((m) => m.map((e) => Tabpage(e.id))), + p.then((m) => m.map((e) => createTabpage(e.id))), } const subscribe = (event: string, fn: (data: any) => void) => { @@ -291,7 +291,7 @@ const buffers = { create: async ({ filetype = '', content = '' } = {}) => { const bufid = await call.bufnr('[No Name]', 420) cmd(`b ${bufid}`) - const buffer = Buffer(bufid) + const buffer = createBuffer(bufid) if (filetype) buffer.setOption(BufferOption.Filetype, filetype) if (content) buffer.append(0, content.split('\n')) return buffer @@ -507,16 +507,20 @@ watchers.events.emit('bufLoad') autocmd.CompleteDone((word) => watchers.events.emit('completion', word)) autocmd.CursorMoved(() => watchers.events.emit('cursorMove')) autocmd.CursorMovedI(() => watchers.events.emit('cursorMoveInsert')) -autocmd.BufAdd((bufId) => watchers.events.emit('bufOpen', Buffer(bufId - 0))) -autocmd.BufEnter((bufId) => watchers.events.emit('bufLoad', Buffer(bufId - 0))) +autocmd.BufAdd((bufId) => + watchers.events.emit('bufOpen', createBuffer(bufId - 0)) +) +autocmd.BufEnter((bufId) => + watchers.events.emit('bufLoad', createBuffer(bufId - 0)) +) autocmd.BufWritePre((bufId) => - watchers.events.emit('bufWritePre', Buffer(bufId - 0)) + watchers.events.emit('bufWritePre', createBuffer(bufId - 0)) ) autocmd.BufWritePost((bufId) => - watchers.events.emit('bufWrite', Buffer(bufId - 0)) + watchers.events.emit('bufWrite', createBuffer(bufId - 0)) ) autocmd.BufWipeout((bufId) => - watchers.events.emit('bufClose', Buffer(bufId - 0)) + watchers.events.emit('bufClose', createBuffer(bufId - 0)) ) autocmd.InsertEnter(() => watchers.events.emit('insertEnter')) autocmd.InsertLeave(() => watchers.events.emit('insertLeave')) @@ -541,7 +545,7 @@ autocmd.TextChangedI((revision) => { // TODO: i think we should just determine this from render events autocmd.WinEnter((id: number) => watchers.events.emit('winEnter', id)) -autocmd.WinEnter((id: number) => (_currentCache.window = Window(id - 0))) +autocmd.WinEnter((id: number) => (_currentCache.window = createWindow(id - 0))) as.win(req.core.getCurrentWin()).then((win) => (_currentCache.window = win)) on.bufLoad((buffer) => (_currentCache.buffer = buffer)) @@ -599,15 +603,15 @@ const current = { } const fromId = { - buffer: (id: number): Buffer => Buffer(id), - window: (id: number): Window => Window(id), - tabpage: (id: number): Tabpage => Tabpage(id), + buffer: (id: number): Buffer => createBuffer(id), + window: (id: number): Window => createWindow(id), + tabpage: (id: number): Tabpage => createTabpage(id), } const HL_CLR = 'nvim_buf_clear_highlight' const HL_ADD = 'nvim_buf_add_highlight' -const Buffer = (id: any) => +const createBuffer = (id: any) => ({ id, get number() { @@ -679,7 +683,11 @@ const Buffer = (id: any) => setLines: (start, end, lines) => api.buf.setLines(id, start, end, true, lines), delete: (start) => api.buf.setLines(id, start, start + 1, true, []), - appendRange: async (position, text, undojoin = false) => { + appendRange: async ( + position: { line: any; character: any }, + text: any, + undojoin = false + ) => { const { line, character: column } = position const lines = await req.buf.getLines(id, line, -2, false) const updatedLines = TextEditPatch.append({ lines, column, text }) @@ -692,7 +700,7 @@ const Buffer = (id: any) => ) if (undojoin) cmd('undojoin') }, - replaceRange: async ({ start, end }, text, undojoin = false) => { + replaceRange: async ({ start, end }: any, text: any, undojoin = false) => { const lines = await req.buf.getLines(id, start.line, end.line + 1, false) const updatedLines = TextEditPatch.replace({ lines, @@ -703,7 +711,7 @@ const Buffer = (id: any) => req.buf.setLines(id, start.line, end.line + 1, false, updatedLines) if (undojoin) cmd('undojoin') }, - deleteRange: async ({ start, end }, undojoin = false) => { + deleteRange: async ({ start, end }: any, undojoin = false) => { const lines = await req.buf.getLines(id, start.line, end.line, false) const updatedLines = TextEditPatch.remove({ lines, @@ -742,7 +750,7 @@ const Buffer = (id: any) => }, } as Buffer) -const Window = (id: any) => +const createWindow = (id: any) => ({ id, get number() { @@ -779,7 +787,7 @@ const Window = (id: any) => setOption: (name, val) => api.win.setOption(id, name, val), } as Window) -const Tabpage = (id: any) => +const createTabpage = (id: any) => ({ id, get number() { @@ -800,9 +808,9 @@ const Tabpage = (id: any) => } as Tabpage) const dummy = { - win: Window(0), - buf: Buffer(0), - tab: Tabpage(0), + win: createWindow(0), + buf: createBuffer(0), + tab: createTabpage(0), } const exportAPI = { diff --git a/src/neovim/state.ts b/src/neovim/state.ts index eea0774f..41cfab18 100644 --- a/src/neovim/state.ts +++ b/src/neovim/state.ts @@ -54,7 +54,7 @@ type UntilStateValue2 = { type UntilStateValue = UntilStateValue1 & UntilStateValue2 -export default (stateName: string) => { +export default (_stateName: string) => { const watchers = new EventEmitter() const stateChangeFns = new Set() @@ -137,27 +137,6 @@ export default (stateName: string) => { }, }) - if (process.env.VEONIM_DEV) { - // assumes we are also using hyperapp-redux-devtools - // we are gonna steal the modules from ^^^ - const { createStore } = require('redux') - const { composeWithDevTools } = require('redux-devtools-extension') - - const composeEnhancers = composeWithDevTools({ - name: `neovim-state-${stateName}`, - }) - const reducer = (state: any, action: any) => ({ - ...state, - ...action.payload, - }) - const store = createStore(reducer, state, composeEnhancers()) - - store.subscribe(() => Object.assign(stateProxy, store.getState())) - onStateChange((_, key, val) => { - store.dispatch({ type: `SET::${key}`, payload: { [key]: val } }) - }) - } - return { state: stateProxy, watchState, diff --git a/src/render/events.ts b/src/render/events.ts index 1f9d94f5..822986ca 100644 --- a/src/render/events.ts +++ b/src/render/events.ts @@ -1,7 +1,7 @@ import { CursorShape, setCursorColor, setCursorShape } from '../core/cursor' import { forceRegenerateFontAtlas } from '../render/font-texture-atlas' -import { showMessageHistory } from '../components/message-history' -import messages, { MessageKind } from '../components/messages' +import { showMessageHistory } from '../components/nvim/message-history' +import messages, { MessageKind } from '../components/nvim/messages' import { getColorById } from '../render/highlight-attributes' import { normalizeVimMode } from '../support/neovim-utils' import * as windows from '../windows/window-manager' diff --git a/src/tsconfig.json b/src/tsconfig.json index 2ffe200a..54c7ed76 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -1,11 +1,18 @@ { - "exclude": ["node_modules", "test", "xdg_config"], + "exclude": [ + "node_modules", + "test", + "xdg_config", + "components/extensions/legacy", + "dev" + ], "compilerOptions": { "skipLibCheck": true, "target": "esnext", "module": "commonjs", "outDir": "../build", "strict": true, + "jsx": "preserve", "lib": ["esnext", "dom"], "noUnusedLocals": true, "noUnusedParameters": true, diff --git a/src/ui/color-picker.ts b/src/ui/color-picker.ts deleted file mode 100644 index 15403541..00000000 --- a/src/ui/color-picker.ts +++ /dev/null @@ -1,507 +0,0 @@ -import { - hsvToRGB, - rgbToHex, - rgbToHSL, - rgbToHSV, - hexToRGB, - hslToRGB, -} from '../ui/css' -import { minmax, throttle, merge } from '../support/utils' -import { h, app, css } from '../ui/uikit' -import Checkboard from '../ui/checkboard' - -enum ColorMode { - hex, - rgb, - hsl, -} - -export default () => { - let onChangeFn = (_: string) => {} - - const state = { - mode: ColorMode.hex, - hue: 0, - saturation: 0, - value: 0, - alpha: 1, - red: 0, - green: 0, - blue: 0, - } - - const reportChange = throttle((m: S) => { - const useAlpha = m.alpha > 0 && m.alpha < 1 - - if (m.mode === ColorMode.hex) - return onChangeFn(rgbToHex(m.red, m.green, m.blue)) - - if (m.mode === ColorMode.rgb) - return useAlpha - ? onChangeFn(`rgba(${m.red}, ${m.green}, ${m.blue}, ${m.alpha})`) - : onChangeFn(`rgb(${m.red}, ${m.green}, ${m.blue})`) - - if (m.mode === ColorMode.hsl) { - const [h, s, l] = rgbToHSL(m.red, m.green, m.blue) - - return useAlpha - ? onChangeFn(`hsla(${h}, ${s}%, ${l}%, ${m.alpha})`) - : onChangeFn(`hsl(${h}, ${s}%, ${l}%)`) - } - }, 50) - - const actions = { - up: (m: object) => (s: S) => { - const next = { ...s, ...m } - const [red, green, blue] = hsvToRGB(next.hue, next.saturation, next.value) - merge(next, { red, green, blue }) - reportChange(next) - return { ...m, red, green, blue } - }, - } - - type S = typeof state - type A = typeof actions - - const styles = { - overlay: { - height: '100%', - width: '100%', - position: 'absolute', - }, - checkboard: { - position: 'absolute', - background: `url(${Checkboard('#242424', '#3a3a3a', 5)}) center left`, - }, - preview: { - width: '40px', - height: '40px', - }, - slider: { - height: '12px', - width: '100%', - borderRadius: '2px', - }, - sliderHandle: { - position: 'absolute', - height: '16px', - width: '16px', - background: 'var(--background-b5)', - borderRadius: '50%', - boxShadow: '1px 1px 0.3px rgba(0, 0, 0, 0.2)', - }, - arrow: { - color: 'rgba(255, 255, 255, 0.3)', - fontSize: '0.5rem', - }, - modeButton: css((id) => [ - `.${id} { - outline: none; - background: none; - border: 1px solid rgba(255, 255, 255, 0.2); - border-radius: 2px; - padding: 5px; - padding-left: 12px; - padding-right: 12px; - color: rgba(255, 255, 255, 0.2); - }`, - - `.${id}:hover { - border-color: rgba(255, 255, 255, 0.4); - color: rgba(255, 255, 255, 0.4); - }`, - ]), - modeActive: { - color: 'rgba(255, 255, 255, 0.8)', - borderColor: 'rgba(255, 255, 255, 0.5)', - }, - } - - const stats = { - hueSliderWidthMultiplier: 2.11, - alphaSliderWidth: 170, - } - - const updateOnMove = (e: HTMLElement, updateFn: (e: MouseEvent) => void) => { - const onMove = (m: MouseEvent) => updateFn(m) - e.addEventListener( - 'mousedown', - (ev) => (updateFn(ev), e.addEventListener('mousemove', onMove)) - ) - e.addEventListener('mouseup', () => - e.removeEventListener('mousemove', onMove) - ) - } - - const getDimensions = (e: MouseEvent, container: HTMLElement) => ({ - left: - e.pageX - (container.getBoundingClientRect().left + window.pageXOffset), - width: container.clientWidth, - }) - - const calc = { - hue: (e: MouseEvent, container: HTMLElement) => { - const { left, width } = getDimensions(e, container) - - if (left < 0) return 0 - else if (left > width) return 359 - else return (360 * ((left * 100) / width)) / 100 - }, - alpha: (e: MouseEvent, container: HTMLElement) => { - const { left, width } = getDimensions(e, container) - - if (left < 0) return 0 - else if (left > width) return 1 - else return Math.round((left * 100) / width) / 100 - }, - saturation: (e: MouseEvent, container: HTMLElement) => { - const { - width: containerWidth, - height: containerHeight, - } = container.getBoundingClientRect() - let left = - e.pageX - (container.getBoundingClientRect().left + window.pageXOffset) - let top = - e.pageY - (container.getBoundingClientRect().top + window.pageYOffset) - - if (left < 0) left = 0 - else if (left > containerWidth) left = containerWidth - else if (top < 0) top = 0 - else if (top > containerHeight) top = containerHeight - - const saturation = (left * 100) / containerWidth - const bright = -((top * 100) / containerHeight) + 100 - - return { - saturation: minmax(0, 100)(saturation), - value: minmax(0, 100)(bright), - } - }, - } - - const hueSlider = ($: S, a: A) => - h( - 'div', - { - style: { - ...styles.slider, - background: - 'linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)', - }, - onupdate: (e: HTMLElement) => { - stats.hueSliderWidthMultiplier = 360 / e.clientWidth - }, - oncreate: (e: HTMLElement) => { - updateOnMove(e, (ev) => a.up({ hue: calc.hue(ev, e) })) - }, - }, - [ - , - h('div', { - style: { - ...styles.sliderHandle, - transform: `translate(${ - $.hue / stats.hueSliderWidthMultiplier - 8 - }px, -2px)`, - }, - }), - ] - ) - - const alphaSlider = ($: S, a: A) => - h( - 'div', - { - style: { - ...styles.slider, - position: 'relative', - }, - }, - [ - , - h('div', { - style: { - ...styles.slider, - ...styles.checkboard, - }, - }), - - h( - 'div', - { - style: { - ...styles.slider, - position: 'absolute', - background: `linear-gradient(to right, rgba(${$.red}, ${$.green}, ${$.blue}, 0), rgb(${$.red}, ${$.green}, ${$.blue}))`, - }, - onupdate: (e: HTMLElement) => { - stats.alphaSliderWidth = e.clientWidth - }, - oncreate: (e: HTMLElement) => { - updateOnMove(e, (ev) => a.up({ alpha: calc.alpha(ev, e) })) - }, - }, - [ - , - h('div', { - style: { - ...styles.sliderHandle, - transform: `translate(${ - $.alpha * stats.alphaSliderWidth - 8 - }px, -2px)`, - }, - }), - ] - ), - ] - ) - - const view = ($: S, a: A) => - h( - 'div', - { - style: { - borderRadius: '2px', - boxShadow: '0 0 2px rgba(0, 0, 0, .3), 0 4px 8px rgba(0, 0, 0, .3)', - boxSizing: 'initial', - width: '250px', - }, - }, - [ - , - h( - 'div', - { - style: { - height: '125px', - display: 'flex', - overflow: 'hidden', - }, - }, - [ - , - h( - 'div', - { - style: { - position: 'relative', - flex: 1, - }, - oncreate: (e: HTMLElement) => - updateOnMove(e, (ev) => { - const { saturation, value } = calc.saturation(ev, e) - a.up({ saturation, value }) - }), - }, - [ - , - h('div', { - style: { - ...styles.overlay, - background: `hsl(${$.hue}, 100%, 50%)`, - }, - }), - - h('div', { - style: { - ...styles.overlay, - background: - 'linear-gradient(to right, #fff, rgba(255, 255, 255, 0))', - }, - }), - - h('div', { - style: { - ...styles.overlay, - background: - 'linear-gradient(to top, #000, rgba(0, 0, 0, 0))', - }, - }), - - h( - 'div', - { - style: { - position: 'absolute', - top: `${-$.value + 100}%`, - left: `${$.saturation}%`, - cursor: 'default', - }, - }, - [ - , - h('div', { - style: { - width: '12px', - height: '12px', - borderRadius: '50%', - transform: 'translate(-6px, -6px)', - boxShadow: 'rgb(255, 255, 255) 0px 0px 0px 1px inset', - }, - }), - ] - ), - ] - ), - ] - ), - - h( - 'div', - { - style: { - background: 'var(--background-10)', - display: 'flex', - padding: '15px', - }, - }, - [ - , - h( - 'div', - { - style: { - display: 'flex', - flex: 1, - }, - }, - [ - , - h( - 'div', - { - style: { - ...styles.preview, - position: 'relative', - }, - }, - [ - , - h('div', { - style: { - ...styles.preview, - borderRadius: '50%', - ...styles.checkboard, - }, - }), - - h('div', { - style: { - ...styles.preview, - borderRadius: '50%', - position: 'absolute', - background: `rgba(${$.red}, ${$.green}, ${$.blue}, ${$.alpha})`, - }, - }), - ] - ), - - h( - 'div', - { - style: { - flex: 1, - display: 'flex', - marginLeft: '10px', - flexFlow: 'column', - justifyContent: 'space-between', - }, - }, - [, hueSlider($, a), alphaSlider($, a)] - ), - ] - ), - ] - ), - - h( - 'div', - { - style: { - background: 'var(--background-10)', - display: 'flex', - padding: '15px', - paddingTop: '10px', - justifyContent: 'space-around', - }, - }, - [ - , - h( - `button.${styles.modeButton}`, - { - style: $.mode === ColorMode.hex && styles.modeActive, - onclick: () => a.up({ mode: ColorMode.hex }), - }, - 'HEX' - ), - - h( - `button.${styles.modeButton}`, - { - style: $.mode === ColorMode.rgb && styles.modeActive, - onclick: () => a.up({ mode: ColorMode.rgb }), - }, - 'RGB' - ), - - h( - `button.${styles.modeButton}`, - { - style: $.mode === ColorMode.hsl && styles.modeActive, - onclick: () => a.up({ mode: ColorMode.hsl }), - }, - 'HSL' - ), - ] - ), - ] - ) - - const element = document.createElement('div') - const ui = app({ name: 'dank-memes', state, actions, view, element }) - - const onChange = (fn: (color: string) => void) => (onChangeFn = fn) - - const setRGB = (red: number, green: number, blue: number, alpha?: number) => { - const [hue, saturation, value] = rgbToHSV(red, green, blue) - ui.up({ - mode: ColorMode.rgb, - hue, - saturation, - value, - red, - green, - blue, - alpha, - }) - } - - const setHex = (hex: string) => { - const [red, green, blue] = hexToRGB(hex) - const [hue, saturation, value] = rgbToHSV(red, green, blue) - ui.up({ mode: ColorMode.hex, hue, saturation, value, red, green, blue }) - } - - const setHSL = ( - hue: number, - saturation: number, - lightness: number, - alpha?: number - ) => { - const [red, green, blue] = hslToRGB(hue, saturation, lightness) - const [h, s, value] = rgbToHSV(red, green, blue) - ui.up({ - mode: ColorMode.hsl, - hue: h, - saturation: s, - value, - red, - green, - blue, - alpha, - }) - } - - return { setRGB, setHex, setHSL, element, onChange } -} diff --git a/src/ui/color-picker.tsx b/src/ui/color-picker.tsx new file mode 100644 index 00000000..e9d617d8 --- /dev/null +++ b/src/ui/color-picker.tsx @@ -0,0 +1,439 @@ +import { + hsvToRGB, + rgbToHex, + rgbToHSL, + rgbToHSV, + hexToRGB, + hslToRGB, +} from '../ui/css' +import { minmax, throttle, merge } from '../support/utils' +import { css } from '../ui/uikit' +import Checkboard from '../ui/checkboard' +import { render } from 'inferno' + +enum ColorMode { + hex, + rgb, + hsl, +} + +export default () => { + let onChangeFn = (_: string) => {} + + let state = { + mode: ColorMode.hex, + hue: 0, + saturation: 0, + value: 0, + alpha: 1, + red: 0, + green: 0, + blue: 0, + } + + const reportChange = throttle((m: S) => { + const useAlpha = m.alpha > 0 && m.alpha < 1 + + if (m.mode === ColorMode.hex) + return onChangeFn(rgbToHex(m.red, m.green, m.blue)) + + if (m.mode === ColorMode.rgb) + return useAlpha + ? onChangeFn(`rgba(${m.red}, ${m.green}, ${m.blue}, ${m.alpha})`) + : onChangeFn(`rgb(${m.red}, ${m.green}, ${m.blue})`) + + if (m.mode === ColorMode.hsl) { + const [h, s, l] = rgbToHSL(m.red, m.green, m.blue) + + return useAlpha + ? onChangeFn(`hsla(${h}, ${s}%, ${l}%, ${m.alpha})`) + : onChangeFn(`hsl(${h}, ${s}%, ${l}%)`) + } + }, 50) + + type S = typeof state + + const styles = { + overlay: { + height: '100%', + width: '100%', + position: 'absolute', + } as CSSProperties, + checkboard: { + position: 'absolute', + background: `url(${Checkboard('#242424', '#3a3a3a', 5)}) center left`, + } as CSSProperties, + preview: { + width: '40px', + height: '40px', + } as CSSProperties, + slider: { + height: '12px', + width: '100%', + 'border-radius': '2px', + } as CSSProperties, + sliderHandle: { + position: 'absolute', + height: '16px', + width: '16px', + background: 'var(--background-b5)', + 'border-radius': '50%', + 'box-shadow': '1px 1px 0.3px rgba(0, 0, 0, 0.2)', + } as CSSProperties, + arrow: { + color: 'rgba(255, 255, 255, 0.3)', + 'font-size': '0.5rem', + } as CSSProperties, + modeButton: css((id) => [ + `.${id} { + outline: none; + background: none; + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 2px; + padding: 5px; + padding-left: 12px; + padding-right: 12px; + color: rgba(255, 255, 255, 0.2); + }`, + + `.${id}:hover { + border-color: rgba(255, 255, 255, 0.4); + color: rgba(255, 255, 255, 0.4); + }`, + ]), + modeActive: { + color: 'rgba(255, 255, 255, 0.8)', + 'border-color': 'rgba(255, 255, 255, 0.5)', + } as CSSProperties, + } + + const stats = { + hueSliderWidthMultiplier: 2.11, + alphaSliderWidth: 170, + } + + const updateOnMove = (e: HTMLElement, updateFn: (e: MouseEvent) => void) => { + const onMove = (m: MouseEvent) => updateFn(m) + e.addEventListener( + 'mousedown', + (ev) => (updateFn(ev), e.addEventListener('mousemove', onMove)) + ) + e.addEventListener('mouseup', () => + e.removeEventListener('mousemove', onMove) + ) + } + + const getDimensions = (e: MouseEvent, container: HTMLElement) => ({ + left: + e.pageX - (container.getBoundingClientRect().left + window.pageXOffset), + width: container.clientWidth, + }) + + const calc = { + hue: (e: MouseEvent, container: HTMLElement) => { + const { left, width } = getDimensions(e, container) + + if (left < 0) return 0 + else if (left > width) return 359 + else return (360 * ((left * 100) / width)) / 100 + }, + alpha: (e: MouseEvent, container: HTMLElement) => { + const { left, width } = getDimensions(e, container) + + if (left < 0) return 0 + else if (left > width) return 1 + else return Math.round((left * 100) / width) / 100 + }, + saturation: (e: MouseEvent, container: HTMLElement) => { + const { + width: containerWidth, + height: containerHeight, + } = container.getBoundingClientRect() + let left = + e.pageX - (container.getBoundingClientRect().left + window.pageXOffset) + let top = + e.pageY - (container.getBoundingClientRect().top + window.pageYOffset) + + if (left < 0) left = 0 + else if (left > containerWidth) left = containerWidth + else if (top < 0) top = 0 + else if (top > containerHeight) top = containerHeight + + const saturation = (left * 100) / containerWidth + const bright = -((top * 100) / containerHeight) + 100 + + return { + saturation: minmax(0, 100)(saturation), + value: minmax(0, 100)(bright), + } + }, + } + + const WhyDiv = (props: any) =>
{props.children}
+ + let hueSliderEl: HTMLElement | undefined = undefined + const HueSlider = ($: S) => ( + { + hueSliderEl = e + updateOnMove(e, (ev) => up({ hue: calc.hue(ev, e) })) + }} + onComponentDidUpdate={(_lastProps: any, _nextProps: any) => { + stats.hueSliderWidthMultiplier = 360 / hueSliderEl!.clientWidth + }} + > +
+ + ) + + let alphaSliderEl: HTMLElement | undefined = undefined + const AlphaSlider = ($: S) => ( +
+
+ { + stats.alphaSliderWidth = alphaSliderEl!.clientWidth + }} + onComponentDidMount={(e: HTMLElement) => { + alphaSliderEl = e + updateOnMove(e, (ev) => up({ alpha: calc.alpha(ev, e) })) + }} + > +
+ +
+ ) + + const ColorPicker = ($: S) => ( +
+
+ { + updateOnMove(e, (ev) => { + const { saturation, value } = calc.saturation(ev, e) + up({ saturation, value }) + }) + }} + > +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ + +
+
+
+ +
+ + + + + +
+
+ ) + + const element = document.createElement('div') + const assignStateAndRender = (newState: any) => ( + Object.assign(state, newState), render(, element) + ) + + const up = (m: object) => { + const next = { ...state, ...m } + const [red, green, blue] = hsvToRGB(next.hue, next.saturation, next.value) + merge(next, { red, green, blue }) + reportChange(next) + assignStateAndRender({ ...m, red, green, blue }) + } + + const onChange = (fn: (color: string) => void) => (onChangeFn = fn) + + const setRGB = (red: number, green: number, blue: number, alpha?: number) => { + const [hue, saturation, value] = rgbToHSV(red, green, blue) + up({ + mode: ColorMode.rgb, + hue, + saturation, + value, + red, + green, + blue, + alpha, + }) + } + + const setHex = (hex: string) => { + const [red, green, blue] = hexToRGB(hex) + const [hue, saturation, value] = rgbToHSV(red, green, blue) + up({ mode: ColorMode.hex, hue, saturation, value, red, green, blue }) + } + + const setHSL = ( + hue: number, + saturation: number, + lightness: number, + alpha?: number + ) => { + const [red, green, blue] = hslToRGB(hue, saturation, lightness) + const [h, s, value] = rgbToHSV(red, green, blue) + up({ + mode: ColorMode.hsl, + hue: h, + saturation: s, + value, + red, + green, + blue, + alpha, + }) + } + + return { setRGB, setHex, setHSL, element, onChange } +} diff --git a/src/ui/css.ts b/src/ui/css.ts index 55d30b79..54a4b5c1 100644 --- a/src/ui/css.ts +++ b/src/ui/css.ts @@ -1,18 +1,18 @@ export const paddingVH = (vertical: number, horizontal: number) => ({ - paddingLeft: `${vertical}px`, - paddingRight: `${vertical}px`, - paddingTop: `${horizontal}px`, - paddingBottom: `${horizontal}px`, + 'padding-left': `${vertical}px`, + 'padding-right': `${vertical}px`, + 'padding-top': `${horizontal}px`, + 'padding-bottom': `${horizontal}px`, }) export const paddingH = (amount: number) => ({ - paddingTop: `${amount}px`, - paddingBottom: `${amount}px`, + 'padding-top': `${amount}px`, + 'padding-bottom': `${amount}px`, }) export const paddingV = (amount: number) => ({ - paddingLeft: `${amount}px`, - paddingRight: `${amount}px`, + 'padding-left': `${amount}px`, + 'padding-right': `${amount}px`, }) export const translate = (x: number | string, y: number | string) => diff --git a/src/ui/styles.ts b/src/ui/styles.ts index 62784242..5bb56038 100644 --- a/src/ui/styles.ts +++ b/src/ui/styles.ts @@ -65,7 +65,7 @@ const refreshColors = ({ fg, bg }: { fg: string; bg: string }) => { .then(({ foreground }) => foreground ? setVar(varName, foreground) : null ) - .catch((error) => console.warn('Error: ', error)) + .catch((_err) => {}) // TODO(smolck): Maybe handle? Not really necessary probably . . . getColorAndSetVar('uvnKeyword', 'keyword') getColorAndSetVar('uvnBuiltin', 'builtin') @@ -102,17 +102,17 @@ export const colors = { export const badgeStyle = { ...paddingV(4), - borderRadius: '2px', + 'border-radius': '2px', background: cvar('background-30'), } export const docStyle = { ...paddingVH(8, 6), overflow: 'visible', - whiteSpace: 'normal', - fontSize: '0.9rem', color: cvar('foreground-40'), background: cvar('background-45'), + 'white-space': 'normal', + 'font-size': '0.9rem', } export const resetMarkdownHTMLStyle = css((id) => [ diff --git a/src/ui/uikit.ts b/src/ui/uikit.ts index f3d75dd8..fd984d3c 100644 --- a/src/ui/uikit.ts +++ b/src/ui/uikit.ts @@ -1,14 +1,6 @@ -import { ActionsType, View } from 'hyperapp' import { showCursor, hideCursor } from '../core/cursor' -import { specs as titleSpecs } from '../core/title' -import * as dispatch from '../messaging/dispatch' -import { merge, uuid } from '../support/utils' -import hyperscript from '../ui/hyperscript' +import { uuid } from '../support/utils' import * as viminput from '../core/input' -// using our own version of hyperapp patched to fix removeChild errors -const { app: makeApp, h: makeHyperscript } = require('../ui/hyperapp') - -export const h = hyperscript(makeHyperscript) export const css = (builder: (classname: string) => string[]): string => { const id = `sc-${uuid()}` @@ -20,21 +12,6 @@ export const css = (builder: (classname: string) => string[]): string => { return id } -const pluginsContainer = document.getElementById('plugins') as HTMLElement -merge(pluginsContainer.style, { - position: 'absolute', - display: 'flex', - width: '100vw', - zIndex: 420, // vape naysh yall - // TODO: 24px for statusline. do it better - // TODO: and title. bruv do i even know css? - height: `calc(100vh - 24px - ${titleSpecs.height}px)`, -}) - -dispatch.sub('window.change', () => { - pluginsContainer.style.height = `calc(100vh - 24px - ${titleSpecs.height}px)` -}) - export const vimFocus = () => { setImmediate(() => viminput.focus()) showCursor() @@ -44,42 +21,3 @@ export const vimBlur = () => { viminput.blur() hideCursor() } - -const prepareContainerElement = (name: string) => { - const el = document.createElement('div') - el.setAttribute('id', name) - merge(el.style, { - position: 'absolute', - width: '100%', - height: '100%', - }) - - pluginsContainer.appendChild(el) - return el -} - -interface App { - name: string - state: StateT - actions: ActionsType - view: View - element?: HTMLElement -} - -/** create app for cultural learnings of hyperapp for make benefit of glorious application veonim */ -export const app = ({ - state, - actions, - view, - element, - name, -}: App): ActionsT => { - const containerElement = element || prepareContainerElement(name) - - if (process.env.VEONIM_DEV) { - const devtools = require('@deomitrus/hyperapp-redux-devtools') - return devtools(makeApp, { name })(state, actions, view, containerElement) - } - - return makeApp(state, actions, view, containerElement) -} diff --git a/src/windows/nameplate.ts b/src/windows/nameplate.ts deleted file mode 100644 index d3ba20b3..00000000 --- a/src/windows/nameplate.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { size } from '../core/workspace' -import * as Icon from 'hyperapp-feather' -import { uuid } from '../support/utils' -import { makel } from '../ui/vanilla' -import { h, app } from '../ui/uikit' -import { cvar } from '../ui/css' - -export interface NameplateState { - name?: string - dir?: string - active?: boolean - modified?: boolean - terminal?: boolean - termAttached?: boolean - termFormat?: string -} - -type S = NameplateState - -export default () => { - const element = makel({ - display: 'flex', - overflow: 'hidden', - height: `${size.nameplateHeight}px`, - minHeight: `${size.nameplateHeight}px`, - }) - - const state: NameplateState = { - name: '', - dir: '', - active: false, - modified: false, - terminal: false, - termAttached: false, - termFormat: '', - } - - const actions = { updateData: (data: S) => data } - type A = typeof actions - - const view = ($: S) => - h( - 'div', - { - style: { - display: 'flex', - paddingLeft: '10px', - paddingRight: '10px', - alignItems: 'center', - maxWidth: 'calc(100% - 20px)', - background: cvar('background'), - }, - }, - [ - , - $.terminal && - h(Icon.Terminal, { - color: cvar('foreground-30'), - style: { - fontSize: '1.2rem', - display: 'flex', - marginRight: '8px', - alignItems: 'center', - }, - }), - - h( - 'div', - { - style: { - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - // TODO: need to contrast, not brighten - filter: `brightness(${$.active ? 130 : 90}%)`, - }, - }, - [ - , - $.dir && - h( - 'span', - { - style: { - color: cvar('foreground-30'), - marginRight: '1px', - }, - }, - `${$.dir}/` - ), - - h( - 'span', - { - style: { - color: cvar('foreground-50'), - }, - }, - $.name || '[No Name]' - ), - ] - ), - - $.modified && - h('div', { - style: { - width: '0.5rem', - height: '0.5rem', - marginTop: '2px', - marginLeft: '8px', - borderRadius: '50%', - background: cvar('foreground-50'), - }, - }), - - $.termAttached && - h(Icon.Eye, { - color: cvar('foreground-40'), - style: { - marginLeft: '15px', - marginRight: '4px', - alignItems: 'center', - }, - }), - - $.termAttached && - h( - 'div', - { - style: { - color: cvar('foreground-50'), - fontSize: '0.8rem', - }, - }, - $.termFormat - ), - ] - ) - - const ui = app({ - name: `nameplate-${uuid()}`, - state, - actions, - view, - element, - }) - const update = (data: S) => ui.updateData(data) - - return { element, update } -} diff --git a/src/windows/nameplate.tsx b/src/windows/nameplate.tsx new file mode 100644 index 00000000..b2959b0d --- /dev/null +++ b/src/windows/nameplate.tsx @@ -0,0 +1,121 @@ +import { size } from '../core/workspace' +import { uuid } from '../support/utils' +import { makel } from '../ui/vanilla' +import { cvar } from '../ui/css' +import Icon from '../components/icon' +import { render } from 'inferno' + +export interface NameplateState { + name?: string + dir?: string + active?: boolean + modified?: boolean + terminal?: boolean + termAttached?: boolean + termFormat?: string +} + +type S = NameplateState + +export default () => { + const element = makel({ + display: 'flex', + overflow: 'hidden', + height: `${size.nameplateHeight}px`, + minHeight: `${size.nameplateHeight}px`, + }) + + let state: NameplateState = { + name: '', + dir: '', + active: false, + modified: false, + terminal: false, + termAttached: false, + termFormat: '', + } + + const feather = require('feather-icons') + const Nameplate = ($: S) => ( +
+ {$.terminal && ( + + )} + +
+ {$.dir && ( + + {$.dir}/ + + )} + + {$.name || '[No Name]'} + +
+ + {$.modified && ( +
+ )} + + {$.termAttached && ( + + )} + + {$.termAttached && ( +
+ {$.termFormat} +
+ )} +
+ ) + + const update = (data: S) => ( + Object.assign(state, data), render(, element) + ) + + return { element, update } +} diff --git a/tools/build.js b/tools/build.js index 94b8e524..a9ac594d 100644 --- a/tools/build.js +++ b/tools/build.js @@ -54,8 +54,8 @@ require.main === module && go(async () => { $`cleaning build folder` await fs.emptyDir(fromRoot('build')) - await run('ttsc -p src/tsconfig.json') await copyAll() + await run("babel --extensions '.ts,.tsx' src -d build") }) module.exports = { paths, copy, copyAll } diff --git a/tools/start.js b/tools/start.js index 09d60f53..2b34afba 100644 --- a/tools/start.js +++ b/tools/start.js @@ -1,7 +1,7 @@ 'use strict' -const { $, go, run, fromRoot, createTask } = require('./runner') -const { copy, copyAll } = require('./build') +const { $, go, run, fromRoot } = require('./runner') +const { copyAll } = require('./build') const fs = require('fs-extra') go(async () => { @@ -9,18 +9,8 @@ go(async () => { await fs.emptyDir(fromRoot('build')) await copyAll() - const tsc = createTask() - - run('tsc -p src/tsconfig.json --watch --preserveWatchOutput', { - outputMatch: 'watching for file changes', - onOutputMatch: async () => { - copy.index() - copy.processExplorer() - tsc.done() - }, - }) - - await tsc.promise + $`running babel stuff` + await run("babel --extensions '.ts,.tsx' src -d build") run('electron build/bootstrap/main.js', { shh: true,