diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 6253f0a4..c697e09a 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -3,11 +3,11 @@ name: 💬 Questions / Help about: If you have questions, please check our documents first --- -Before you submit an question we recommend you to check out the [DOCUMENT](https://github.com/jdneo/vscode-leetcode/blob/master/README.md) first. +Before you submit an question we recommend you to check out the [DOCUMENT](https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/README.md) first. You can also find more information in: -- [TROUBLESHOOTING](https://github.com/jdneo/vscode-leetcode/wiki/Troubleshooting) -- [FAQ](https://github.com/jdneo/vscode-leetcode/wiki/FAQ) +- [TROUBLESHOOTING](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/Troubleshooting) +- [FAQ](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/FAQ) ## 💬 Questions and Help diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..dd9a1c24 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,50 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + linux: + name: Linux + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v2 + + - name: Setup Node.js environment + uses: actions/setup-node@v2 + with: + node-version: 14 + + - name: Install Node.js modules + run: npm install + + - name: Lint + run: npm run lint + + - name: VSCE Packge + run: npx vsce package + + windows: + name: Windows + runs-on: windows-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v2 + + - name: Setup Node.js environment + uses: actions/setup-node@v2 + with: + node-version: 14 + + - name: Install Node.js modules + run: npm install + + - name: Lint + run: npm run lint + + - name: VSCE Packge + run: npx vsce package diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6bbae841..00000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: node_js - -node_js: - - 'lts/*' - -before_install: - - if [ $TRAVIS_OS_NAME == "linux" ]; then - export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0; - sh -e /etc/init.d/xvfb start; - sleep 3; - fi - -install: - - npm install -g vsce - - npm install - -script: - - npm run lint - - vsce package diff --git a/.vscode/settings.json b/.vscode/settings.json index a2d0a8b1..5e5ca483 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "editor.formatOnSave": true, + "editor.formatOnSave": false, "editor.insertSpaces": true, "editor.tabSize": 4, "files.insertFinalNewline": true, @@ -10,5 +10,8 @@ ".vscode-test": true }, "tslint.autoFixOnSave": true, - "tslint.ignoreDefinitionFiles": true -} \ No newline at end of file + "tslint.ignoreDefinitionFiles": true, + "prettier.tabWidth": 4, + "prettier.useTabs": false, + "prettier.printWidth": 150 +} diff --git a/.vscodeignore b/.vscodeignore index 8cdceec0..7a04907d 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -5,7 +5,6 @@ test/** src/** **/*.map .gitignore -.travis.yml package-lock.json tsconfig.json tslint.json diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index bddc5bd5..6c7758be 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -2,16 +2,23 @@ A big thanks to the following individuals for contributing: -- [@TsFreddie](https://github.com/TsFreddie) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=TsFreddie) -- [@ntt2k](https://github.com/ntt2k) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=ntt2k) -- [@purocean](https://github.com/purocean) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=purocean) -- [@Xeonacid](https://github.com/Xeonacid) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=Xeonacid) -- [@Himself65](https://github.com/Himself65) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=Himself65) -- [@Vigilans](https://github.com/Vigilans) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=Vigilans) -- [@ringcrl](https://github.com/ringcrl) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=ringcrl) -- [@pujiaxun](https://github.com/pujiaxun) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=pujiaxun) -- [@edvardchen](https://github.com/edvardchen) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=edvardchen) -- [@poppinlp](https://github.com/poppinlp) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=poppinlp) -- [@xuzaixian](https://github.com/xuzaixian) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=xuzaixian) -- [@ZainChen](https://github.com/ZainChen) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=ZainChen) -- [@houtianze](https://github.com/houtianze) — [contributions](https://github.com/jdneo/vscode-leetcode/commits?author=houtianze) +- [@JIEJIAN21](https://github.com/JIEJIAN21) - thanks for logo and icon design +- [@TsFreddie](https://github.com/TsFreddie) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=TsFreddie) +- [@ntt2k](https://github.com/ntt2k) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=ntt2k) +- [@purocean](https://github.com/purocean) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=purocean) +- [@Xeonacid](https://github.com/Xeonacid) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=Xeonacid) +- [@Himself65](https://github.com/Himself65) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=Himself65) +- [@Vigilans](https://github.com/Vigilans) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=Vigilans) +- [@ringcrl](https://github.com/ringcrl) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=ringcrl) +- [@pujiaxun](https://github.com/pujiaxun) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=pujiaxun) +- [@edvardchen](https://github.com/edvardchen) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=edvardchen) +- [@poppinlp](https://github.com/poppinlp) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=poppinlp) +- [@xuzaixian](https://github.com/xuzaixian) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=xuzaixian) +- [@ZainChen](https://github.com/ZainChen) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=ZainChen) +- [@houtianze](https://github.com/houtianze) — [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=houtianze) +- [@magic-akari](https://github.com/magic-akari) - [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=magic-akari) +- [@SF-Zhou](https://github.com/SF-Zhou) - [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=SF-Zhou) +- [@fuafa](https://github.com/fuafa) - [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=fuafa) +- [@iFun](https://github.com/iFun) - [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=iFun) +- [@hologerry](https://github.com/hologerry) - [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=hologerry) +- [@yihong0618](https://github.com/yihong0618) - [contributions](https://github.com/LeetCode-OpenSource/vscode-leetcode/commits?author=yihong0618) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47ea1e63..b9d7d46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,86 +3,220 @@ All notable changes to the "leetcode" extension will be documented in this file. Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. +## [0.18.4] +### Added +- change graphql path + +## [0.18.3] +### Added +- re-add cookie-based login method [PR#969](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/969) + +## [0.18.2] +### Fixed +- fix login issue on VS Code Insiders [PR#968](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/968) + +## [0.18.1] +### Changed +- change login way and add tracking logic option [PR#944](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/944) + +## [0.18.0] +### Added +- Add `star` command in shortcuts [PR#601](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/601) +- Add an option to disable endpoint translation [#389](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/389) + +### Changed +- LeetCode actions are moved into sub-menu: `LeetCode` in the editor context menu. [PR#712](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/712) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.18.0+is%3Aclosed+label%3Abug) + +## [0.17.0] +### Added +- Add TypeScript support [#560](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/560) + +### Changed +- Update the UI resources [PR#561](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/561) + +## [0.16.2] +### Added +- New Category: `Concurrency` [CLI#42](https://github.com/leetcode-tools/leetcode-cli/pull/42) +- New configuration to better configure how to show the description [#310](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/310) + +### Removed +- Removed the deprecated setting `leetcode.enableShortcuts` [PR#520](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/520) +- Removed the deprecated setting `leetcode.outputFolder` [PR#521](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/521) + +## [0.16.1] +### Added +- Can show the problem in current workspace even if it's not a LeetCode workspace [#373](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/373) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.16.1+is%3Aclosed+label%3Abug) + +## [0.16.0] +### Added +- Support GitHub login and LinkedIn login [PR#496](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/496) + +## [0.15.8] +### Added +- Add a new command `Sign In by Cookie` to workaround the issue that [users cannot login to LeetCode](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478). Please check the [workaround steps](https://github.com/LeetCode-OpenSource/vscode-leetcode/tree/master#%EF%B8%8F-attention-%EF%B8%8F--workaround-to-login-to-leetcode-endpoint) for more details! + +### Changed +- Update the explorer icons to be align with the VS Code design [#460](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/460) + +## [0.15.7] +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.7+is%3Aclosed+label%3Abug) + +## [0.15.6] +### Added +- Add a link to the solution page [#424](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/424) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.6+is%3Aclosed+label%3Abug) + +## [0.15.5] +### Added +- Add a link to the discussion page [#420](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/420) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.5+is%3Aclosed+label%3Abug) + +## [0.15.4] +### Added +- Add a new setting `leetcode.filePath`. Now users can use this setting to dynamicly specify the relative folder name and file name. [#PR380](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/380) + +### Fixed +- Missing language `Rust` in the supported language list. [#PR412](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/412) +- Cannot show output when the answer is wrong. [#414](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/414) + +## [0.15.3] +### Added +- Support `Pick One` [#263](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/263) +- Support toggling the favorite problems [#378](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/378) + +### Changed +- Update the activity bar icon [#395](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/263) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.3+is%3Aclosed+label%3Abug) + +## [0.15.2] +### Added +- Prompt to open the workspace for LeetCode [#130](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/130) +- Support deleting sessions [#198](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/130) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.2+is%3Aclosed+label%3Abug) + +## [0.15.1] +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.1+is%3Aclosed+label%3Abug) + +## [0.15.0] +### Added +- Auto refresh the explorer after submitting [#91](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/91) +- Add a editor shortcut `Description` to show the problem description [#286](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/286) +- Support customizing the shortcuts in editor [#335](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/335) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.15.0+is%3Aclosed+label%3Abug) + +## [0.14.3] +### Added +- Support interpolation for `leetcode.outputFolder` settings [#151](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/151) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.14.3+label%3Abug) + +## [0.14.2] +### Added +- Add the `All` category in the LeetCode Explorer [#184](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/184) +- Add shortcuts for `Show top voted solution` [#269](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/269) + +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+is%3Aclosed+label%3Abug+milestone%3A0.14.2) + ## [0.14.1] -## Added -- Add setting `leetcode.showCommentDescription` to specify whether including the problem description in comments or not [#287](https://github.com/jdneo/vscode-leetcode/issues/287) +### Added +- Add setting `leetcode.showCommentDescription` to specify whether including the problem description in comments or not [#287](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/287) ## [0.14.0] -## Added -- Add setting `leetcode.enableShortcuts` to specify whether to show the submit/test shortcuts in editor [#146](https://github.com/jdneo/vscode-leetcode/issues/146) -- Add `Like` and `Dislike` counts in the problem description [#267](https://github.com/jdneo/vscode-leetcode/issues/267) +### Added +- Add setting `leetcode.enableShortcuts` to specify whether to show the submit/test shortcuts in editor [#146](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/146) +- Add `Like` and `Dislike` counts in the problem description [#267](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/267) -## Changed +### Changed - Improve the `Preview`, `Result` and `Solution` views -## Fixed -[Bugs fixed](https://github.com/jdneo/vscode-leetcode/issues?q=is%3Aissue+label%3Abug+is%3Aclosed+milestone%3A0.14.0) +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+label%3Abug+is%3Aclosed+milestone%3A0.14.0) ## [0.13.3] -## Fixed +### Fixed - Fix the bug that the extension cannot be activated ## [0.13.2] -## Added -- Add a setting `leetcode.enableStatusBar` to specify whether the LeetCode status bar will be shown or not [#156](https://github.com/jdneo/vscode-leetcode/issues/156) -- Add a setting `leetcode.nodePath` to specify the `Node.js` executable path [#227](https://github.com/jdneo/vscode-leetcode/issues/227) +### Added +- Add a setting `leetcode.enableStatusBar` to specify whether the LeetCode status bar will be shown or not [#156](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/156) +- Add a setting `leetcode.nodePath` to specify the `Node.js` executable path [#227](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/227) -## Changed -- Update the activity bar icon, See: [#225](https://github.com/jdneo/vscode-leetcode/pull/225) +### Changed +- Update the activity bar icon, See: [#225](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/225) -## Fixed -[Bugs fixed](https://github.com/jdneo/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.13.2+is%3Aclosed+label%3Abug) +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.13.2+is%3Aclosed+label%3Abug) ## [0.13.1] -## Fixed -[Bugs fixed](https://github.com/jdneo/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.13.1+is%3Aclosed+label%3Abug) +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+milestone%3A0.13.1+is%3Aclosed+label%3Abug) ## [0.13.0] -## Added -- Preview the problem description [#131](https://github.com/jdneo/vscode-leetcode/issues/131) -- Show top voted solution [#193](https://github.com/jdneo/vscode-leetcode/pull/193) -- Add `collapse all` for the explorer [#197](https://github.com/jdneo/vscode-leetcode/pull/197) +### Added +- Preview the problem description [#131](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/131) +- Show top voted solution [#193](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/193) +- Add `collapse all` for the explorer [#197](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/197) -## Fixed -[Bugs fixed](https://github.com/jdneo/vscode-leetcode/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.13.0+label%3Abug) +### Fixed +[Bugs fixed](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.13.0+label%3Abug) ## [0.12.0] -## Added -- Add new command `LeetCode: Switch Default Language` to support switching the default language [#115](https://github.com/jdneo/vscode-leetcode/issues/115) -- Support `PHP` and `Rust` ([#83](https://github.com/jdneo/vscode-leetcode/issues/83), [#103](https://github.com/jdneo/vscode-leetcode/issues/103)) +### Added +- Add new command `LeetCode: Switch Default Language` to support switching the default language [#115](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/115) +- Support `PHP` and `Rust` ([#83](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/83), [#103](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/103)) -## Fixed -- Cannot retrieve time and memory result [#105](https://github.com/jdneo/vscode-leetcode/issues/105) -- Power operator displays in a wrong way [#74](https://github.com/jdneo/vscode-leetcode/issues/74) +### Fixed +- Cannot retrieve time and memory result [#105](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/105) +- Power operator displays in a wrong way [#74](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/74) ## [0.11.0] -## Added -- Add new setting: `leetcode.outputFolder` to customize the sub-directory to save the files generated by 'Show Problem' [#119](https://github.com/jdneo/vscode-leetcode/issues/119) -- Add tooltips for sub-category nodes in LeetCode Explorer [#143](https://github.com/jdneo/vscode-leetcode/pull/143) +### Added +- Add new setting: `leetcode.outputFolder` to customize the sub-directory to save the files generated by 'Show Problem' [#119](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/119) +- Add tooltips for sub-category nodes in LeetCode Explorer [#143](https://github.com/LeetCode-OpenSource/vscode-leetcode/pull/143) -## Changed -- Now when triggering 'Show Problem', the extension will not generate a new file if it already exists [#59](https://github.com/jdneo/vscode-leetcode/issues/59) +### Changed +- Now when triggering 'Show Problem', the extension will not generate a new file if it already exists [#59](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/59) -## Fixed -- Log in timeout when proxy is enabled [#117](https://github.com/jdneo/vscode-leetcode/issues/117) +### Fixed +- Log in timeout when proxy is enabled [#117](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/117) ## [0.10.2] -## Fixed -- Test cases cannot have double quotes [#60](https://github.com/jdneo/vscode-leetcode/issues/60) +### Fixed +- Test cases cannot have double quotes [#60](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/60) ## [0.10.1] -## Changed +### Changed - Refine the README page. ## [0.10.0] -## Added -- Add an extension setting to hide solved problems [#95](https://github.com/jdneo/vscode-leetcode/issues/95) -- Support categorize problems by company, tag, difficulty and favorite [#67](https://github.com/jdneo/vscode-leetcode/issues/67) +### Added +- Add an extension setting to hide solved problems [#95](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/95) +- Support categorize problems by company, tag, difficulty and favorite [#67](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/67) ## [0.9.0] ### Changed -- Improve the experience of switching endpoint [#85](https://github.com/jdneo/vscode-leetcode/issues/85) -- Use web view to show the result page [#76](https://github.com/jdneo/vscode-leetcode/issues/76) +- Improve the experience of switching endpoint [#85](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/85) +- Use web view to show the result page [#76](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/76) ## [0.8.2] @@ -90,7 +224,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how - Add Code Lens for submitting the answer to LeetCode ### Fixed -- Fix the bug that the extension could not automatically sign in [#72](https://github.com/jdneo/vscode-leetcode/issues/72) +- Fix the bug that the extension could not automatically sign in [#72](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/72) ## [0.8.1] ### Changed @@ -98,67 +232,67 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## [0.8.0] ### Added -- Support LeetCode CN [#50](https://github.com/jdneo/vscode-leetcode/issues/50) -- Support Windows Subsystem for Linux [#47](https://github.com/jdneo/vscode-leetcode/issues/47) +- Support LeetCode CN [#50](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/50) +- Support Windows Subsystem for Linux [#47](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/47) ## [0.7.0] ### Added -- Add spinner when submitting code [#43](https://github.com/jdneo/vscode-leetcode/issues/43) +- Add spinner when submitting code [#43](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/43) ## [0.6.1] ### Added -- Add Sign in action into LeetCode Explorer title area [#25](https://github.com/jdneo/vscode-leetcode/issues/25) +- Add Sign in action into LeetCode Explorer title area [#25](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/25) ## [0.6.0] ### Changed -- Move LeetCode explorer into activity bar [#39](https://github.com/jdneo/vscode-leetcode/issues/39) +- Move LeetCode explorer into activity bar [#39](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/39) ### Added -- Support trigger test & submit in the editor [#37](https://github.com/jdneo/vscode-leetcode/issues/37) +- Support trigger test & submit in the editor [#37](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/37) ### Fixed -- Fix the bug that cannot show problem [#41](https://github.com/jdneo/vscode-leetcode/issues/41) +- Fix the bug that cannot show problem [#41](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/41) ## [0.5.1] ### Fixed -- Fix the bug when user's path contains white spaces [#34](https://github.com/jdneo/vscode-leetcode/issues/34) +- Fix the bug when user's path contains white spaces [#34](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/34) ## [0.5.0] ### Added -- Support submit and test solution files from the file explorer in VS Code ([#24](https://github.com/jdneo/vscode-leetcode/issues/24), [#26](https://github.com/jdneo/vscode-leetcode/issues/26)) +- Support submit and test solution files from the file explorer in VS Code ([#24](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/24), [#26](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/26)) ## [0.4.0] ### Added -- Support locked problem [#20](https://github.com/jdneo/vscode-leetcode/issues/20) +- Support locked problem [#20](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/20) ### Changed -- Simplify the command 'LeetCode: Test Current File' to 'LeetCode: Test' [#18](https://github.com/jdneo/vscode-leetcode/issues/18) -- Will automatically save current file when 'LeetCode: Test' command is triggered [#17](https://github.com/jdneo/vscode-leetcode/issues/17) +- Simplify the command 'LeetCode: Test Current File' to 'LeetCode: Test' [#18](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/18) +- Will automatically save current file when 'LeetCode: Test' command is triggered [#17](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/17) ## [0.3.0] ### Added -- Test current solution file [#15](https://github.com/jdneo/vscode-leetcode/issues/15) +- Test current solution file [#15](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/15) ## [0.2.1] ### Fixed -- Fix the wrong icon bug in LeetCode Explorer [#9](https://github.com/jdneo/vscode-leetcode/issues/9) -- Fix the switch session bug when login session is expired [#12](https://github.com/jdneo/vscode-leetcode/issues/12) +- Fix the wrong icon bug in LeetCode Explorer [#9](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/9) +- Fix the switch session bug when login session is expired [#12](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/12) ## [0.2.0] ### Added -- Support setting the default language to solve problems [#5](https://github.com/jdneo/vscode-leetcode/issues/5) +- Support setting the default language to solve problems [#5](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/5) ### Fixed -- When user cancels login, no further actions will happen [#10](https://github.com/jdneo/vscode-leetcode/issues/10) +- When user cancels login, no further actions will happen [#10](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/10) ## [0.1.2] ### Fixed -- Fix the duplicated nodes in LeetCode Explorer bug [#6](https://github.com/jdneo/vscode-leetcode/issues/6) +- Fix the duplicated nodes in LeetCode Explorer bug [#6](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/6) ## [0.1.1] ### Fixed -- Fix a bug in LeetCode Explorer [#3](https://github.com/jdneo/vscode-leetcode/issues/3) -- Remove the show problem command from command palette [#4](https://github.com/jdneo/vscode-leetcode/issues/4) +- Fix a bug in LeetCode Explorer [#3](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/3) +- Remove the show problem command from command palette [#4](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/4) ## [0.1.0] ### Added diff --git a/LICENSE b/LICENSE index 4401d6f6..fffb65eb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License -Copyright (c) 2018 jdneo +Copyright (c) 2020-present 力扣 +Copyright (c) 2018-2019 jdneo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ab08b3b2..623e95f2 100644 --- a/README.md +++ b/README.md @@ -3,43 +3,51 @@ > Solve LeetCode problems in VS Code

- +

- - + + - + - - + + - - + +

-## Sponsor -[![coding](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/imgs/sponsor_coding.png)](https://coding.net/?utm_source=leetcode) +- English Document | [中文文档](https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/docs/README_zh-CN.md) -- [English Document](#Requirements) -- [中文文档](https://github.com/jdneo/vscode-leetcode/blob/master/docs/README_zh-CN.md) +## ❗️ Attention ❗️- Workaround to login to LeetCode endpoint + +> Note: If you are using `leetcode.cn`, you can just ignore this section. + +Recently we observed that [the extension cannot login to leetcode.com endpoint anymore](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478). The root cause of this issue is that leetcode.com changed its login mechanism and so far there is no ideal way to fix that issue. + +Thanks for [@yihong0618](https://github.com/yihong0618) provided a workaround which can somehow mitigate this. Now you can simply click the `Sign In` button and then select `Third Party` login or `Cookie` login. + +> Note: If you want to use third-party login(**Recommended**), please make sure your account has been connected to the third-party. If you want to use `Cookie` login, click [here](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478#issuecomment-564757098) to see the steps. ## Requirements + - [VS Code 1.30.1+](https://code.visualstudio.com/) -- [Node.js 8+](https://nodejs.org) - > NOTE: Please make sure that `Node` is in your `PATH` environment variable. You can also use the setting `leetcode.nodePath` to specify the location of your `Node.js` executable. +- [Node.js 10+](https://nodejs.org) + > NOTE: Please make sure that `Node` is in your `PATH` environment variable. You can also use the setting `leetcode.nodePath` to specify the location of your `Node.js` executable. ## Quick Start -![demo](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/gifs/demo.gif) +![demo](https://raw.githubusercontent.com/LeetCode-OpenSource/vscode-leetcode/master/docs/gifs/demo.gif) ## Features ### Sign In/Out +

- Sign in + Sign in

- Simply click `Sign in to LeetCode` in the `LeetCode Explorer` will let you **sign in** with your LeetCode account. @@ -51,29 +59,32 @@ --- ### Switch Endpoint +

- Switch Endpoint + Switch Endpoint

-- By clicking the button ![btn_endpoint](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/imgs/btn_endpoint.png) at the **explorer's navigation bar**, you can switch between different endpoints. +- By clicking the button ![btn_endpoint](https://raw.githubusercontent.com/LeetCode-OpenSource/vscode-leetcode/master/docs/imgs/btn_endpoint.png) at the **explorer's navigation bar**, you can switch between different endpoints. - The supported endpoints are: + - **leetcode.com** - - **leetcode-cn.com** + - **leetcode.cn** > Note: The accounts of different endpoints are **not** shared. Please make sure you are using the right endpoint. The extension will use `leetcode.com` by default. --- ### Pick a Problem +

- Pick a Problem + Pick a Problem

- Directly click on the problem or right click the problem in the `LeetCode Explorer` and select `Preview Problem` to see the problem description. - Select `Show Problem` to directly open the file with the problem description. - > Note: If no folder is opened in VS Code, the extension will save the problem files in **$HOME/.leetcode/**. + > Note:You can specify the path of the workspace folder to store the problem files by updating the setting `leetcode.workspaceFolder`. The default value is:**$HOME/.leetcode/**. > You can specify whether including the problem description in comments or not by updating the setting `leetcode.showCommentDescription`. @@ -81,82 +92,73 @@ --- -### Show Top Voted Solution -

- Show Top Voted Solution -

- -- Select `Show Top Voted Solution` will display the top voted solution for you. +### Editor Shortcuts ---- - -### Submit the Answer

- Submit the Answer + Editor Shortcuts

-- You can submit the answer by clicking `Submit` at the bottom of the file. Or you can right click in the editor and select `Submit to LeetCode`. - -> If you want to hide the shortcuts showing in the editor, just simply set the setting `leetcode.enableShortcuts` to false. - ---- - -### Test the Answer -

- Test the Answer -

+- The extension supports 5 editor shortcuts (aka Code Lens): -- You can test the answer by clicking `Test` at the bottom of the file. Or you can right click in the editor and select `Test in LeetCode`. + - `Submit`: Submit your answer to LeetCode. + - `Test`: Test your answer with customized test cases. + - `Star/Unstar`: Star or unstar the current problem. + - `Solution`: Show the top voted solution for the current problem. + - `Description`: Show the problem description page. -- There are 3 ways to test the answer: - - **Test with the default cases** - - **Write test cases in input box** - - **Test with the written cases in file** + > Note: You can customize the shortcuts using the setting: `leetcode.editor.shortcuts`. By default, only `Submit` and `Test` shortcuts are enabled. --- ### Search problems by Keywords +

- Search problems by Keywords + Search problems by Keywords

-- By clicking the button ![btn_search](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/imgs/btn_search.png) at the **explorer's navigation bar**, you can search the problems by keywords. +- By clicking the button ![btn_search](https://raw.githubusercontent.com/LeetCode-OpenSource/vscode-leetcode/master/docs/imgs/btn_search.png) at the **explorer's navigation bar**, you can search the problems by keywords. --- ### Manage Session +

- Manage Session + Manage Session

-- To manage your LeetCode sessions, just clicking the `LeetCode: ***` at the bottom of the status bar. You can **switch** between sessions or **create** a new session. - +- To manage your LeetCode sessions, just clicking the `LeetCode: ***` at the bottom of the status bar. You can **switch** between sessions or **create**, **delete** a session. ## Settings -| Setting Name | Description | Default Value | -| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| `leetcode.hideSolved` | Specify to hide the solved problems or not | `false` | -| `leetcode.showLocked` | Specify to show the locked problems or not. Only Premium users could open the locked problems | `false` | -| `leetcode.defaultLanguage` | Specify the default language used to solve the problem. Supported languages are: `bash`, `c`, `cpp`, `csharp`, `golang`, `java`, `javascript`, `kotlin`, `mysql`, `php`, `python`,`python3`,`ruby`,`rust`, `scala`,`swift` | `N/A` | -| `leetcode.useWsl` | Specify whether to use WSL or not | `false` | -| `leetcode.endpoint` | Specify the active endpoint. Supported endpoints are: `leetcode`, `leetcode-cn` | `leetcode` | -| `leetcode.outputFolder` | Specify the relative path to save the problem files. Besides using customized path, there are also several reserved words which can be used here: | N/A | -| `leetcode.enableStatusBar` | Specify whether the LeetCode status bar will be shown or not. | `true` | -| `leetcode.enableShortcuts` | Specify whether the submit and test shortcuts in editor or not. | `true` | -| `leetcode.enableSideMode` | Specify whether `preview`, `solution` and `submission` tab should be grouped into the second editor column when solving a problem. | `true` | -| `leetcode.nodePath` | Specify the `Node.js` executable path. | `node` | + +| Setting Name | Description | Default Value | +| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `leetcode.hideSolved` | Specify to hide the solved problems or not | `false` | +| `leetcode.defaultLanguage` | Specify the default language used to solve the problem. Supported languages are: `bash`, `c`, `cpp`, `csharp`, `golang`, `java`, `javascript`, `kotlin`, `mysql`, `php`, `python`,`python3`,`ruby`,`rust`, `scala`, `swift`, `typescript` | `N/A` | +| `leetcode.useWsl` | Specify whether to use WSL or not | `false` | +| `leetcode.endpoint` | Specify the active endpoint. Supported endpoints are: `leetcode`, `leetcode-cn` | `leetcode` | +| `leetcode.workspaceFolder` | Specify the path of the workspace folder to store the problem files. | `""` | +| `leetcode.filePath` | Specify the relative path under the workspace and the file name to save the problem files. More details can be found [here](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/Customize-the-Relative-Folder-and-the-File-Name-of-the-Problem-File). | | +| `leetcode.enableStatusBar` | Specify whether the LeetCode status bar will be shown or not. | `true` | +| `leetcode.editor.shortcuts` | Specify the customized shortcuts in editors. Supported values are: `submit`, `test`, `star`, `solution` and `description`. | `["submit, test"]` | +| `leetcode.enableSideMode` | Specify whether `preview`, `solution` and `submission` tab should be grouped into the second editor column when solving a problem. | `true` | +| `leetcode.nodePath` | Specify the `Node.js` executable path. for example, C:\Program Files\nodejs\node.exe | `node` | +| `leetcode.showCommentDescription` | Specify whether to include the problem description in the comments | `false` | +| `leetcode.useEndpointTranslation` | Use endpoint's translation (if available) | `true` | +| `leetcode.colorizeProblems` | Add difficulty badge and colorize problems files in explorer tree | `true` | +| `leetcode.problems.sortStrategy` | Specify sorting strategy for problems list | `None` | +| `leetcode.allowReportData` | Allow LeetCode to report anonymous usage data to improve the product. list | `true` | ## Want Help? -When you meet any problem, you can check out the [Troubleshooting](https://github.com/jdneo/vscode-leetcode/wiki/Troubleshooting) and [FAQ](https://github.com/jdneo/vscode-leetcode/wiki/FAQ) first. +When you meet any problem, you can check out the [Troubleshooting](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/Troubleshooting) and [FAQ](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/FAQ) first. -If your problem still cannot be addressed, feel free to reach us in the [Gitter Channel](https://gitter.im/vscode-leetcode/Lobby) or [file an issue](https://github.com/jdneo/vscode-leetcode/issues/new/choose). +If your problem still cannot be addressed, feel free to reach us in the [Gitter Channel](https://gitter.im/vscode-leetcode/Lobby) or [file an issue](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/new/choose). ## Release Notes -Refer to [CHANGELOG](https://github.com/jdneo/vscode-leetcode/blob/master/CHANGELOG.md) +Refer to [CHANGELOG](https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/CHANGELOG.md) ## Acknowledgement - This extension is based on [@skygragon](https://github.com/skygragon)'s [leetcode-cli](https://github.com/skygragon/leetcode-cli) open source project. -- Special thanks to our [contributors](https://github.com/jdneo/vscode-leetcode/blob/master/ACKNOWLEDGEMENTS.md). +- Special thanks to our [contributors](https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/ACKNOWLEDGEMENTS.md). diff --git a/docs/README_zh-CN.md b/docs/README_zh-CN.md index 98b04748..caf110bf 100644 --- a/docs/README_zh-CN.md +++ b/docs/README_zh-CN.md @@ -3,77 +3,88 @@ > 在 VS Code 中练习 LeetCode

- +

- - + + - + - - + + - - + +

-## 赞助 -[![coding](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/imgs/sponsor_coding.png)](https://coding.net/?utm_source=leetcode) +- [English Document](https://github.com/LeetCode-OpenSource/vscode-leetcode#requirements) | 中文文档 -- [English Document](#Requirements) -- [中文文档](https://github.com/jdneo/vscode-leetcode/blob/master/docs/README_zh-CN.md) +## ❗️ 注意 ❗️- 无法登录 LeetCode 节点的临时解决办法 + +> 注意:如果使用的是 `leetcode.cn` 账户,可以跳过此段落。 + +近期我们发现插件出现了[无法登录 leetcode.com 节点的问题](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478)。原因是因为近期 leetcode.com 改变了登录机制,目前我们暂时没有找到解决该问题的完美解决方案。 + +感谢 [@yihong0618](https://github.com/yihong0618) 提供了一个临时解决办法。现在你可以直接点击登录按钮并选择第三方登录或者 `Cookie` 登录。 + +> 注意:如果你希望使用第三方登录(**推荐**),请确保你的账户已经与第三方账户连接。如果你希望通过 `Cookie` 登录,请点击[该连接](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478#issuecomment-564757098)查看登录步骤。 ## 运行条件 + - [VS Code 1.23.0+](https://code.visualstudio.com/) -- [Node.js 8+](https://nodejs.org) - > 注意:请确保`Node`在`PATH`环境变量中。您也可以通过设定 `leetcode.nodePath` 选项来指定 `Node.js` 可执行文件的路径。 +- [Node.js 10+](https://nodejs.org) + > 注意:请确保`Node`在`PATH`环境变量中。您也可以通过设定 `leetcode.nodePath` 选项来指定 `Node.js` 可执行文件的路径。 ## 快速开始 -![demo](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/gifs/demo.gif) +![demo](https://raw.githubusercontent.com/LeetCode-OpenSource/vscode-leetcode/master/docs/gifs/demo.gif) ## 功能 ### 登入登出 +

- 登入登出 + 登入登出

- 点击 `LeetCode Explorer` 中的 `Sign in to LeetCode` 即可登入。 -- 你也可以使用下来命令登入或登出: +- 你也可以使用下来命令登入或利用 cookie 登入或登出: - **LeetCode: Sign in** - **LeetCode: Sign out** --- ### 切换 LeetCode 版本 +

- 切换 LeetCode 版本 + 切换 LeetCode 版本

-- LeetCode 目前有**英文版**和**中文版**两种版本。点击 `LeetCode Explorer` 导航栏中的 ![btn_endpoint](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/imgs/btn_endpoint.png) 按钮可切换版本。 +- LeetCode 目前有**英文版**和**中文版**两种版本。点击 `LeetCode Explorer` 导航栏中的 ![btn_endpoint](https://raw.githubusercontent.com/LeetCode-OpenSource/vscode-leetcode/master/docs/imgs/btn_endpoint.png) 按钮可切换版本。 - 目前可切换的版本有: + - **leetcode.com** - - **leetcode-cn.com** + - **leetcode.cn** > 注意:两种版本的 LeetCode 账户并**不通用**,请确保当前激活的版本是正确的。插件默认激活的是**英文版**。 --- ### 选择题目 +

- 选择题目 + 选择题目

- 直接点击题目或者在 `LeetCode Explorer` 中**右键**题目并选择 `Preview Problem` 可查看题目描述 - 选择 `Show Problem` 可直接进行答题。 - > 注意:若当前 VS Code 没有已打开的文件夹,则生成的题目文件会存储于 **$HOME/.leetcode/** 目录下。 + > 注意:你可以通过更新配置项 `leetcode.workspaceFolder` 来指定保存题目文件所用的工作区路径。默认工作区路径为:**$HOME/.leetcode/**。 > 注意:你可以通过更新配置项 `leetcode.showCommentDescription` 来指定是否要在注释中包含题目描述。 @@ -81,81 +92,71 @@ --- -### 查看高票解答 -

- 高票解答 -

- -- 选择 `Show Top Voted Solution` 可查看该题目在讨论区内的高票解答。 +### 编辑器快捷方式 ---- - -### 提交答案

- 提交答案 + Editor Shortcuts

-- 通过点击文件最下方的 `Submit` 可提交答案。 你也可以在编辑区内右键并选择 `Submit to LeetCode`,将**当前**文件提交。 - -> 如果你不希望在编辑器中显示**测试**和**提交**的快捷方式,可以将配置项 `leetcode.enableShortcuts` 设置为 `false`。 - ---- - -### 测试答案 -

- 测试答案 -

+- 插件会在编辑区域内支持五种不同的快捷方式(Code Lens): -- 通过点击文件最下方的 `Test` 可测试答案。你也可以在编辑区内右键并选择 `Test in LeetCode`,对**当前**文件进行测试。 + - `Submit`: 提交你的答案至 LeetCode; + - `Test`: 用给定的测试用例测试你的答案; + - `Star`: 收藏或取消收藏该问题; + - `Solution`: 显示该问题的高票解答; + - `Description`: 显示该问题的题目描述。 -- 有下列三种测试集来源: - - **默认测试集**:Test with the default cases - - **在输入框内输入测试集**:Write test cases in input box - - **提供自定义测试集文件**:Test with the written cases in file + > 注意:你可以通过 `leetcode.editor.shortcuts` 配置项来定制需要激活的快捷方式。默认情况下只有 `Submit` 和 `Test` 会被激活。 --- ### 通过关键字搜索题目 +

- 通过关键字搜索题目 + 通过关键字搜索题目

-- 点击 `LeetCode Explorer` 导航栏中的 ![btn_search](https://raw.githubusercontent.com/jdneo/vscode-leetcode/master/docs/imgs/btn_search.png) 按钮可按照关键字搜索题目。 +- 点击 `LeetCode Explorer` 导航栏中的 ![btn_search](https://raw.githubusercontent.com/LeetCode-OpenSource/vscode-leetcode/master/docs/imgs/btn_search.png) 按钮可按照关键字搜索题目。 --- ### 管理存档 +

- 管理存档 + 管理存档

-- 点击位于 VS Code 底部状态栏的 `LeetCode: ***` 管理 `LeetCode 存档`。你可以**切换**存档或者**创建**新的存档。 - +- 点击位于 VS Code 底部状态栏的 `LeetCode: ***` 管理 `LeetCode 存档`。你可以**切换**存档或者**创建**,**删除**存档。 ## 插件配置项 -| 配置项名称 | 描述 | 默认值 | -| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| `leetcode.hideSolved` | 指定是否要隐藏已解决的问题 | `false` | -| `leetcode.showLocked` | 指定是否显示付费题目,只有付费账户才可以打开付费题目 | `false` | -| `leetcode.defaultLanguage` | 指定答题时使用的默认语言,可选语言有:`bash`, `c`, `cpp`, `csharp`, `golang`, `java`, `javascript`, `kotlin`, `mysql`, `php`, `python`,`python3`,`ruby`, `rust`, `scala`,`swift` | `N/A` | -| `leetcode.useWsl` | 指定是否启用 WSL | `false` | -| `leetcode.endpoint` | 指定使用的终端,可用终端有:`leetcode`, `leetcode-cn` | `leetcode` | -| `leetcode.outputFolder` | 指定保存文件时所用的相对文件夹路径。除了用户自定义路径外,也可以使用保留项,包括: | N/A | -| `leetcode.enableStatusBar` | 指定是否在 VS Code 下方显示插件状态栏。 | `true` | -| `leetcode.enableShortcuts` | 指定是否在 VS Code 编辑文件下方显示提交和测试的快捷按钮。 | `true` | -| `leetcode.enableSideMode` | 指定在解决一道题时,是否将`问题预览`、`高票答案`与`提交结果`窗口集中在编辑器的第二栏。 | `true` | -| `leetcode.nodePath` | 指定 `Node.js` 可执行文件的路径。 | `node` | + +| 配置项名称 | 描述 | 默认值 | +| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `leetcode.hideSolved` | 指定是否要隐藏已解决的问题 | `false` | +| `leetcode.defaultLanguage` | 指定答题时使用的默认语言,可选语言有:`bash`, `c`, `cpp`, `csharp`, `golang`, `java`, `javascript`, `kotlin`, `mysql`, `php`, `python`,`python3`,`ruby`, `rust`, `scala`, `swift`, `typescript` | `N/A` | +| `leetcode.useWsl` | 指定是否启用 WSL | `false` | +| `leetcode.endpoint` | 指定使用的终端,可用终端有:`leetcode`, `leetcode-cn` | `leetcode` | +| `leetcode.workspaceFolder` | 指定保存文件的工作区目录 | `""` | +| `leetcode.filePath` | 指定生成题目文件的相对文件夹路径名和文件名。点击查看[更多详细用法](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A2%98%E7%9B%AE%E6%96%87%E4%BB%B6%E7%9A%84%E7%9B%B8%E5%AF%B9%E6%96%87%E4%BB%B6%E5%A4%B9%E8%B7%AF%E5%BE%84%E5%92%8C%E6%96%87%E4%BB%B6%E5%90%8D)。 | | +| `leetcode.enableStatusBar` | 指定是否在 VS Code 下方显示插件状态栏。 | `true` | +| `leetcode.editor.shortcuts` | 指定在编辑器内所自定义的快捷方式。可用的快捷方式有: `submit`, `test`, `star`, `solution`, `description`。 | `["submit, test"]` | +| `leetcode.enableSideMode` | 指定在解决一道题时,是否将`问题预览`、`高票答案`与`提交结果`窗口集中在编辑器的第二栏。 | `true` | +| `leetcode.nodePath` | 指定 `Node.js` 可执行文件的路径。如:C:\Program Files\nodejs\node.exe | `node` | +| `leetcode.showCommentDescription` | 指定是否要在注释中显示题干。 | `false` | +| `leetcode.useEndpointTranslation` | 是否显示翻译版本内容。 | `true` | +| `leetcode.allowReportData` | 为了更好的产品体验允许上报用户埋数据 | `true` | ## 需要帮助? -在遇到任何问题时,可以先查看一下[疑难解答](https://github.com/jdneo/vscode-leetcode/wiki/%E7%96%91%E9%9A%BE%E8%A7%A3%E7%AD%94)以及[常见问题](https://github.com/jdneo/vscode-leetcode/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)寻求帮助。 -如果您的问题依然没有解决,可以在 [Gitter Channel](https://gitter.im/vscode-leetcode/Lobby) 联系我们,或者您也可以[记录一个新的 issue](https://github.com/jdneo/vscode-leetcode/issues/new/choose)。 +在遇到任何问题时,可以先查看一下[疑难解答](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/%E7%96%91%E9%9A%BE%E8%A7%A3%E7%AD%94)以及[常见问题](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)寻求帮助。 + +如果您的问题依然没有解决,可以在 [Gitter Channel](https://gitter.im/vscode-leetcode/Lobby) 联系我们,或者您也可以[记录一个新的 issue](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/new/choose)。 ## 更新日志 -请参考[更新日志](https://github.com/jdneo/vscode-leetcode/blob/master/CHANGELOG.md) +请参考[更新日志](https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/CHANGELOG.md) ## 鸣谢 - 本插件基于[@skygragon](https://github.com/skygragon)的[leetcode-cli](https://github.com/skygragon/leetcode-cli)开源项目制作。 -- 特别鸣谢这些[贡献者们](https://github.com/jdneo/vscode-leetcode/blob/master/ACKNOWLEDGEMENTS.md)。 +- 特别鸣谢这些[贡献者们](https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/ACKNOWLEDGEMENTS.md)。 diff --git a/docs/imgs/shortcuts.png b/docs/imgs/shortcuts.png new file mode 100644 index 00000000..c949989d Binary files /dev/null and b/docs/imgs/shortcuts.png differ diff --git a/docs/imgs/solution.png b/docs/imgs/solution.png deleted file mode 100644 index 526d3f66..00000000 Binary files a/docs/imgs/solution.png and /dev/null differ diff --git a/docs/imgs/sponsor_coding.png b/docs/imgs/sponsor_coding.png deleted file mode 100644 index df7b7780..00000000 Binary files a/docs/imgs/sponsor_coding.png and /dev/null differ diff --git a/docs/imgs/submit.png b/docs/imgs/submit.png deleted file mode 100644 index 9c81a760..00000000 Binary files a/docs/imgs/submit.png and /dev/null differ diff --git a/docs/imgs/test.png b/docs/imgs/test.png deleted file mode 100644 index b90feab8..00000000 Binary files a/docs/imgs/test.png and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 0ed248d8..2ac17cf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,34 +1,2220 @@ { "name": "vscode-leetcode", - "version": "0.14.1", - "lockfileVersion": 1, + "version": "0.18.1", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "vscode-leetcode", + "version": "0.18.1", + "license": "MIT", + "dependencies": { + "axios": "^1.6.8", + "fs-extra": "^10.0.0", + "highlight.js": "^10.7.2", + "lodash": "^4.17.21", + "markdown-it": "^8.4.2", + "require-from-string": "^2.0.2", + "unescape-js": "^1.1.4", + "vsc-leetcode-cli": "2.8.1" + }, + "devDependencies": { + "@types/fs-extra": "^9.0.11", + "@types/lodash": "^4.14.170", + "@types/markdown-it": "0.0.7", + "@types/mocha": "^2.2.42", + "@types/node": "^14.14.33", + "@types/require-from-string": "^1.2.0", + "@types/vscode": "1.57.0", + "tslint": "^5.20.1", + "typescript": "^4.3.2" + }, + "engines": { + "vscode": "^1.57.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.11.tgz", + "integrity": "sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.1.tgz", + "integrity": "sha512-pQv3Sygwxxh6jYQzXaiyWDAHevJqWtqDUv6t11Sa9CPGiXny66II7Pl6PR8QO5OVysD6HYOkHMeBgIjLnk9SkQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.170", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz", + "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.7.tgz", + "integrity": "sha512-WyL6pa76ollQFQNEaLVa41ZUUvDvPY+qAUmlsphnrpL6I9p1m868b26FyeoOmo7X3/Ta/S9WKXcEYXUSHnxoVQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*" + } + }, + "node_modules/@types/mocha": { + "version": "2.2.48", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", + "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.1.tgz", + "integrity": "sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw==", + "dev": true + }, + "node_modules/@types/require-from-string": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/require-from-string/-/require-from-string-1.2.0.tgz", + "integrity": "sha512-5vE9WoOOC9/DoD3Zj53UISpM+5tSvh8k0mL4fe2zFI6vO715/W4IQ3EdVUrWVMrFi1/NZhyMvm2iKsDFkEGddQ==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.57.0.tgz", + "integrity": "sha512-FeznBFtIDCWRluojTsi9c3LLcCHOXP5etQfBK42+ixo1CoEAchkw39tuui9zomjZuKfUVL33KZUDIwHZ/xvOkQ==", + "dev": true + }, + "node_modules/abab": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", + "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", + "optional": true + }, + "node_modules/acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "optional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", + "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", + "optional": true, + "dependencies": { + "acorn": "^2.1.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://r.cnpmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://r2.cnpmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cheerio": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", + "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", + "dependencies": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "~3.8.1", + "lodash": "^4.1.0" + }, + "engines": { + "node": ">= 0.6" + }, + "optionalDependencies": { + "jsdom": "^7.0.2" + } + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dependencies": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "node_modules/css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "engines": { + "node": "*" + } + }, + "node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "optional": true + }, + "node_modules/cssstyle": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", + "optional": true, + "dependencies": { + "cssom": "0.3.x" + } + }, + "node_modules/cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-equal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", + "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=" + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "optional": true + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dependencies": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/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==" + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "optional": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "devOptional": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "optional": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "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==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "optional": true + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://r.cnpmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/highlight.js": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz", + "integrity": "sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg==", + "engines": { + "node": "*" + } + }, + "node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/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 + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/jsdom": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", + "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", + "optional": true, + "dependencies": { + "abab": "^1.0.0", + "acorn": "^2.4.0", + "acorn-globals": "^1.0.4", + "cssom": ">= 0.3.0 < 0.4.0", + "cssstyle": ">= 0.2.29 < 0.3.0", + "escodegen": "^1.6.1", + "nwmatcher": ">= 1.3.7 < 2.0.0", + "parse5": "^1.5.1", + "request": "^2.55.0", + "sax": "^1.1.4", + "symbol-tree": ">= 3.1.0 < 4.0.0", + "tough-cookie": "^2.2.0", + "webidl-conversions": "^2.0.0", + "whatwg-url-compat": "~0.6.5", + "xml-name-validator": ">= 2.0.1 < 3.0.0" + } + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "optional": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dependencies": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "node_modules/mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "dependencies": { + "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "engines": { + "node": "*" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nconf": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.4.tgz", + "integrity": "sha512-YaDR846q11JnG1vTrhJ0QIlhiGY6+W1bgWtReG9SS3vkTl3AoNwFvUItdhG6/ZjGCfWpUVuRTNEBTDAQ3nWhGw==", + "dependencies": { + "async": "^1.4.0", + "ini": "^2.0.0", + "secure-keys": "^1.0.0", + "yargs": "^16.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/nconf/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "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.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nconf/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ncp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", + "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=", + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/nwmatcher": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", + "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", + "optional": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", + "integrity": "sha512-LBS97LFe2RV6GJmXBi6OKcETKyklHNMV0xw7BtsVn2MlsgsydyZetSCbCANr+PFLmDyv4KV88nn0eCKza665Mg==", + "dependencies": { + "chalk": "^2.3.1", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.1.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^4.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "optional": true + }, + "node_modules/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "optional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prompt": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", + "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", + "dependencies": { + "colors": "^1.1.2", + "pkginfo": "0.x.x", + "read": "1.0.x", + "revalidator": "0.1.x", + "utile": "0.3.x", + "winston": "2.1.x" + }, + "engines": { + "node": ">= 0.6.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://r2.cnpmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/request/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/request/node_modules/tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dependencies": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "node_modules/secure-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", + "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.fromcodepoint": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.fromcodepoint/-/string.fromcodepoint-0.2.1.tgz", + "integrity": "sha1-jZeDM8C8klOPUPOD5IiPPlYZ1lM=" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "optional": true + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "optional": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "optional": true + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + } + }, + "node_modules/tslint/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "optional": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, + "node_modules/unescape-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unescape-js/-/unescape-js-1.1.4.tgz", + "integrity": "sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==", + "dependencies": { + "string.fromcodepoint": "^0.2.1" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utile": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", + "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", + "dependencies": { + "async": "~0.9.0", + "deep-equal": "~0.2.1", + "i": "0.3.x", + "mkdirp": "0.x.x", + "ncp": "1.0.x", + "rimraf": "2.x.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/utile/node_modules/async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "node_modules/utile/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vsc-leetcode-cli": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/vsc-leetcode-cli/-/vsc-leetcode-cli-2.8.1.tgz", + "integrity": "sha512-C5q5wGeedHKJzs53/jrVWEeobRteB/libKrVHmLqE3zraKJBgteUN4LUNEYrAjU9O6yxgj/NPEWOLoEdRhwATw==", + "dependencies": { + "ansi-styles": "3.2.1", + "cheerio": "0.20.0", + "he": "1.2.0", + "mkdirp": "^1.0.4", + "moment": "^2.29.1", + "nconf": "^0.11.2", + "ora": "3.0.0", + "prompt": "1.0.0", + "request": "2.88.0", + "supports-color": "5.5.0", + "underscore": "1.9.1", + "wordwrap": "1.0.0", + "yargs": "^15.4.1" + }, + "bin": { + "leetcode": "bin/leetcode" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", + "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", + "optional": true + }, + "node_modules/whatwg-url-compat": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", + "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", + "optional": true, + "dependencies": { + "tr46": "~0.0.1" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/winston": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", + "integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=", + "dependencies": { + "async": "~1.0.0", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "pkginfo": "0.3.x", + "stack-trace": "0.0.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/winston/node_modules/async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + }, + "node_modules/winston/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/winston/node_modules/pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "node_modules/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==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/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==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xml-name-validator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", + "optional": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yargs/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/yargs/node_modules/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/yargs/node_modules/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==" + }, + "node_modules/yargs/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + } + }, "dependencies": { - "@types/fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-qtxDULQKUenuaDLW003CgC+0T0eiAfH3BrH+vSt87GLzbz5EZ6Ox6mv9rMttvhDOatbb9nYh0E1m7ydoYwUrAg==", + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "requires": { - "@types/node": "*" + "@babel/highlight": "^7.12.13" } }, - "@types/highlight.js": { - "version": "9.12.3", - "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", - "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@types/fs-extra": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.11.tgz", + "integrity": "sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/linkify-it": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-2.0.4.tgz", - "integrity": "sha512-9o5piu3tP6DwqT+Cyf7S3BitsTc6Cl0pCPKUhIE5hzQbtueiBXdtBipTLLvaGfT11/8XHRmsagu4YfBesTaiCA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.1.tgz", + "integrity": "sha512-pQv3Sygwxxh6jYQzXaiyWDAHevJqWtqDUv6t11Sa9CPGiXny66II7Pl6PR8QO5OVysD6HYOkHMeBgIjLnk9SkQ==", "dev": true }, "@types/lodash": { - "version": "4.14.123", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", - "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==", + "version": "4.14.170", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz", + "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==", "dev": true }, "@types/markdown-it": { @@ -47,9 +2233,9 @@ "dev": true }, "@types/node": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.3.tgz", - "integrity": "sha512-HeyK+csRk7Khhg9krpMGJeT9pLzjsmiJFHYRzYpPv/dQ5tPclQsbvceiX/HKynRt/9lMLorWUYTbBHC3hRI4sg==", + "version": "14.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.1.tgz", + "integrity": "sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw==", "dev": true }, "@types/require-from-string": { @@ -58,6 +2244,12 @@ "integrity": "sha512-5vE9WoOOC9/DoD3Zj53UISpM+5tSvh8k0mL4fe2zFI6vO715/W4IQ3EdVUrWVMrFi1/NZhyMvm2iKsDFkEGddQ==", "dev": true }, + "@types/vscode": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.57.0.tgz", + "integrity": "sha512-FeznBFtIDCWRluojTsi9c3LLcCHOXP5etQfBK42+ixo1CoEAchkw39tuui9zomjZuKfUVL33KZUDIwHZ/xvOkQ==", + "dev": true + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -67,7 +2259,8 @@ "acorn": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=" + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "optional": true }, "acorn-globals": { "version": "1.0.9", @@ -78,30 +2271,21 @@ "acorn": "^2.1.0" } }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, "ajv": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", - "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "3.2.1", @@ -148,52 +2332,36 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "axios": { + "version": "1.6.8", + "resolved": "https://r.cnpmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, + "form-data": { + "version": "4.0.0", + "resolved": "https://r2.cnpmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -217,29 +2385,12 @@ "concat-map": "0.0.1" } }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -282,13 +2433,13 @@ "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==" }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, "clone": { @@ -296,11 +2447,6 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -315,22 +2461,22 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } }, "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "concat-map": { @@ -343,18 +2489,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -372,9 +2506,10 @@ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" }, "cssom": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", - "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==" + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "optional": true }, "cssstyle": { "version": "0.2.37", @@ -398,15 +2533,6 @@ "assert-plus": "^1.0.0" } }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -437,9 +2563,9 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "dom-serializer": { @@ -482,33 +2608,20 @@ "safer-buffer": "^2.1.0" } }, - "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==", - "requires": { - "once": "^1.4.0" - } + "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==" }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, - "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { "version": "1.0.5", @@ -516,12 +2629,12 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", - "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "optional": true, "requires": { - "esprima": "^3.1.3", + "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", @@ -529,35 +2642,22 @@ } }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "optional": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "devOptional": true }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "optional": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "optional": true }, "extend": { "version": "3.0.2", @@ -575,14 +2675,14 @@ "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "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==" }, "fast-levenshtein": { "version": "2.0.6", @@ -591,13 +2691,19 @@ "optional": true }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://r.cnpmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -614,13 +2720,13 @@ } }, "fs-extra": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", - "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, "fs.realpath": { @@ -628,18 +2734,16 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "getpass": { "version": "0.1.7", @@ -650,9 +2754,9 @@ } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -663,15 +2767,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "dev": true + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "har-schema": { "version": "2.0.0", @@ -679,21 +2777,21 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "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": { - "ansi-regex": "^2.0.0" + "function-bind": "^1.1.1" } }, "has-flag": { @@ -707,9 +2805,9 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "highlight.js": { - "version": "9.15.6", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.6.tgz", - "integrity": "sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==" + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz", + "integrity": "sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg==" }, "htmlparser2": { "version": "3.8.3", @@ -730,16 +2828,6 @@ } } }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -750,20 +2838,10 @@ "sshpk": "^1.7.0" } }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - } - }, "i": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", - "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=" + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==" }, "inflight": { "version": "1.0.6", @@ -775,32 +2853,28 @@ } }, "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==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "has": "^1.0.3" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "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==" }, "is-typedarray": { "version": "1.0.0", @@ -812,38 +2886,25 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "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.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } } }, "jsbn": { @@ -890,11 +2951,12 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, "jsprim": { @@ -908,14 +2970,6 @@ "verror": "1.10.0" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "^1.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -927,26 +2981,25 @@ } }, "linkify-it": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.1.0.tgz", - "integrity": "sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", "requires": { "uc.micro": "^1.0.1" } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "log-symbols": { "version": "2.2.0", @@ -956,14 +3009,6 @@ "chalk": "^2.0.1" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "requires": { - "p-defer": "^1.0.0" - } - }, "markdown-it": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", @@ -981,34 +3026,17 @@ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - } - } - }, "mime-db": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", - "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" }, "mime-types": { - "version": "2.1.22", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", - "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "requires": { - "mime-db": "~1.38.0" + "mime-db": "1.47.0" } }, "mimic-fn": { @@ -1025,95 +3053,19 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" }, "mute-stream": { "version": "0.0.8", @@ -1121,29 +3073,34 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "nconf": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz", - "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.4.tgz", + "integrity": "sha512-YaDR846q11JnG1vTrhJ0QIlhiGY6+W1bgWtReG9SS3vkTl3AoNwFvUItdhG6/ZjGCfWpUVuRTNEBTDAQ3nWhGw==", "requires": { "async": "^1.4.0", - "ini": "^1.3.0", + "ini": "^2.0.0", "secure-keys": "^1.0.0", - "yargs": "^3.19.0" + "yargs": "^16.1.1" }, "dependencies": { "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" + "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.5", + "yargs-parser": "^20.2.2" } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" } } }, @@ -1152,19 +3109,6 @@ "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "^2.0.0" - } - }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -1173,11 +3117,6 @@ "boolbase": "~1.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "nwmatcher": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", @@ -1206,17 +3145,17 @@ } }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "optional": true, "requires": { "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", + "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "word-wrap": "~1.2.3" } }, "ora": { @@ -1233,9 +3172,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" }, "strip-ansi": { "version": "4.0.0", @@ -1247,43 +3186,20 @@ } } }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "^1.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" - }, "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { "p-try": "^2.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "requires": { - "p-limit": "^2.0.0" + "p-limit": "^2.2.0" } }, "p-try": { @@ -1298,24 +3214,19 @@ "optional": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "performance-now": { @@ -1331,7 +3242,8 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "optional": true }, "prompt": { "version": "1.0.0", @@ -1346,19 +3258,15 @@ "winston": "2.1.x" } }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://r2.cnpmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { "version": "2.1.1", @@ -1370,12 +3278,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", - "dev": true - }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -1449,22 +3351,17 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -1483,17 +3380,17 @@ "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=" }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -1512,47 +3409,26 @@ "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=" }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true }, "sprintf-js": { "version": "1.0.3", @@ -1580,14 +3456,19 @@ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "string.fromcodepoint": { @@ -1595,24 +3476,14 @@ "resolved": "https://registry.npmjs.org/string.fromcodepoint/-/string.fromcodepoint-0.2.1.tgz", "integrity": "sha1-jZeDM8C8klOPUPOD5IiPPlYZ1lM=" }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1622,9 +3493,9 @@ } }, "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "optional": true }, "tough-cookie": { @@ -1644,29 +3515,41 @@ "optional": true }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tslint": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", - "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", "builtin-modules": "^1.1.1", "chalk": "^2.3.0", "commander": "^2.12.1", - "diff": "^3.2.0", + "diff": "^4.0.1", "glob": "^7.1.1", - "js-yaml": "^3.7.0", + "js-yaml": "^3.13.1", "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", "resolve": "^1.3.2", "semver": "^5.3.0", "tslib": "^1.8.0", - "tsutils": "^2.27.2" + "tsutils": "^2.29.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } } }, "tsutils": { @@ -1695,14 +3578,15 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "optional": true, "requires": { "prelude-ls": "~1.1.2" } }, "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", "dev": true }, "uc.micro": { @@ -1716,36 +3600,26 @@ "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, "unescape-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unescape-js/-/unescape-js-1.1.1.tgz", - "integrity": "sha512-2/6CdybfFt9fzYJhCD6SHfBnqCGNfjhMwPK9Pf+sJRloa/WmyAmxdBVOslOIYkvSIRKX+9xGePF5t1tugtZ63g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unescape-js/-/unescape-js-1.1.4.tgz", + "integrity": "sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==", "requires": { "string.fromcodepoint": "^0.2.1" } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "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.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } }, - "url-parse": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.6.tgz", - "integrity": "sha512-/B8AD9iQ01seoXmXf9z/MjLZQIdOoYl/+gvsQF6+mpnxaTfG9P7srYaiqaDMyKkR36XMXfhqSHss5MyFAO8lew==", - "dev": true, - "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" - } - }, "utile": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", @@ -1763,13 +3637,21 @@ "version": "0.9.2", "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } } } }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "verror": { "version": "1.10.0", @@ -1782,48 +3664,23 @@ } }, "vsc-leetcode-cli": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/vsc-leetcode-cli/-/vsc-leetcode-cli-2.6.5.tgz", - "integrity": "sha512-Veb7FpiijEt6G2BEJ+90tgqXxkagEme/jSoidL26GClgVxpki3VYv9h8Zd9X6xY2VEaduefhoVCwqZ6SQ2P7Kg==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/vsc-leetcode-cli/-/vsc-leetcode-cli-2.8.1.tgz", + "integrity": "sha512-C5q5wGeedHKJzs53/jrVWEeobRteB/libKrVHmLqE3zraKJBgteUN4LUNEYrAjU9O6yxgj/NPEWOLoEdRhwATw==", "requires": { "ansi-styles": "3.2.1", "cheerio": "0.20.0", "he": "1.2.0", - "mkdirp": "0.5.1", - "moment": "^2.20.1", - "nconf": "0.10.0", + "mkdirp": "^1.0.4", + "moment": "^2.29.1", + "nconf": "^0.11.2", "ora": "3.0.0", "prompt": "1.0.0", "request": "2.88.0", "supports-color": "5.5.0", "underscore": "1.9.1", "wordwrap": "1.0.0", - "yargs": "12.0.4" - } - }, - "vscode": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.33.tgz", - "integrity": "sha512-sXedp2oF6y4ZvqrrFiZpeMzaCLSWV+PpYkIxjG/iYquNZ9KrLL2LujltGxPLvzn49xu2sZkyC+avVNFgcJD1Iw==", - "dev": true, - "requires": { - "glob": "^7.1.2", - "mocha": "^4.0.1", - "request": "^2.88.0", - "semver": "^5.4.1", - "source-map-support": "^0.5.0", - "url-parse": "^1.4.4", - "vscode-test": "^0.1.4" - } - }, - "vscode-test": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.1.5.tgz", - "integrity": "sha512-s+lbF1Dtasc0yXVB9iQTexBe2JK6HJAUJe3fWezHKIjq+xRw5ZwCMEMBaonFIPy7s95qg2HPTRDR5W4h4kbxGw==", - "dev": true, - "requires": { - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1" + "yargs": "^15.4.1" } }, "wcwidth": { @@ -1849,24 +3706,11 @@ "tr46": "~0.0.1" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" - }, "winston": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", @@ -1898,18 +3742,48 @@ } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "optional": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.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==", + "requires": { + "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==", + "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==" + } } }, "wrappy": { @@ -1924,95 +3798,80 @@ "optional": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yargs": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.4.tgz", - "integrity": "sha512-f5esswlPO351AnejaO2A1ZZr0zesz19RehQKwiRDqWtrraWrJy16tsUIKgDXFMVytvNOHPVmTiaTh3wO67I0fQ==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "requires": { - "cliui": "^4.0.0", + "cliui": "^6.0.0", "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.0" + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "color-convert": "^2.0.1" } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "requires": { - "invert-kv": "^2.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "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==", "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "color-name": "~1.1.4" } }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } + "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==" }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "requires": { - "ansi-regex": "^3.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" } } }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index 63f95049..53552b74 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,19 @@ "name": "vscode-leetcode", "displayName": "LeetCode", "description": "Solve LeetCode problems in VS Code", - "version": "0.14.1", - "author": "Sheng Chen", - "publisher": "shengchen", + "version": "0.18.4", + "author": "LeetCode", + "publisher": "LeetCode", "license": "MIT", "icon": "resources/LeetCode.png", "engines": { - "vscode": "^1.30.1" + "vscode": "^1.57.0" }, "repository": { "type": "git", - "url": "https://github.com/jdneo/vscode-leetcode" + "url": "https://github.com/LeetCode-OpenSource/vscode-leetcode" }, - "homepage": "https://github.com/jdneo/vscode-leetcode/blob/master/README.md", + "homepage": "https://github.com/LeetCode-OpenSource/vscode-leetcode/blob/master/README.md", "categories": [ "Other", "Snippets" @@ -29,15 +29,16 @@ "onCommand:leetcode.toggleLeetCodeCn", "onCommand:leetcode.signin", "onCommand:leetcode.signout", - "onCommand:leetcode.selectSessions", - "onCommand:leetcode.createSession", + "onCommand:leetcode.manageSessions", "onCommand:leetcode.refreshExplorer", + "onCommand:leetcode.pickOne", "onCommand:leetcode.showProblem", "onCommand:leetcode.previewProblem", "onCommand:leetcode.searchProblem", "onCommand:leetcode.testSolution", "onCommand:leetcode.submitSolution", "onCommand:leetcode.switchDefaultLanguage", + "onCommand:leetcode.problems.sort", "onView:leetCodeExplorer" ], "main": "./out/src/extension", @@ -52,19 +53,13 @@ "command": "leetcode.toggleLeetCodeCn", "title": "Switch Endpoint", "category": "LeetCode", - "icon": { - "light": "resources/light/endpoint.svg", - "dark": "resources/dark/endpoint.svg" - } + "icon": "$(globe)" }, { "command": "leetcode.signin", "title": "Sign In", "category": "LeetCode", - "icon": { - "light": "resources/light/signin.svg", - "dark": "resources/dark/signin.svg" - } + "icon": "$(sign-in)" }, { "command": "leetcode.signout", @@ -72,23 +67,20 @@ "category": "LeetCode" }, { - "command": "leetcode.selectSessions", - "title": "Select Session", - "category": "LeetCode" - }, - { - "command": "leetcode.createSession", - "title": "Create New Session", + "command": "leetcode.manageSessions", + "title": "Manage Sessions", "category": "LeetCode" }, { "command": "leetcode.refreshExplorer", "title": "Refresh", "category": "LeetCode", - "icon": { - "light": "resources/light/refresh.svg", - "dark": "resources/dark/refresh.svg" - } + "icon": "$(refresh)" + }, + { + "command": "leetcode.pickOne", + "title": "Pick One", + "category": "LeetCode" }, { "command": "leetcode.showProblem", @@ -104,10 +96,7 @@ "command": "leetcode.searchProblem", "title": "Search Problem", "category": "LeetCode", - "icon": { - "light": "resources/light/search.svg", - "dark": "resources/dark/search.svg" - } + "icon": "$(search)" }, { "command": "leetcode.showSolution", @@ -124,10 +113,34 @@ "title": "Submit to LeetCode", "category": "LeetCode" }, + { + "command": "leetcode.addFavorite", + "title": "Add to Favorite List", + "category": "LeetCode", + "icon": { + "light": "resources/light/like.png", + "dark": "resources/dark/like.png" + } + }, + { + "command": "leetcode.removeFavorite", + "title": "Remove from Favorite List", + "category": "LeetCode", + "icon": { + "light": "resources/light/dislike.png", + "dark": "resources/dark/dislike.png" + } + }, { "command": "leetcode.switchDefaultLanguage", "title": "Switch Default Language", "category": "LeetCode" + }, + { + "command": "leetcode.problems.sort", + "title": "Sort Problems", + "category": "LeetCode", + "icon": "$(sort-precedence)" } ], "viewsContainers": { @@ -168,23 +181,48 @@ "command": "leetcode.refreshExplorer", "when": "view == leetCodeExplorer", "group": "navigation@3" + }, + { + "command": "leetcode.signout", + "when": "view == leetCodeExplorer", + "group": "overflow@1" + }, + { + "command": "leetcode.pickOne", + "when": "view == leetCodeExplorer", + "group": "overflow@2" + }, + { + "command": "leetcode.problems.sort", + "when": "view == leetCodeExplorer", + "group": "overflow@3" } ], "view/item/context": [ { "command": "leetcode.previewProblem", - "when": "view == leetCodeExplorer && viewItem == problem", + "when": "view == leetCodeExplorer && viewItem =~ /problem*/", "group": "leetcode@1" }, { "command": "leetcode.showProblem", - "when": "view == leetCodeExplorer && viewItem == problem", + "when": "view == leetCodeExplorer && viewItem =~ /problem*/", "group": "leetcode@2" }, { "command": "leetcode.showSolution", - "when": "view == leetCodeExplorer && viewItem == problem", + "when": "view == leetCodeExplorer && viewItem =~ /problem*/", "group": "leetcode@3" + }, + { + "command": "leetcode.addFavorite", + "when": "view == leetCodeExplorer && viewItem == problem", + "group": "inline" + }, + { + "command": "leetcode.removeFavorite", + "when": "view == leetCodeExplorer && viewItem == problem-favorite", + "group": "inline" } ], "commandPalette": [ @@ -199,6 +237,14 @@ { "command": "leetcode.previewProblem", "when": "never" + }, + { + "command": "leetcode.addFavorite", + "when": "never" + }, + { + "command": "leetcode.removeFavorite", + "when": "never" } ], "explorer/context": [ @@ -214,6 +260,11 @@ } ], "editor/context": [ + { + "submenu": "leetcode.editorAction" + } + ], + "leetcode.editorAction": [ { "command": "leetcode.testSolution", "group": "leetcode@1" @@ -221,9 +272,23 @@ { "command": "leetcode.submitSolution", "group": "leetcode@2" + }, + { + "command": "leetcode.showSolution", + "group": "leetcode@3" + }, + { + "command": "leetcode.previewProblem", + "group": "leetcode@4" } ] }, + "submenus": [ + { + "id": "leetcode.editorAction", + "label": "LeetCode" + } + ], "configuration": [ { "title": "LeetCode", @@ -234,12 +299,6 @@ "scope": "application", "description": "Hide solved problems." }, - "leetcode.showLocked": { - "type": "boolean", - "default": false, - "scope": "application", - "description": "Show locked problems." - }, "leetcode.defaultLanguage": { "type": "string", "enum": [ @@ -256,17 +315,36 @@ "python", "python3", "ruby", + "rust", "scala", - "swift" + "swift", + "typescript" ], "scope": "application", "description": "Default language for solving the problems." }, + "leetcode.showDescription": { + "type": "string", + "default": "In Webview", + "enum": [ + "In Webview", + "In File Comment", + "Both", + "None" + ], + "enumDescriptions": [ + "Show the problem description in a new webview window", + "Show the problem description in the file's comment" + ], + "scope": "application", + "description": "Specify where to show the description." + }, "leetcode.showCommentDescription": { "type": "boolean", "default": false, "scope": "application", - "description": "Include problem description in comments." + "description": "[Deprecated] Include problem description in comments.", + "deprecationMessage": "This setting will be deprecated in 0.17.0, please use 'leetcode.showDescription' instead" }, "leetcode.hint.setDefaultLanguage": { "type": "boolean", @@ -308,10 +386,258 @@ ], "description": "Endpoint of the user account." }, - "leetcode.outputFolder": { + "leetcode.useEndpointTranslation": { + "type": "boolean", + "default": true, + "scope": "application", + "description": "Use endpoint's translation (if available)" + }, + "leetcode.workspaceFolder": { "type": "string", "scope": "application", - "description": "The relative path to save the problem files." + "description": "The path of the workspace folder to store the problem files.", + "default": "" + }, + "leetcode.filePath": { + "type": "object", + "scope": "application", + "description": "The output folder and filename to save the problem files.", + "properties": { + "default": { + "type": "object", + "properties": { + "folder": { + "type": "string", + "examples": [ + "src" + ] + }, + "filename": { + "type": "string", + "examples": [ + "${camelCaseName}.${ext}", + "${PascalCaseName}.${ext}", + "${id}-${kebab-case-name}.${ext}", + "${id}_${snake_case_name}.${ext}" + ] + } + }, + "required": [ + "folder", + "filename" + ] + }, + "bash": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "c": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "cpp": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "csharp": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "golang": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "java": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "javascript": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "kotlin": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "mysql": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "php": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "python": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "python3": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "ruby": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "rust": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "scala": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "swift": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + } + }, + "additionalProperties": { + "type": "object", + "properties": { + "folder": { + "type": "string" + }, + "filename": { + "type": "string" + } + }, + "minProperties": 1 + }, + "default": { + "default": { + "folder": "", + "filename": "${id}.${kebab-case-name}.${ext}" + } + } }, "leetcode.enableStatusBar": { "type": "boolean", @@ -319,11 +645,31 @@ "scope": "application", "description": "Show the LeetCode status bar or not." }, - "leetcode.enableShortcuts": { - "type": "boolean", - "default": true, + "leetcode.editor.shortcuts": { + "type": "array", + "default": [ + "submit", + "test" + ], "scope": "application", - "description": "Show the submit and test shortcuts in editor or not." + "items": { + "type": "string", + "enum": [ + "submit", + "test", + "star", + "solution", + "description" + ], + "enumDescriptions": [ + "Submit your answer to LeetCode.", + "Test your answer with customized test cases.", + "Star or unstar the current problem.", + "Show the top voted solution for the current problem.", + "Show the problem description page." + ] + }, + "description": "Customize the shortcuts in editors." }, "leetcode.enableSideMode": { "type": "boolean", @@ -335,7 +681,30 @@ "type": "string", "default": "node", "scope": "application", - "description": "The Node.js executable path." + "description": "The Node.js executable path. for example, C:\\Program Files\\nodejs\\node.exe" + }, + "leetcode.colorizeProblems": { + "type": "boolean", + "default": true, + "scope": "application", + "description": "Add difficulty badge and colorize problems files in explorer tree." + }, + "leetcode.problems.sortStrategy": { + "type": "string", + "default": "None", + "scope": "application", + "enum": [ + "None", + "Acceptance Rate (Ascending)", + "Acceptance Rate (Descending)" + ], + "description": "Sorting strategy for problems list." + }, + "leetcode.allowReportData": { + "type": "boolean", + "default": true, + "scope": "application", + "description": "Allow LeetCode to report anonymous usage data to improve the product." } } } @@ -345,29 +714,29 @@ "vscode:prepublish": "npm run compile", "compile": "tsc -p ./", "watch": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "npm run compile && node ./node_modules/vscode/bin/test", - "lint": "tslint --project tsconfig.json -e src/*.d.ts -t verbose" + "lint": "tslint --project tsconfig.json -e src/*.d.ts -t verbose", + "build": "vsce package", + "vs-publish": "vsce publish" }, "devDependencies": { - "@types/fs-extra": "5.0.0", - "@types/highlight.js": "^9.12.3", - "@types/lodash": "^4.14.123", + "@types/fs-extra": "^9.0.11", + "@types/lodash": "^4.14.170", "@types/markdown-it": "0.0.7", "@types/mocha": "^2.2.42", - "@types/node": "^7.0.43", + "@types/node": "^14.14.33", "@types/require-from-string": "^1.2.0", - "tslint": "^5.9.1", - "typescript": "^2.6.1", - "vscode": "^1.1.33" + "@types/vscode": "1.57.0", + "tslint": "^5.20.1", + "typescript": "^4.3.2" }, "dependencies": { - "fs-extra": "^6.0.1", - "highlight.js": "^9.15.6", - "lodash": "^4.17.11", + "axios": "^1.6.8", + "fs-extra": "^10.0.0", + "highlight.js": "^10.7.2", + "lodash": "^4.17.21", "markdown-it": "^8.4.2", "require-from-string": "^2.0.2", - "unescape-js": "^1.1.1", - "vsc-leetcode-cli": "2.6.5" + "unescape-js": "^1.1.4", + "vsc-leetcode-cli": "2.8.1" } } diff --git a/resources/LeetCode.png b/resources/LeetCode.png index dcf79f2d..35461b5f 100644 Binary files a/resources/LeetCode.png and b/resources/LeetCode.png differ diff --git a/resources/LeetCode.svg b/resources/LeetCode.svg index c06fe89d..3a80c1b4 100644 --- a/resources/LeetCode.svg +++ b/resources/LeetCode.svg @@ -1,16 +1,9 @@ - - - LeetCode_36 - Created with Sketch. - - - - - - - - + + LeetCode + + + \ No newline at end of file diff --git a/resources/check.png b/resources/check.png index ad7077df..84d2d100 100644 Binary files a/resources/check.png and b/resources/check.png differ diff --git a/resources/dark/dislike.png b/resources/dark/dislike.png new file mode 100644 index 00000000..47f17c57 Binary files /dev/null and b/resources/dark/dislike.png differ diff --git a/resources/dark/endpoint.svg b/resources/dark/endpoint.svg deleted file mode 100644 index c9b4d058..00000000 --- a/resources/dark/endpoint.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/resources/dark/like.png b/resources/dark/like.png new file mode 100644 index 00000000..d7789612 Binary files /dev/null and b/resources/dark/like.png differ diff --git a/resources/dark/refresh.svg b/resources/dark/refresh.svg deleted file mode 100644 index fbc960f4..00000000 --- a/resources/dark/refresh.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/resources/dark/search.svg b/resources/dark/search.svg deleted file mode 100644 index 6cd41c04..00000000 --- a/resources/dark/search.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/resources/dark/signin.svg b/resources/dark/signin.svg deleted file mode 100644 index 4c115bc6..00000000 --- a/resources/dark/signin.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/resources/light/dislike.png b/resources/light/dislike.png new file mode 100644 index 00000000..4ced195d Binary files /dev/null and b/resources/light/dislike.png differ diff --git a/resources/light/endpoint.svg b/resources/light/endpoint.svg deleted file mode 100644 index 949fcd3e..00000000 --- a/resources/light/endpoint.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/resources/light/like.png b/resources/light/like.png new file mode 100644 index 00000000..92b845de Binary files /dev/null and b/resources/light/like.png differ diff --git a/resources/light/refresh.svg b/resources/light/refresh.svg deleted file mode 100644 index e1969cd4..00000000 --- a/resources/light/refresh.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/resources/light/search.svg b/resources/light/search.svg deleted file mode 100644 index 48ffa86d..00000000 --- a/resources/light/search.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/resources/light/signin.svg b/resources/light/signin.svg deleted file mode 100644 index ab5fe2df..00000000 --- a/resources/light/signin.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/resources/lock.png b/resources/lock.png index 8c6fa7fd..c9ce3774 100644 Binary files a/resources/lock.png and b/resources/lock.png differ diff --git a/resources/x.png b/resources/x.png index 57709cdb..64a5fc7e 100644 Binary files a/resources/x.png and b/resources/x.png differ diff --git a/src/codelens/CodeLensController.ts b/src/codelens/CodeLensController.ts index a7fa1ef7..b41f28f0 100644 --- a/src/codelens/CodeLensController.ts +++ b/src/codelens/CodeLensController.ts @@ -1,8 +1,8 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. -import { ConfigurationChangeEvent, Disposable, languages, workspace, WorkspaceConfiguration } from "vscode"; -import { CustomCodeLensProvider } from "./CustomCodeLensProvider"; +import { ConfigurationChangeEvent, Disposable, languages, workspace } from "vscode"; +import { customCodeLensProvider, CustomCodeLensProvider } from "./CustomCodeLensProvider"; class CodeLensController implements Disposable { private internalProvider: CustomCodeLensProvider; @@ -10,15 +10,15 @@ class CodeLensController implements Disposable { private configurationChangeListener: Disposable; constructor() { - this.internalProvider = new CustomCodeLensProvider(); + this.internalProvider = customCodeLensProvider; this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { - if (event.affectsConfiguration("leetcode.enableShortcuts")) { - this.setCodeLensVisibility(); + if (event.affectsConfiguration("leetcode.editor.shortcuts")) { + this.internalProvider.refresh(); } }, this); - this.setCodeLensVisibility(); + this.registeredProvider = languages.registerCodeLensProvider({ scheme: "file" }, this.internalProvider); } public dispose(): void { @@ -27,20 +27,6 @@ class CodeLensController implements Disposable { } this.configurationChangeListener.dispose(); } - - private setCodeLensVisibility(): void { - if (this.isShortcutsEnabled() && !this.registeredProvider) { - this.registeredProvider = languages.registerCodeLensProvider({ scheme: "file" }, this.internalProvider); - } else if (!this.isShortcutsEnabled() && this.registeredProvider) { - this.registeredProvider.dispose(); - this.registeredProvider = undefined; - } - } - - private isShortcutsEnabled(): boolean { - const configuration: WorkspaceConfiguration = workspace.getConfiguration(); - return configuration.get("leetcode.enableShortcuts", true); - } } export const codeLensController: CodeLensController = new CodeLensController(); diff --git a/src/codelens/CustomCodeLensProvider.ts b/src/codelens/CustomCodeLensProvider.ts index 001ccc0b..4b9b6491 100644 --- a/src/codelens/CustomCodeLensProvider.ts +++ b/src/codelens/CustomCodeLensProvider.ts @@ -2,29 +2,93 @@ // Licensed under the MIT license. import * as vscode from "vscode"; +import { explorerNodeManager } from "../explorer/explorerNodeManager"; +import { LeetCodeNode } from "../explorer/LeetCodeNode"; +import { getEditorShortcuts } from "../utils/settingUtils"; export class CustomCodeLensProvider implements vscode.CodeLensProvider { - private validFileNamePattern: RegExp = /\d+\..*\.(.+)/; + private onDidChangeCodeLensesEmitter: vscode.EventEmitter = new vscode.EventEmitter(); + + get onDidChangeCodeLenses(): vscode.Event { + return this.onDidChangeCodeLensesEmitter.event; + } + + public refresh(): void { + this.onDidChangeCodeLensesEmitter.fire(); + } public provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult { - const fileName: string = document.fileName.trim(); - const matchResult: RegExpMatchArray | null = fileName.match(this.validFileNamePattern); + const shortcuts: string[] = getEditorShortcuts(); + if (!shortcuts) { + return; + } + + const content: string = document.getText(); + const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/); if (!matchResult) { return undefined; } + const nodeId: string | undefined = matchResult[1]; + let node: LeetCodeNode | undefined; + if (nodeId) { + node = explorerNodeManager.getNodeById(nodeId); + } - const range: vscode.Range = new vscode.Range(document.lineCount - 1, 0, document.lineCount - 1, 0); + let codeLensLine: number = document.lineCount - 1; + for (let i: number = document.lineCount - 1; i >= 0; i--) { + const lineContent: string = document.lineAt(i).text; + if (lineContent.indexOf("@lc code=end") >= 0) { + codeLensLine = i; + break; + } + } - return [ - new vscode.CodeLens(range, { + const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0); + const codeLens: vscode.CodeLens[] = []; + + if (shortcuts.indexOf("submit") >= 0) { + codeLens.push(new vscode.CodeLens(range, { title: "Submit", command: "leetcode.submitSolution", - }), - new vscode.CodeLens(range, { + arguments: [document.uri], + })); + } + + if (shortcuts.indexOf("test") >= 0) { + codeLens.push(new vscode.CodeLens(range, { title: "Test", command: "leetcode.testSolution", - }), - ]; + arguments: [document.uri], + })); + } + + if (shortcuts.indexOf("star") >= 0 && node) { + codeLens.push(new vscode.CodeLens(range, { + title: node.isFavorite ? "Unstar" : "Star", + command: node.isFavorite ? "leetcode.removeFavorite" : "leetcode.addFavorite", + arguments: [node], + })); + } + + if (shortcuts.indexOf("solution") >= 0) { + codeLens.push(new vscode.CodeLens(range, { + title: "Solution", + command: "leetcode.showSolution", + arguments: [document.uri], + })); + } + + if (shortcuts.indexOf("description") >= 0) { + codeLens.push(new vscode.CodeLens(range, { + title: "Description", + command: "leetcode.previewProblem", + arguments: [document.uri], + })); + } + + return codeLens; } } + +export const customCodeLensProvider: CustomCodeLensProvider = new CustomCodeLensProvider(); diff --git a/src/commands/list.ts b/src/commands/list.ts index 5cb44137..3ebe236a 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -1,10 +1,10 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. -import * as vscode from "vscode"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; import { IProblem, ProblemState, UserStatus } from "../shared"; +import * as settingUtils from "../utils/settingUtils"; import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils"; export async function listProblems(): Promise { @@ -12,9 +12,9 @@ export async function listProblems(): Promise { if (leetCodeManager.getStatus() === UserStatus.SignedOut) { return []; } - const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); - const showLocked: boolean = !!leetCodeConfig.get("showLocked"); - const result: string = await leetCodeExecutor.listProblems(showLocked); + + const useEndpointTranslation: boolean = settingUtils.shouldUseEndpointTranslation(); + const result: string = await leetCodeExecutor.listProblems(true, useEndpointTranslation); const problems: IProblem[] = []; const lines: string[] = result.split("\n"); const reg: RegExp = /^(.)\s(.{1,2})\s(.)\s\[\s*(\d*)\s*\]\s*(.*)\s*(Easy|Medium|Hard)\s*\((\s*\d+\.\d+ %)\)/; diff --git a/src/commands/plugin.ts b/src/commands/plugin.ts index 3e3b5bf0..d2ed4b6c 100644 --- a/src/commands/plugin.ts +++ b/src/commands/plugin.ts @@ -2,9 +2,10 @@ // Licensed under the MIT license. import * as vscode from "vscode"; +import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { IQuickItemEx } from "../shared"; -import { Endpoint } from "../shared"; +import { Endpoint, SortingStrategy } from "../shared"; import { DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; import { deleteCache } from "./cache"; @@ -20,13 +21,13 @@ export async function switchEndpoint(): Promise { }, { label: `${isCnEnabled ? "$(check) " : ""}力扣`, - description: "leetcode-cn.com", + description: "leetcode.cn", detail: `启用中国版 LeetCode`, value: Endpoint.LeetCodeCN, }, ); const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks); - if (!choice) { + if (!choice || choice.value === getLeetCodeEndpoint()) { return; } const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); @@ -52,3 +53,36 @@ export function getLeetCodeEndpoint(): string { const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); return leetCodeConfig.get("endpoint", Endpoint.LeetCode); } + +const SORT_ORDER: SortingStrategy[] = [ + SortingStrategy.None, + SortingStrategy.AcceptanceRateAsc, + SortingStrategy.AcceptanceRateDesc, +]; + +export async function switchSortingStrategy(): Promise { + const currentStrategy: SortingStrategy = getSortingStrategy(); + const picks: Array> = []; + picks.push( + ...SORT_ORDER.map((s: SortingStrategy) => { + return { + label: `${currentStrategy === s ? "$(check)" : " "} ${s}`, + value: s, + }; + }), + ); + + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks); + if (!choice || choice.value === currentStrategy) { + return; + } + + const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); + await leetCodeConfig.update("problems.sortStrategy", choice.value, true); + await leetCodeTreeDataProvider.refresh(); +} + +export function getSortingStrategy(): SortingStrategy { + const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); + return leetCodeConfig.get("problems.sortStrategy", SortingStrategy.None); +} diff --git a/src/commands/session.ts b/src/commands/session.ts index 5cf37724..f86d4cf3 100644 --- a/src/commands/session.ts +++ b/src/commands/session.ts @@ -5,7 +5,7 @@ import * as vscode from "vscode"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; import { IQuickItemEx } from "../shared"; -import { DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; +import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; export async function getSessionList(): Promise { const signInStatus: string | undefined = leetCodeManager.getUser(); @@ -32,17 +32,21 @@ export async function getSessionList(): Promise { return sessions; } -export async function selectSession(): Promise { - const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(parseSessionsToPicks()); +export async function manageSessions(): Promise { + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(parseSessionsToPicks(true /* includeOperation */)); if (!choice || choice.description === "Active") { return; } - if (choice.value === ":createNewSession") { - await vscode.commands.executeCommand("leetcode.createSession"); + if (choice.value === ":createSession") { + await createSession(); + return; + } + if (choice.value === ":deleteSession") { + await deleteSession(); return; } try { - await leetCodeExecutor.enableSession(choice.value); + await leetCodeExecutor.enableSession((choice.value as ISession).id); vscode.window.showInformationMessage(`Successfully switched to session '${choice.label}'.`); await vscode.commands.executeCommand("leetcode.refreshExplorer"); } catch (error) { @@ -50,22 +54,20 @@ export async function selectSession(): Promise { } } -async function parseSessionsToPicks(): Promise>> { - return new Promise(async (resolve: (res: Array>) => void): Promise => { +async function parseSessionsToPicks(includeOperations: boolean = false): Promise>> { + return new Promise(async (resolve: (res: Array>) => void): Promise => { try { const sessions: ISession[] = await getSessionList(); - const picks: Array> = sessions.map((s: ISession) => Object.assign({}, { + const picks: Array> = sessions.map((s: ISession) => Object.assign({}, { label: `${s.active ? "$(check) " : ""}${s.name}`, description: s.active ? "Active" : "", detail: `AC Questions: ${s.acQuestions}, AC Submits: ${s.acSubmits}`, - value: s.id, + value: s, })); - picks.push({ - label: "$(plus) Create a new session", - description: "", - detail: "Click this item to create a new session", - value: ":createNewSession", - }); + + if (includeOperations) { + picks.push(...parseSessionManagementOperations()); + } resolve(picks); } catch (error) { return await promptForOpenOutputChannel("Failed to list sessions. Please open the output channel for details.", DialogType.error); @@ -73,7 +75,21 @@ async function parseSessionsToPicks(): Promise>> { }); } -export async function createSession(): Promise { +function parseSessionManagementOperations(): Array> { + return [{ + label: "$(plus) Create a session", + description: "", + detail: "Click this item to create a session", + value: ":createSession", + }, { + label: "$(trashcan) Delete a session", + description: "", + detail: "Click this item to DELETE a session", + value: ":deleteSession", + }]; +} + +async function createSession(): Promise { const session: string | undefined = await vscode.window.showInputBox({ prompt: "Enter the new session name.", validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "Session name must not be empty", @@ -89,6 +105,47 @@ export async function createSession(): Promise { } } +async function deleteSession(): Promise { + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick( + parseSessionsToPicks(false /* includeOperation */), + { placeHolder: "Please select the session you want to delete" }, + ); + if (!choice) { + return; + } + + const selectedSession: ISession = choice.value as ISession; + if (selectedSession.active) { + vscode.window.showInformationMessage("Cannot delete an active session."); + return; + } + + const action: vscode.MessageItem | undefined = await vscode.window.showWarningMessage( + `This operation cannot be reverted. Are you sure to delete the session: ${selectedSession.name}?`, + DialogOptions.yes, + DialogOptions.no, + ); + if (action !== DialogOptions.yes) { + return; + } + + const confirm: string | undefined = await vscode.window.showInputBox({ + prompt: "Enter 'yes' to confirm deleting the session", + validateInput: (value: string): string => { + if (value === "yes") { + return ""; + } else { + return "Enter 'yes' to confirm"; + } + }, + }); + + if (confirm === "yes") { + await leetCodeExecutor.deleteSession(selectedSession.id); + vscode.window.showInformationMessage("The session has been successfully deleted."); + } +} + export interface ISession { active: boolean; id: string; diff --git a/src/commands/show.ts b/src/commands/show.ts index 24d3b50f..eccf5571 100644 --- a/src/commands/show.ts +++ b/src/commands/show.ts @@ -1,27 +1,75 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. -import * as fse from "fs-extra"; +import * as _ from "lodash"; import * as path from "path"; import * as unescapeJS from "unescape-js"; import * as vscode from "vscode"; +import { explorerNodeManager } from "../explorer/explorerNodeManager"; import { LeetCodeNode } from "../explorer/LeetCodeNode"; import { leetCodeChannel } from "../leetCodeChannel"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; -import { IProblem, IQuickItemEx, languages, ProblemState } from "../shared"; -import { DialogOptions, DialogType, openSettingsEditor, promptForOpenOutputChannel, promptForSignIn, promptHintMessage } from "../utils/uiUtils"; -import { selectWorkspaceFolder } from "../utils/workspaceUtils"; +import { Endpoint, IProblem, IQuickItemEx, languages, PREMIUM_URL_CN, PREMIUM_URL_GLOBAL, ProblemState } from "../shared"; +import { genFileExt, genFileName, getNodeIdFromFile } from "../utils/problemUtils"; +import * as settingUtils from "../utils/settingUtils"; +import { IDescriptionConfiguration } from "../utils/settingUtils"; +import { + DialogOptions, + DialogType, + openSettingsEditor, + openUrl, + promptForOpenOutputChannel, + promptForSignIn, + promptHintMessage, +} from "../utils/uiUtils"; +import { getActiveFilePath, selectWorkspaceFolder } from "../utils/workspaceUtils"; import * as wsl from "../utils/wslUtils"; import { leetCodePreviewProvider } from "../webview/leetCodePreviewProvider"; import { leetCodeSolutionProvider } from "../webview/leetCodeSolutionProvider"; import * as list from "./list"; +import { getLeetCodeEndpoint } from "./plugin"; +import { globalState } from "../globalState"; -export async function previewProblem(node: IProblem, isSideMode: boolean = false): Promise { - const descString: string = await leetCodeExecutor.getDescription(node); +export async function previewProblem(input: IProblem | vscode.Uri, isSideMode: boolean = false): Promise { + let node: IProblem; + + if (input instanceof vscode.Uri) { + const activeFilePath: string = input.fsPath; + const id: string = await getNodeIdFromFile(activeFilePath); + if (!id) { + vscode.window.showErrorMessage(`Failed to resolve the problem id from file: ${activeFilePath}.`); + return; + } + const cachedNode: IProblem | undefined = explorerNodeManager.getNodeById(id); + if (!cachedNode) { + vscode.window.showErrorMessage(`Failed to resolve the problem with id: ${id}.`); + return; + } + node = cachedNode; + // Move the preview page aside if it's triggered from Code Lens + isSideMode = true; + } else { + node = input; + const { isPremium } = globalState.getUserStatus() ?? {}; + if (input.locked && !isPremium) { + const url = getLeetCodeEndpoint() === Endpoint.LeetCode ? PREMIUM_URL_GLOBAL : PREMIUM_URL_CN; + openUrl(url); + return; + } + } + + const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation(); + const descString: string = await leetCodeExecutor.getDescription(node.id, needTranslation); leetCodePreviewProvider.show(descString, node, isSideMode); } +export async function pickOne(): Promise { + const problems: IProblem[] = await list.listProblems(); + const randomProblem: IProblem = problems[Math.floor(Math.random() * problems.length)]; + await showProblemInternal(randomProblem); +} + export async function showProblem(node?: LeetCodeNode): Promise { if (!node) { return; @@ -34,30 +82,42 @@ export async function searchProblem(): Promise { promptForSignIn(); return; } - const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick( - parseProblemsToPicks(list.listProblems()), - { - matchOnDetail: true, - placeHolder: "Select one problem", - }, - ); + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(parseProblemsToPicks(list.listProblems()), { + matchOnDetail: true, + placeHolder: "Select one problem", + }); if (!choice) { return; } await showProblemInternal(choice.value); } -export async function showSolution(node?: LeetCodeNode): Promise { - if (!node) { +export async function showSolution(input: LeetCodeNode | vscode.Uri): Promise { + let problemInput: string | undefined; + if (input instanceof LeetCodeNode) { + // Triggerred from explorer + problemInput = input.id; + } else if (input instanceof vscode.Uri) { + // Triggerred from Code Lens/context menu + problemInput = `"${input.fsPath}"`; + } else if (!input) { + // Triggerred from command + problemInput = await getActiveFilePath(); + } + + if (!problemInput) { + vscode.window.showErrorMessage("Invalid input to fetch the solution data."); return; } + const language: string | undefined = await fetchProblemLanguage(); if (!language) { return; } try { - const solution: string = await leetCodeExecutor.showSolution(node, language); - leetCodeSolutionProvider.show(unescapeJS(solution), node); + const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation(); + const solution: string = await leetCodeExecutor.showSolution(problemInput, language, needTranslation); + leetCodeSolutionProvider.show(unescapeJS(solution)); } catch (error) { leetCodeChannel.appendLine(error.toString()); await promptForOpenOutputChannel("Failed to fetch the top voted solution. Please open the output channel for details.", DialogType.error); @@ -70,7 +130,12 @@ async function fetchProblemLanguage(): Promise { if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) { defaultLanguage = undefined; } - const language: string | undefined = defaultLanguage || await vscode.window.showQuickPick(languages, { placeHolder: "Select the language you want to use", ignoreFocusOut: true }); + const language: string | undefined = + defaultLanguage || + (await vscode.window.showQuickPick(languages, { + placeHolder: "Select the language you want to use", + ignoreFocusOut: true, + })); // fire-and-forget default language query (async (): Promise => { if (language && !defaultLanguage && leetCodeConfig.get("hint.setDefaultLanguage")) { @@ -78,7 +143,7 @@ async function fetchProblemLanguage(): Promise { `Would you like to set '${language}' as your default language?`, DialogOptions.yes, DialogOptions.no, - DialogOptions.never, + DialogOptions.never ); if (choice === DialogOptions.yes) { leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */); @@ -98,54 +163,72 @@ async function showProblemInternal(node: IProblem): Promise { } const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); - let outDir: string = await selectWorkspaceFolder(); - let relativePath: string = (leetCodeConfig.get("outputFolder", "")).trim(); - const matchResult: RegExpMatchArray | null = relativePath.match(/\$\{(.*?)\}/); - if (matchResult) { - const resolvedPath: string | undefined = await resolveRelativePath(matchResult[1].toLocaleLowerCase(), node, language); - if (!resolvedPath) { + const workspaceFolder: string = await selectWorkspaceFolder(); + if (!workspaceFolder) { + return; + } + + const fileFolder: string = leetCodeConfig + .get(`filePath.${language}.folder`, leetCodeConfig.get(`filePath.default.folder`, "")) + .trim(); + const fileName: string = leetCodeConfig + .get(`filePath.${language}.filename`, leetCodeConfig.get(`filePath.default.filename`) || genFileName(node, language)) + .trim(); + + let finalPath: string = path.join(workspaceFolder, fileFolder, fileName); + + if (finalPath) { + finalPath = await resolveRelativePath(finalPath, node, language); + if (!finalPath) { leetCodeChannel.appendLine("Showing problem canceled by user."); return; } - relativePath = resolvedPath; } - outDir = path.join(outDir, relativePath); - await fse.ensureDir(outDir); + finalPath = wsl.useWsl() ? await wsl.toWinPath(finalPath) : finalPath; + + const descriptionConfig: IDescriptionConfiguration = settingUtils.getDescriptionConfiguration(); + const needTranslation: boolean = settingUtils.shouldUseEndpointTranslation(); - const originFilePath: string = await leetCodeExecutor.showProblem(node, language, outDir, leetCodeConfig.get("showCommentDescription")); - const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath; - await Promise.all([ - vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One }), - movePreviewAsideIfNeeded(node), + await leetCodeExecutor.showProblem(node, language, finalPath, descriptionConfig.showInComment, needTranslation); + const promises: any[] = [ + vscode.window.showTextDocument(vscode.Uri.file(finalPath), { + preview: false, + viewColumn: vscode.ViewColumn.One, + }), promptHintMessage( "hint.commentDescription", - 'You can generate the code file with problem description in the comments by enabling "leetcode.showCommentDescription".', + 'You can config how to show the problem description through "leetcode.showDescription".', "Open settings", - (): Promise => openSettingsEditor("leetcode.showCommentDescription"), + (): Promise => openSettingsEditor("leetcode.showDescription") ), - ]); + ]; + if (descriptionConfig.showInWebview) { + promises.push(showDescriptionView(node)); + } + + await Promise.all(promises); } catch (error) { - await promptForOpenOutputChannel("Failed to show the problem. Please open the output channel for details.", DialogType.error); + await promptForOpenOutputChannel(`${error} Please open the output channel for details.`, DialogType.error); } } -async function movePreviewAsideIfNeeded(node: IProblem): Promise { - if (vscode.workspace.getConfiguration("leetcode").get("enableSideMode", true)) { - return previewProblem(node, true); - } else { - return Promise.resolve(); - } +async function showDescriptionView(node: IProblem): Promise { + return previewProblem(node, vscode.workspace.getConfiguration("leetcode").get("enableSideMode", true)); } - async function parseProblemsToPicks(p: Promise): Promise>> { return new Promise(async (resolve: (res: Array>) => void): Promise => { - const picks: Array> = (await p).map((problem: IProblem) => Object.assign({}, { - label: `${parseProblemDecorator(problem.state, problem.locked)}${problem.id}.${problem.name}`, - description: "", - detail: `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`, - value: problem, - })); + const picks: Array> = (await p).map((problem: IProblem) => + Object.assign( + {}, + { + label: `${parseProblemDecorator(problem.state, problem.locked)}${problem.id}.${problem.name}`, + description: "", + detail: `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`, + value: problem, + } + ) + ); resolve(picks); }); } @@ -161,27 +244,70 @@ function parseProblemDecorator(state: ProblemState, locked: boolean): string { } } -async function resolveRelativePath(value: string, node: IProblem, selectedLanguage: string): Promise { - switch (value) { - case "tag": - if (node.tags.length === 1) { - return node.tags[0]; - } - return await vscode.window.showQuickPick( - node.tags, - { - matchOnDetail: true, - placeHolder: "Multiple tags available, please select one", - ignoreFocusOut: true, - }, - ); - case "language": - return selectedLanguage; - case "difficulty": - return node.difficulty; - default: - const errorMsg: string = `The config '${value}' is not supported.`; - leetCodeChannel.appendLine(errorMsg); - throw new Error(errorMsg); +async function resolveRelativePath(relativePath: string, node: IProblem, selectedLanguage: string): Promise { + let tag: string = ""; + if (/\$\{tag\}/i.test(relativePath)) { + tag = (await resolveTagForProblem(node)) || ""; + } + + let company: string = ""; + if (/\$\{company\}/i.test(relativePath)) { + company = (await resolveCompanyForProblem(node)) || ""; + } + + return relativePath.replace(/\$\{(.*?)\}/g, (_substring: string, ...args: string[]) => { + const placeholder: string = args[0].toLowerCase().trim(); + switch (placeholder) { + case "id": + return node.id; + case "name": + return node.name; + case "camelcasename": + return _.camelCase(node.name); + case "pascalcasename": + return _.upperFirst(_.camelCase(node.name)); + case "kebabcasename": + case "kebab-case-name": + return _.kebabCase(node.name); + case "snakecasename": + case "snake_case_name": + return _.snakeCase(node.name); + case "ext": + return genFileExt(selectedLanguage); + case "language": + return selectedLanguage; + case "difficulty": + return node.difficulty.toLocaleLowerCase(); + case "tag": + return tag; + case "company": + return company; + default: + const errorMsg: string = `The config '${placeholder}' is not supported.`; + leetCodeChannel.appendLine(errorMsg); + throw new Error(errorMsg); + } + }); +} + +async function resolveTagForProblem(problem: IProblem): Promise { + if (problem.tags.length === 1) { + return problem.tags[0]; + } + return await vscode.window.showQuickPick(problem.tags, { + matchOnDetail: true, + placeHolder: "Multiple tags available, please select one", + ignoreFocusOut: true, + }); +} + +async function resolveCompanyForProblem(problem: IProblem): Promise { + if (problem.companies.length === 1) { + return problem.companies[0]; } + return await vscode.window.showQuickPick(problem.companies, { + matchOnDetail: true, + placeHolder: "Multiple tags available, please select one", + ignoreFocusOut: true, + }); } diff --git a/src/commands/star.ts b/src/commands/star.ts new file mode 100644 index 00000000..36611499 --- /dev/null +++ b/src/commands/star.ts @@ -0,0 +1,34 @@ + +// Copyright (c) jdneo. All rights reserved. +// Licensed under the MIT license. + +import { customCodeLensProvider } from "../codelens/CustomCodeLensProvider"; +import { LeetCodeNode } from "../explorer/LeetCodeNode"; +import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider"; +import { leetCodeExecutor } from "../leetCodeExecutor"; +import { hasStarShortcut } from "../utils/settingUtils"; +import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils"; + +export async function addFavorite(node: LeetCodeNode): Promise { + try { + await leetCodeExecutor.toggleFavorite(node, true); + await leetCodeTreeDataProvider.refresh(); + if (hasStarShortcut()) { + customCodeLensProvider.refresh(); + } + } catch (error) { + await promptForOpenOutputChannel("Failed to add the problem to favorite. Please open the output channel for details.", DialogType.error); + } +} + +export async function removeFavorite(node: LeetCodeNode): Promise { + try { + await leetCodeExecutor.toggleFavorite(node, false); + await leetCodeTreeDataProvider.refresh(); + if (hasStarShortcut()) { + customCodeLensProvider.refresh(); + } + } catch (error) { + await promptForOpenOutputChannel("Failed to remove the problem from favorite. Please open the output channel for details.", DialogType.error); + } +} diff --git a/src/commands/submit.ts b/src/commands/submit.ts index f6e2d989..26660029 100644 --- a/src/commands/submit.ts +++ b/src/commands/submit.ts @@ -2,6 +2,7 @@ // Licensed under the MIT license. import * as vscode from "vscode"; +import { leetCodeTreeDataProvider } from "../explorer/LeetCodeTreeDataProvider"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; import { DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; @@ -24,5 +25,8 @@ export async function submitSolution(uri?: vscode.Uri): Promise { leetCodeSubmissionProvider.show(result); } catch (error) { await promptForOpenOutputChannel("Failed to submit the solution. Please open the output channel for details.", DialogType.error); + return; } + + leetCodeTreeDataProvider.refresh(); } diff --git a/src/commands/test.ts b/src/commands/test.ts index 262f7339..d070c9aa 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -65,7 +65,7 @@ export async function testSolution(uri?: vscode.Uri): Promise { } break; case ":file": - const testFile: vscode.Uri[] | undefined = await showFileSelectDialog(); + const testFile: vscode.Uri[] | undefined = await showFileSelectDialog(filePath); if (testFile && testFile.length) { const input: string = (await fse.readFile(testFile[0].fsPath, "utf-8")).trim(); if (input) { diff --git a/src/explorer/LeetCodeNode.ts b/src/explorer/LeetCodeNode.ts index 3f685b70..3d2cc74f 100644 --- a/src/explorer/LeetCodeNode.ts +++ b/src/explorer/LeetCodeNode.ts @@ -1,11 +1,12 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. -import { Command } from "vscode"; +import { Command, Uri } from "vscode"; import { IProblem, ProblemState } from "../shared"; export class LeetCodeNode { - constructor(private data: IProblem, private parentNodeName: string, private isProblemNode: boolean = true) { } + + constructor(private data: IProblem, private isProblemNode: boolean = true) { } public get locked(): boolean { return this.data.locked; @@ -46,10 +47,6 @@ export class LeetCodeNode { return this.isProblemNode; } - public get parentName(): string { - return this.parentNodeName; - } - public get previewCommand(): Command { return { title: "Preview Problem", @@ -58,4 +55,17 @@ export class LeetCodeNode { }; } + public get acceptanceRate(): number { + return Number(this.passRate.slice(0, -1).trim()); + } + + public get uri(): Uri { + return Uri.from({ + scheme: "leetcode", + authority: this.isProblem ? "problems" : "tree-node", + path: `/${this.id}`, // path must begin with slash / + query: `difficulty=${this.difficulty}`, + }); + } + } diff --git a/src/explorer/LeetCodeTreeDataProvider.ts b/src/explorer/LeetCodeTreeDataProvider.ts index 09f47530..9c298944 100644 --- a/src/explorer/LeetCodeTreeDataProvider.ts +++ b/src/explorer/LeetCodeTreeDataProvider.ts @@ -1,42 +1,37 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. -import * as _ from "lodash"; import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; -import * as list from "../commands/list"; -import { leetCodeChannel } from "../leetCodeChannel"; import { leetCodeManager } from "../leetCodeManager"; -import { Category, defaultProblem, IProblem, ProblemState } from "../shared"; -import { getWorkspaceConfiguration } from "../utils/workspaceUtils"; +import { Category, defaultProblem, ProblemState } from "../shared"; +import { explorerNodeManager } from "./explorerNodeManager"; import { LeetCodeNode } from "./LeetCodeNode"; +import { globalState } from "../globalState"; export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider { + private context: vscode.ExtensionContext; - private treeData: { - Difficulty: Map, - Tag: Map, - Company: Map, - Favorite: IProblem[], - }; - - private onDidChangeTreeDataEvent: vscode.EventEmitter = new vscode.EventEmitter(); + private onDidChangeTreeDataEvent: vscode.EventEmitter = new vscode.EventEmitter< + LeetCodeNode | undefined | null + >(); // tslint:disable-next-line:member-ordering public readonly onDidChangeTreeData: vscode.Event = this.onDidChangeTreeDataEvent.event; - constructor(private context: vscode.ExtensionContext) { } + public initialize(context: vscode.ExtensionContext): void { + this.context = context; + } public async refresh(): Promise { - await this.getProblemData(); - this.onDidChangeTreeDataEvent.fire(); + await explorerNodeManager.refreshCache(); + this.onDidChangeTreeDataEvent.fire(null); } public getTreeItem(element: LeetCodeNode): vscode.TreeItem | Thenable { if (element.id === "notSignIn") { return { label: element.name, - id: element.id, collapsibleState: vscode.TreeItemCollapsibleState.None, command: { command: "leetcode.signin", @@ -45,122 +40,72 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider { if (!leetCodeManager.getUser()) { return [ - new LeetCodeNode(Object.assign({}, defaultProblem, { - id: "notSignIn", - name: "Sign in to LeetCode", - }), "ROOT", false), + new LeetCodeNode( + Object.assign({}, defaultProblem, { + id: "notSignIn", + name: "Sign in to LeetCode", + }), + false + ), ]; } - if (!element) { // Root view - return [ - new LeetCodeNode(Object.assign({}, defaultProblem, { - id: Category.Difficulty, - name: Category.Difficulty, - }), "ROOT", false), - new LeetCodeNode(Object.assign({}, defaultProblem, { - id: Category.Tag, - name: Category.Tag, - }), "ROOT", false), - new LeetCodeNode(Object.assign({}, defaultProblem, { - id: Category.Company, - name: Category.Company, - }), "ROOT", false), - new LeetCodeNode(Object.assign({}, defaultProblem, { - id: Category.Favorite, - name: Category.Favorite, - }), "ROOT", false), - ]; + if (!element) { + // Root view + return explorerNodeManager.getRootNodes(); } else { - switch (element.name) { // First-level + switch (element.id) { + case Category.All: + return explorerNodeManager.getAllNodes(); case Category.Favorite: - const nodes: IProblem[] = this.treeData[Category.Favorite]; - return nodes.map((p: IProblem) => new LeetCodeNode(p, Category.Favorite)); + return explorerNodeManager.getFavoriteNodes(); case Category.Difficulty: + return explorerNodeManager.getAllDifficultyNodes(); case Category.Tag: + return explorerNodeManager.getAllTagNodes(); case Category.Company: - return this.composeSubCategoryNodes(element); - default: // Second and lower levels - return element.isProblem ? [] : this.composeProblemNodes(element); - } - } - } - - private async getProblemData(): Promise { - // clear cache - this.treeData = { - Difficulty: new Map(), - Tag: new Map(), - Company: new Map(), - Favorite: [], - }; - for (const problem of await list.listProblems()) { - // Add favorite problem, no matter whether it is solved. - if (problem.isFavorite) { - this.treeData[Category.Favorite].push(problem); - } - // Hide solved problem in other category. - if (problem.state === ProblemState.AC && getWorkspaceConfiguration().get("hideSolved")) { - continue; + return explorerNodeManager.getAllCompanyNodes(); + default: + if (element.isProblem) { + return []; + } + return explorerNodeManager.getChildrenNodesById(element.id); } - - this.addProblemToTreeData(problem); - } - } - - private composeProblemNodes(node: LeetCodeNode): LeetCodeNode[] { - const map: Map | undefined = this.treeData[node.parentName]; - if (!map) { - leetCodeChannel.appendLine(`Category: ${node.parentName} is not available.`); - return []; - } - const problems: IProblem[] = map.get(node.name) || []; - const problemNodes: LeetCodeNode[] = []; - for (const problem of problems) { - problemNodes.push(new LeetCodeNode(problem, node.name)); - } - return problemNodes; - } - - private composeSubCategoryNodes(node: LeetCodeNode): LeetCodeNode[] { - const category: Category = node.name as Category; - if (category === Category.Favorite) { - leetCodeChannel.appendLine("No sub-level for Favorite nodes"); - return []; - } - const map: Map | undefined = this.treeData[category]; - if (!map) { - leetCodeChannel.appendLine(`Category: ${category} is not available.`); - return []; } - return this.getSubCategoryNodes(map, category); } private parseIconPathFromProblemState(element: LeetCodeNode): string { if (!element.isProblem) { return ""; } + const { isPremium } = globalState.getUserStatus() ?? {}; switch (element.state) { case ProblemState.AC: return this.context.asAbsolutePath(path.join("resources", "check.png")); case ProblemState.NotAC: return this.context.asAbsolutePath(path.join("resources", "x.png")); case ProblemState.Unknown: - if (element.locked) { + if (element.locked && !isPremium) { return this.context.asAbsolutePath(path.join("resources", "lock.png")); } return this.context.asAbsolutePath(path.join("resources", "blank.png")); @@ -169,18 +114,26 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider, key: string, problem: IProblem): void { - const problems: IProblem[] | undefined = map.get(key); - if (problems) { - problems.push(problem); - } else { - map.set(key, [problem]); - } - } - - private getSubCategoryNodes(map: Map, category: Category): LeetCodeNode[] { - const subCategoryNodes: LeetCodeNode[] = Array.from(map.keys()).map((subCategory: string) => { - return new LeetCodeNode(Object.assign({}, defaultProblem, { - id: subCategory, - name: subCategory, - }), category.toString(), false); - }); - this.sortSubCategoryNodes(subCategoryNodes, category); - return subCategoryNodes; - } - - private sortSubCategoryNodes(subCategoryNodes: LeetCodeNode[], category: Category): void { - switch (category) { - case Category.Difficulty: - subCategoryNodes.sort((a: LeetCodeNode, b: LeetCodeNode): number => { - function getValue(input: LeetCodeNode): number { - switch (input.name.toLowerCase()) { - case "easy": - return 1; - case "medium": - return 2; - case "hard": - return 3; - default: - return Number.MAX_SAFE_INTEGER; - } - } - return getValue(a) - getValue(b); - }); - break; - case Category.Tag: - case Category.Company: - subCategoryNodes.sort((a: LeetCodeNode, b: LeetCodeNode): number => { - if (a.name === "Unknown") { - return 1; - } else if (b.name === "Unknown") { - return -1; - } else { - return Number(a.name > b.name) - Number(a.name < b.name); - } - }); - break; - default: - break; - } + return [`AC: ${acceptedNum}`, `Failed: ${failedNum}`, `Total: ${childernNodes.length}`].join(os.EOL); } } + +export const leetCodeTreeDataProvider: LeetCodeTreeDataProvider = new LeetCodeTreeDataProvider(); diff --git a/src/explorer/LeetCodeTreeItemDecorationProvider.ts b/src/explorer/LeetCodeTreeItemDecorationProvider.ts new file mode 100644 index 00000000..103ce2d9 --- /dev/null +++ b/src/explorer/LeetCodeTreeItemDecorationProvider.ts @@ -0,0 +1,40 @@ +import { URLSearchParams } from "url"; +import { FileDecoration, FileDecorationProvider, ProviderResult, ThemeColor, Uri, workspace, WorkspaceConfiguration } from "vscode"; + +export class LeetCodeTreeItemDecorationProvider implements FileDecorationProvider { + private readonly DIFFICULTY_BADGE_LABEL: { [key: string]: string } = { + easy: "E", + medium: "M", + hard: "H", + }; + + private readonly ITEM_COLOR: { [key: string]: ThemeColor } = { + easy: new ThemeColor("charts.green"), + medium: new ThemeColor("charts.yellow"), + hard: new ThemeColor("charts.red"), + }; + + public provideFileDecoration(uri: Uri): ProviderResult { + if (!this.isDifficultyBadgeEnabled()) { + return; + } + + if (uri.scheme !== "leetcode" && uri.authority !== "problems") { + return; + } + + const params: URLSearchParams = new URLSearchParams(uri.query); + const difficulty: string = params.get("difficulty")!.toLowerCase(); + return { + badge: this.DIFFICULTY_BADGE_LABEL[difficulty], + color: this.ITEM_COLOR[difficulty], + }; + } + + private isDifficultyBadgeEnabled(): boolean { + const configuration: WorkspaceConfiguration = workspace.getConfiguration(); + return configuration.get("leetcode.colorizeProblems", false); + } +} + +export const leetCodeTreeItemDecorationProvider: LeetCodeTreeItemDecorationProvider = new LeetCodeTreeItemDecorationProvider(); diff --git a/src/explorer/explorerNodeManager.ts b/src/explorer/explorerNodeManager.ts new file mode 100644 index 00000000..a04ad55c --- /dev/null +++ b/src/explorer/explorerNodeManager.ts @@ -0,0 +1,203 @@ +// Copyright (c) jdneo. All rights reserved. +// Licensed under the MIT license. + +import * as _ from "lodash"; +import { Disposable } from "vscode"; +import * as list from "../commands/list"; +import { getSortingStrategy } from "../commands/plugin"; +import { Category, defaultProblem, ProblemState, SortingStrategy } from "../shared"; +import { shouldHideSolvedProblem } from "../utils/settingUtils"; +import { LeetCodeNode } from "./LeetCodeNode"; + +class ExplorerNodeManager implements Disposable { + private explorerNodeMap: Map = new Map(); + private companySet: Set = new Set(); + private tagSet: Set = new Set(); + + public async refreshCache(): Promise { + this.dispose(); + const shouldHideSolved: boolean = shouldHideSolvedProblem(); + for (const problem of await list.listProblems()) { + if (shouldHideSolved && problem.state === ProblemState.AC) { + continue; + } + this.explorerNodeMap.set(problem.id, new LeetCodeNode(problem)); + for (const company of problem.companies) { + this.companySet.add(company); + } + for (const tag of problem.tags) { + this.tagSet.add(tag); + } + } + } + + public getRootNodes(): LeetCodeNode[] { + return [ + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: Category.All, + name: Category.All, + }), false), + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: Category.Difficulty, + name: Category.Difficulty, + }), false), + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: Category.Tag, + name: Category.Tag, + }), false), + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: Category.Company, + name: Category.Company, + }), false), + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: Category.Favorite, + name: Category.Favorite, + }), false), + ]; + } + + public getAllNodes(): LeetCodeNode[] { + return this.applySortingStrategy( + Array.from(this.explorerNodeMap.values()), + ); + } + + public getAllDifficultyNodes(): LeetCodeNode[] { + const res: LeetCodeNode[] = []; + res.push( + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: `${Category.Difficulty}.Easy`, + name: "Easy", + }), false), + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: `${Category.Difficulty}.Medium`, + name: "Medium", + }), false), + new LeetCodeNode(Object.assign({}, defaultProblem, { + id: `${Category.Difficulty}.Hard`, + name: "Hard", + }), false), + ); + this.sortSubCategoryNodes(res, Category.Difficulty); + return res; + } + + public getAllCompanyNodes(): LeetCodeNode[] { + const res: LeetCodeNode[] = []; + for (const company of this.companySet.values()) { + res.push(new LeetCodeNode(Object.assign({}, defaultProblem, { + id: `${Category.Company}.${company}`, + name: _.startCase(company), + }), false)); + } + this.sortSubCategoryNodes(res, Category.Company); + return res; + } + + public getAllTagNodes(): LeetCodeNode[] { + const res: LeetCodeNode[] = []; + for (const tag of this.tagSet.values()) { + res.push(new LeetCodeNode(Object.assign({}, defaultProblem, { + id: `${Category.Tag}.${tag}`, + name: _.startCase(tag), + }), false)); + } + this.sortSubCategoryNodes(res, Category.Tag); + return res; + } + + public getNodeById(id: string): LeetCodeNode | undefined { + return this.explorerNodeMap.get(id); + } + + public getFavoriteNodes(): LeetCodeNode[] { + const res: LeetCodeNode[] = []; + for (const node of this.explorerNodeMap.values()) { + if (node.isFavorite) { + res.push(node); + } + } + return this.applySortingStrategy(res); + } + + public getChildrenNodesById(id: string): LeetCodeNode[] { + // The sub-category node's id is named as {Category.SubName} + const metaInfo: string[] = id.split("."); + const res: LeetCodeNode[] = []; + for (const node of this.explorerNodeMap.values()) { + switch (metaInfo[0]) { + case Category.Company: + if (node.companies.indexOf(metaInfo[1]) >= 0) { + res.push(node); + } + break; + case Category.Difficulty: + if (node.difficulty === metaInfo[1]) { + res.push(node); + } + break; + case Category.Tag: + if (node.tags.indexOf(metaInfo[1]) >= 0) { + res.push(node); + } + break; + default: + break; + } + } + return this.applySortingStrategy(res); + } + + public dispose(): void { + this.explorerNodeMap.clear(); + this.companySet.clear(); + this.tagSet.clear(); + } + + private sortSubCategoryNodes(subCategoryNodes: LeetCodeNode[], category: Category): void { + switch (category) { + case Category.Difficulty: + subCategoryNodes.sort((a: LeetCodeNode, b: LeetCodeNode): number => { + function getValue(input: LeetCodeNode): number { + switch (input.name.toLowerCase()) { + case "easy": + return 1; + case "medium": + return 2; + case "hard": + return 3; + default: + return Number.MAX_SAFE_INTEGER; + } + } + return getValue(a) - getValue(b); + }); + break; + case Category.Tag: + case Category.Company: + subCategoryNodes.sort((a: LeetCodeNode, b: LeetCodeNode): number => { + if (a.name === "Unknown") { + return 1; + } else if (b.name === "Unknown") { + return -1; + } else { + return Number(a.name > b.name) - Number(a.name < b.name); + } + }); + break; + default: + break; + } + } + + private applySortingStrategy(nodes: LeetCodeNode[]): LeetCodeNode[] { + const strategy: SortingStrategy = getSortingStrategy(); + switch (strategy) { + case SortingStrategy.AcceptanceRateAsc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(x.acceptanceRate) - Number(y.acceptanceRate)); + case SortingStrategy.AcceptanceRateDesc: return nodes.sort((x: LeetCodeNode, y: LeetCodeNode) => Number(y.acceptanceRate) - Number(x.acceptanceRate)); + default: return nodes; + } + } +} + +export const explorerNodeManager: ExplorerNodeManager = new ExplorerNodeManager(); diff --git a/src/extension.ts b/src/extension.ts index 877ff90c..439673f8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -8,10 +8,13 @@ import { switchDefaultLanguage } from "./commands/language"; import * as plugin from "./commands/plugin"; import * as session from "./commands/session"; import * as show from "./commands/show"; +import * as star from "./commands/star"; import * as submit from "./commands/submit"; import * as test from "./commands/test"; +import { explorerNodeManager } from "./explorer/explorerNodeManager"; import { LeetCodeNode } from "./explorer/LeetCodeNode"; -import { LeetCodeTreeDataProvider } from "./explorer/LeetCodeTreeDataProvider"; +import { leetCodeTreeDataProvider } from "./explorer/LeetCodeTreeDataProvider"; +import { leetCodeTreeItemDecorationProvider } from "./explorer/LeetCodeTreeItemDecorationProvider"; import { leetCodeChannel } from "./leetCodeChannel"; import { leetCodeExecutor } from "./leetCodeExecutor"; import { leetCodeManager } from "./leetCodeManager"; @@ -21,10 +24,12 @@ import { leetCodePreviewProvider } from "./webview/leetCodePreviewProvider"; import { leetCodeSolutionProvider } from "./webview/leetCodeSolutionProvider"; import { leetCodeSubmissionProvider } from "./webview/leetCodeSubmissionProvider"; import { markdownEngine } from "./webview/markdownEngine"; +import TrackData from "./utils/trackingUtils"; +import { globalState } from "./globalState"; export async function activate(context: vscode.ExtensionContext): Promise { try { - if (!await leetCodeExecutor.meetRequirements()) { + if (!(await leetCodeExecutor.meetRequirements(context))) { throw new Error("The environment doesn't meet requirements."); } @@ -33,7 +38,8 @@ export async function activate(context: vscode.ExtensionContext): Promise leetCodeTreeDataProvider.refresh(); }); - const leetCodeTreeDataProvider: LeetCodeTreeDataProvider = new LeetCodeTreeDataProvider(context); + leetCodeTreeDataProvider.initialize(context); + globalState.initialize(context); context.subscriptions.push( leetCodeStatusBarController, @@ -44,25 +50,59 @@ export async function activate(context: vscode.ExtensionContext): Promise leetCodeExecutor, markdownEngine, codeLensController, + explorerNodeManager, + vscode.window.registerFileDecorationProvider(leetCodeTreeItemDecorationProvider), vscode.window.createTreeView("leetCodeExplorer", { treeDataProvider: leetCodeTreeDataProvider, showCollapseAll: true }), vscode.commands.registerCommand("leetcode.deleteCache", () => cache.deleteCache()), vscode.commands.registerCommand("leetcode.toggleLeetCodeCn", () => plugin.switchEndpoint()), vscode.commands.registerCommand("leetcode.signin", () => leetCodeManager.signIn()), vscode.commands.registerCommand("leetcode.signout", () => leetCodeManager.signOut()), - vscode.commands.registerCommand("leetcode.selectSessions", () => session.selectSession()), - vscode.commands.registerCommand("leetcode.createSession", () => session.createSession()), - vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => show.previewProblem(node)), + vscode.commands.registerCommand("leetcode.manageSessions", () => session.manageSessions()), + vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => { + TrackData.report({ + event_key: `vscode_open_problem`, + type: "click", + extra: JSON.stringify({ + problem_id: node.id, + problem_name: node.name, + }), + }); + show.previewProblem(node); + }), vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)), + vscode.commands.registerCommand("leetcode.pickOne", () => show.pickOne()), vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()), - vscode.commands.registerCommand("leetcode.showSolution", (node: LeetCodeNode) => show.showSolution(node)), + vscode.commands.registerCommand("leetcode.showSolution", (input: LeetCodeNode | vscode.Uri) => show.showSolution(input)), vscode.commands.registerCommand("leetcode.refreshExplorer", () => leetCodeTreeDataProvider.refresh()), - vscode.commands.registerCommand("leetcode.testSolution", (uri?: vscode.Uri) => test.testSolution(uri)), - vscode.commands.registerCommand("leetcode.submitSolution", (uri?: vscode.Uri) => submit.submitSolution(uri)), + vscode.commands.registerCommand("leetcode.testSolution", (uri?: vscode.Uri) => { + TrackData.report({ + event_key: `vscode_runCode`, + type: "click", + extra: JSON.stringify({ + path: uri?.path, + }), + }); + return test.testSolution(uri); + }), + vscode.commands.registerCommand("leetcode.submitSolution", (uri?: vscode.Uri) => { + TrackData.report({ + event_key: `vscode_submit`, + type: "click", + extra: JSON.stringify({ + path: uri?.path, + }), + }); + return submit.submitSolution(uri); + }), vscode.commands.registerCommand("leetcode.switchDefaultLanguage", () => switchDefaultLanguage()), + vscode.commands.registerCommand("leetcode.addFavorite", (node: LeetCodeNode) => star.addFavorite(node)), + vscode.commands.registerCommand("leetcode.removeFavorite", (node: LeetCodeNode) => star.removeFavorite(node)), + vscode.commands.registerCommand("leetcode.problems.sort", () => plugin.switchSortingStrategy()) ); await leetCodeExecutor.switchEndpoint(plugin.getLeetCodeEndpoint()); - leetCodeManager.getLoginStatus(); + await leetCodeManager.getLoginStatus(); + vscode.window.registerUriHandler({ handleUri: leetCodeManager.handleUriSignIn }); } catch (error) { leetCodeChannel.appendLine(error.toString()); promptForOpenOutputChannel("Extension initialization failed. Please open output channel for details.", DialogType.error); diff --git a/src/globalState.ts b/src/globalState.ts new file mode 100644 index 00000000..49d38421 --- /dev/null +++ b/src/globalState.ts @@ -0,0 +1,55 @@ +// Copyright (c) leo.zhao. All rights reserved. +// Licensed under the MIT license. + +import * as vscode from "vscode"; + +const CookieKey = "leetcode-cookie"; +const UserStatusKey = "leetcode-user-status"; + +export type UserDataType = { + isSignedIn: boolean; + isPremium: boolean; + username: string; + avatar: string; + isVerified?: boolean; +}; + +class GlobalState { + private context: vscode.ExtensionContext; + private _state: vscode.Memento; + private _cookie: string; + private _userStatus: UserDataType; + + public initialize(context: vscode.ExtensionContext): void { + this.context = context; + this._state = this.context.globalState; + } + + public setCookie(cookie: string): any { + this._cookie = cookie; + return this._state.update(CookieKey, this._cookie); + } + public getCookie(): string | undefined { + return this._cookie ?? this._state.get(CookieKey); + } + + public setUserStatus(userStatus: UserDataType): any { + this._userStatus = userStatus; + return this._state.update(UserStatusKey, this._userStatus); + } + + public getUserStatus(): UserDataType | undefined { + return this._userStatus ?? this._state.get(UserStatusKey); + } + + public removeCookie(): void { + this._state.update(CookieKey, undefined); + } + + public removeAll(): void { + this._state.update(CookieKey, undefined); + this._state.update(UserStatusKey, undefined); + } +} + +export const globalState: GlobalState = new GlobalState(); diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts index 27b896c1..d2332c7a 100644 --- a/src/leetCodeExecutor.ts +++ b/src/leetCodeExecutor.ts @@ -3,25 +3,24 @@ import * as cp from "child_process"; import * as fse from "fs-extra"; +import * as os from "os"; import * as path from "path"; import * as requireFromString from "require-from-string"; +import { ExtensionContext } from "vscode"; import { ConfigurationChangeEvent, Disposable, MessageItem, window, workspace, WorkspaceConfiguration } from "vscode"; -import { Endpoint, IProblem, supportedPlugins } from "./shared"; +import { Endpoint, IProblem, leetcodeHasInited, supportedPlugins } from "./shared"; import { executeCommand, executeCommandWithProgress } from "./utils/cpUtils"; -import { genFileName } from "./utils/problemUtils"; import { DialogOptions, openUrl } from "./utils/uiUtils"; import * as wsl from "./utils/wslUtils"; import { toWslPath, useWsl } from "./utils/wslUtils"; class LeetCodeExecutor implements Disposable { private leetCodeRootPath: string; - private leetCodeRootPathInWsl: string; private nodeExecutable: string; private configurationChangeListener: Disposable; constructor() { this.leetCodeRootPath = path.join(__dirname, "..", "..", "node_modules", "vsc-leetcode-cli"); - this.leetCodeRootPathInWsl = ""; this.nodeExecutable = this.getNodePath(); this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { if (event.affectsConfiguration("leetcode.nodePath")) { @@ -30,25 +29,24 @@ class LeetCodeExecutor implements Disposable { }, this); } - public async getLeetCodeRootPath(): Promise { // not wrapped by "" + public async getLeetCodeBinaryPath(): Promise { if (wsl.useWsl()) { - if (!this.leetCodeRootPathInWsl) { - this.leetCodeRootPathInWsl = `${await wsl.toWslPath(this.leetCodeRootPath)}`; - } - return `${this.leetCodeRootPathInWsl}`; + return `${await wsl.toWslPath(`"${path.join(this.leetCodeRootPath, "bin", "leetcode")}"`)}`; } - return `${this.leetCodeRootPath}`; - } - - public async getLeetCodeBinaryPath(): Promise { // wrapped by "" - return `"${path.join(await this.getLeetCodeRootPath(), "bin", "leetcode")}"`; + return `"${path.join(this.leetCodeRootPath, "bin", "leetcode")}"`; } - public async meetRequirements(): Promise { + public async meetRequirements(context: ExtensionContext): Promise { + const hasInited: boolean | undefined = context.globalState.get(leetcodeHasInited); + if (!hasInited) { + await this.removeOldCache(); + } if (this.nodeExecutable !== "node") { if (!await fse.pathExists(this.nodeExecutable)) { throw new Error(`The Node.js executable does not exist on path ${this.nodeExecutable}`); } + // Wrap the executable with "" to avoid space issue in the path. + this.nodeExecutable = `"${this.nodeExecutable}"`; if (useWsl()) { this.nodeExecutable = await toWslPath(this.nodeExecutable); } @@ -68,10 +66,13 @@ class LeetCodeExecutor implements Disposable { for (const plugin of supportedPlugins) { try { // Check plugin await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "plugin", "-e", plugin]); - } catch (error) { // Download plugin and activate + } catch (error) { // Remove old cache that may cause the error download plugin and activate + await this.removeOldCache(); await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "plugin", "-i", plugin]); } } + // Set the global state HasInited true to skip delete old cache after init + context.globalState.update(leetcodeHasInited, true); return true; } @@ -84,36 +85,65 @@ class LeetCodeExecutor implements Disposable { } public async signOut(): Promise { - return await await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user", "-L"]); + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user", "-L"]); } - public async listProblems(showLocked: boolean): Promise { - return await this.executeCommandEx(this.nodeExecutable, showLocked ? - [await this.getLeetCodeBinaryPath(), "list"] : - [await this.getLeetCodeBinaryPath(), "list", "-q", "L"], - ); + public async listProblems(showLocked: boolean, needTranslation: boolean): Promise { + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "list"]; + if (!needTranslation) { + cmd.push("-T"); // use -T to prevent translation + } + if (!showLocked) { + cmd.push("-q"); + cmd.push("L"); + } + return await this.executeCommandEx(this.nodeExecutable, cmd); } - public async showProblem(problemNode: IProblem, language: string, outDir: string, detailed: boolean = false): Promise { - const fileName: string = genFileName(problemNode, language); - const filePath: string = path.join(outDir, fileName); - const templateType: string = detailed ? "-cx" : "-c"; + public async showProblem(problemNode: IProblem, language: string, filePath: string, showDescriptionInComment: boolean = false, needTranslation: boolean): Promise { + const templateType: string = showDescriptionInComment ? "-cx" : "-c"; + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNode.id, templateType, "-l", language]; + + if (!needTranslation) { + cmd.push("-T"); // use -T to force English version + } if (!await fse.pathExists(filePath)) { - const codeTemplate: string = await this.executeCommandWithProgressEx("Fetching problem data...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", problemNode.id, templateType, "-l", language]); + await fse.createFile(filePath); + const codeTemplate: string = await this.executeCommandWithProgressEx("Fetching problem data...", this.nodeExecutable, cmd); await fse.writeFile(filePath, codeTemplate); } - - return filePath; } - public async showSolution(problemNode: IProblem, language: string): Promise { - const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "--solution", "-l", language]); + /** + * This function returns solution of a problem identified by input + * + * @remarks + * Even though this function takes the needTranslation flag, it is important to note + * that as of vsc-leetcode-cli 2.8.0, leetcode-cli doesn't support querying solution + * on CN endpoint yet. So this flag doesn't have any effect right now. + * + * @param input - parameter to pass to cli that can identify a problem + * @param language - the source code language of the solution desired + * @param needTranslation - whether or not to use endPoint translation on solution query + * @returns promise of the solution string + */ + public async showSolution(input: string, language: string, needTranslation: boolean): Promise { + // solution don't support translation + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language]; + if (!needTranslation) { + cmd.push("-T"); + } + const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, cmd); return solution; } - public async getDescription(problemNode: IProblem): Promise { - return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "-x"]); + public async getDescription(problemNodeId: string, needTranslation: boolean): Promise { + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNodeId, "-x"]; + if (!needTranslation) { + cmd.push("-T"); + } + return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, cmd); } public async listSessions(): Promise { @@ -124,8 +154,12 @@ class LeetCodeExecutor implements Disposable { return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-e", name]); } - public async createSession(name: string): Promise { - return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-c", name]); + public async createSession(id: string): Promise { + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-c", id]); + } + + public async deleteSession(id: string): Promise { + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "session", "-d", id]); } public async submitSolution(filePath: string): Promise { @@ -156,9 +190,17 @@ class LeetCodeExecutor implements Disposable { } } + public async toggleFavorite(node: IProblem, addToFavorite: boolean): Promise { + const commandParams: string[] = [await this.getLeetCodeBinaryPath(), "star", node.id]; + if (!addToFavorite) { + commandParams.push("-d"); + } + await this.executeCommandWithProgressEx("Updating the favorite list...", "node", commandParams); + } + public async getCompaniesAndTags(): Promise<{ companies: { [key: string]: string[] }, tags: { [key: string]: string[] } }> { // preprocess the plugin source - const companiesTagsPath: string = path.join(await leetCodeExecutor.getLeetCodeRootPath(), "lib", "plugins", "company.js"); + const companiesTagsPath: string = path.join(this.leetCodeRootPath, "lib", "plugins", "company.js"); const companiesTagsSrc: string = (await fse.readFile(companiesTagsPath, "utf8")).replace( "module.exports = plugin", "module.exports = { COMPONIES, TAGS }", @@ -193,6 +235,14 @@ class LeetCodeExecutor implements Disposable { } return await executeCommandWithProgress(message, command, args, options); } + + private async removeOldCache(): Promise { + const oldPath: string = path.join(os.homedir(), ".lc"); + if (await fse.pathExists(oldPath)) { + await fse.remove(oldPath); + } + } + } export const leetCodeExecutor: LeetCodeExecutor = new LeetCodeExecutor(); diff --git a/src/leetCodeManager.ts b/src/leetCodeManager.ts index a5f1cb3e..16ec3782 100644 --- a/src/leetCodeManager.ts +++ b/src/leetCodeManager.ts @@ -6,19 +6,26 @@ import { EventEmitter } from "events"; import * as vscode from "vscode"; import { leetCodeChannel } from "./leetCodeChannel"; import { leetCodeExecutor } from "./leetCodeExecutor"; -import { UserStatus } from "./shared"; +import { Endpoint, IQuickItemEx, loginArgsMapping, urls, urlsCn, UserStatus } from "./shared"; import { createEnvOption } from "./utils/cpUtils"; -import { DialogType, promptForOpenOutputChannel } from "./utils/uiUtils"; +import { DialogType, openUrl, promptForOpenOutputChannel } from "./utils/uiUtils"; import * as wsl from "./utils/wslUtils"; +import { getLeetCodeEndpoint } from "./commands/plugin"; +import { globalState } from "./globalState"; +import { queryUserData } from "./request/query-user-data"; +import { parseQuery } from "./utils/toolUtils"; class LeetCodeManager extends EventEmitter { private currentUser: string | undefined; private userStatus: UserStatus; + private readonly successRegex: RegExp = /(?:.*)Successfully .*login as (.*)/i; + private readonly failRegex: RegExp = /.*\[ERROR\].*/i; constructor() { super(); this.currentUser = undefined; this.userStatus = UserStatus.SignedOut; + this.handleUriSignIn = this.handleUriSignIn.bind(this); } public async getLoginStatus(): Promise { @@ -29,73 +36,90 @@ class LeetCodeManager extends EventEmitter { } catch (error) { this.currentUser = undefined; this.userStatus = UserStatus.SignedOut; + globalState.removeAll(); } finally { this.emit("statusChanged"); } } - public async signIn(): Promise { + private async updateUserStatusWithCookie(cookie: string): Promise { + globalState.setCookie(cookie); + const data = await queryUserData(); + globalState.setUserStatus(data); + await this.setCookieToCli(cookie, data.username); + if (data.username) { + vscode.window.showInformationMessage(`Successfully ${data.username}.`); + this.currentUser = data.username; + this.userStatus = UserStatus.SignedIn; + this.emit("statusChanged"); + } + } + + public async handleUriSignIn(uri: vscode.Uri): Promise { try { - const userName: string | undefined = await new Promise(async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => { - let result: string = ""; - - const leetCodeBinaryPath: string = await leetCodeExecutor.getLeetCodeBinaryPath(); - - const childProc: cp.ChildProcess = wsl.useWsl() - ? cp.spawn("wsl", [leetCodeExecutor.node, leetCodeBinaryPath, "user", "-l"], { shell: true }) - : cp.spawn(leetCodeExecutor.node, [leetCodeBinaryPath, "user", "-l"], { - shell: true, - env: createEnvOption(), - }); - - childProc.stdout.on("data", (data: string | Buffer) => { - data = data.toString(); - result = result.concat(data); - leetCodeChannel.append(data); - }); - - childProc.stderr.on("data", (data: string | Buffer) => leetCodeChannel.append(data.toString())); - - childProc.on("error", reject); - const name: string | undefined = await vscode.window.showInputBox({ - prompt: "Enter user name.", - validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "User name must not be empty", - }); - if (!name) { - childProc.kill(); - return resolve(undefined); - } - childProc.stdin.write(`${name}\n`); - const pwd: string | undefined = await vscode.window.showInputBox({ - prompt: "Enter password.", - password: true, - validateInput: (s: string): string | undefined => s ? undefined : "Password must not be empty", - }); - if (!pwd) { - childProc.kill(); - return resolve(undefined); + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (progress: vscode.Progress<{}>) => { + progress.report({ message: "Fetching user data..." }); + const queryParams = parseQuery(uri.query); + const cookie = queryParams["cookie"]; + if (!cookie) { + promptForOpenOutputChannel(`Failed to get cookie. Please log in again`, DialogType.error); + return; } - childProc.stdin.write(`${pwd}\n`); - childProc.stdin.end(); - childProc.on("close", () => { - const match: RegExpMatchArray | null = result.match(/(?:.*) Successfully login as (.*)/i); - if (match && match[1]) { - resolve(match[1]); - } else { - reject(new Error("Failed to sign in.")); - } - }); + + await this.updateUserStatusWithCookie(cookie) + }); - if (userName) { - vscode.window.showInformationMessage("Successfully signed in."); - this.currentUser = userName; - this.userStatus = UserStatus.SignedIn; - this.emit("statusChanged"); - } } catch (error) { - promptForOpenOutputChannel("Failed to sign in. Please open the output channel for details", DialogType.error); + promptForOpenOutputChannel(`Failed to log in. Please open the output channel for details`, DialogType.error); + } + } + + public async handleInputCookieSignIn(): Promise { + const cookie: string | undefined = await vscode.window.showInputBox({ + prompt: 'Enter LeetCode Cookie', + password: true, + ignoreFocusOut: true, + validateInput: (s: string): string | undefined => + s ? undefined : 'Cookie must not be empty', + }) + + await this.updateUserStatusWithCookie(cookie || '') + } + + public async signIn(): Promise { + const picks: Array> = [] + picks.push( + { + label: 'Web Authorization', + detail: 'Open browser to authorize login on the website', + value: 'WebAuth', + description: '[Recommended]' + }, + { + label: 'LeetCode Cookie', + detail: 'Use LeetCode cookie copied from browser to login', + value: 'Cookie', + } + ) + + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks) + if (!choice) { + return } + const loginMethod: string = choice.value + if (loginMethod === 'WebAuth') { + openUrl(this.getAuthLoginUrl()) + return + } + + try { + await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: "Fetching user data..." }, async () => { + await this.handleInputCookieSignIn() + }); + } catch (error) { + promptForOpenOutputChannel(`Failed to log in. Please open the output channel for details`, DialogType.error); + } } public async signOut(): Promise { @@ -104,6 +128,7 @@ class LeetCodeManager extends EventEmitter { vscode.window.showInformationMessage("Successfully signed out."); this.currentUser = undefined; this.userStatus = UserStatus.SignedOut; + globalState.removeAll(); this.emit("statusChanged"); } catch (error) { // swallow the error when sign out. @@ -127,6 +152,52 @@ class LeetCodeManager extends EventEmitter { return "Unknown"; } + + public getAuthLoginUrl(): string { + switch (getLeetCodeEndpoint()) { + case Endpoint.LeetCodeCN: + return urlsCn.authLoginUrl; + case Endpoint.LeetCode: + default: + return urls.authLoginUrl; + } + } + + public setCookieToCli(cookie: string, name: string): Promise { + return new Promise(async (resolve: (res: void) => void, reject: (e: Error) => void) => { + const leetCodeBinaryPath: string = await leetCodeExecutor.getLeetCodeBinaryPath(); + + const childProc: cp.ChildProcess = wsl.useWsl() + ? cp.spawn("wsl", [leetCodeExecutor.node, leetCodeBinaryPath, "user", loginArgsMapping.get("Cookie") ?? ""], { + shell: true, + }) + : cp.spawn(leetCodeExecutor.node, [leetCodeBinaryPath, "user", loginArgsMapping.get("Cookie") ?? ""], { + shell: true, + env: createEnvOption(), + }); + + childProc.stdout?.on("data", async (data: string | Buffer) => { + data = data.toString(); + leetCodeChannel.append(data); + const successMatch: RegExpMatchArray | null = data.match(this.successRegex); + if (successMatch && successMatch[1]) { + childProc.stdin?.end(); + return resolve(); + } else if (data.match(this.failRegex)) { + childProc.stdin?.end(); + return reject(new Error("Faile to login")); + } else if (data.match(/login: /)) { + childProc.stdin?.write(`${name}\n`); + } else if (data.match(/cookie: /)) { + childProc.stdin?.write(`${cookie}\n`); + } + }); + + childProc.stderr?.on("data", (data: string | Buffer) => leetCodeChannel.append(data.toString())); + + childProc.on("error", reject); + }); + } } export const leetCodeManager: LeetCodeManager = new LeetCodeManager(); diff --git a/src/request/query-user-data.ts b/src/request/query-user-data.ts new file mode 100644 index 00000000..ffcca1e1 --- /dev/null +++ b/src/request/query-user-data.ts @@ -0,0 +1,25 @@ +import { UserDataType } from "../globalState"; +import { getUrl } from "../shared"; +import { LcAxios } from "../utils/httpUtils"; + +const graphqlStr = ` + query globalData { + userStatus { + isPremium + isVerified + username + avatar + isSignedIn + } + } +`; + +export const queryUserData = async (): Promise => { + return LcAxios(getUrl("userGraphql"), { + method: "POST", + data: { + query: graphqlStr, + variables: {}, + }, + }).then((res) => res.data.data.userStatus); +}; diff --git a/src/shared.ts b/src/shared.ts index f543cd47..e8b59d89 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -12,6 +12,13 @@ export enum UserStatus { SignedOut = 2, } +export const loginArgsMapping: Map = new Map([ + ["LeetCode", "-l"], + ["Cookie", "-c"], + ["GitHub", "-g"], + ["LinkedIn", "-i"], +]); + export const languages: string[] = [ "bash", "c", @@ -29,6 +36,7 @@ export const languages: string[] = [ "rust", "scala", "swift", + "typescript", ]; export const langExt: Map = new Map([ @@ -48,12 +56,14 @@ export const langExt: Map = new Map([ ["rust", "rs"], ["scala", "scala"], ["swift", "swift"], + ["typescript", "ts"], ]); export enum ProblemState { AC = 1, NotAC = 2, Unknown = 3, + Locked = 4, } export enum Endpoint { @@ -86,14 +96,63 @@ export const defaultProblem: IProblem = { }; export enum Category { + All = "All", Difficulty = "Difficulty", Tag = "Tag", Company = "Company", Favorite = "Favorite", } -export const supportedPlugins: string[] = [ - "company", - "solution.discuss", - "leetcode.cn", -]; +export const supportedPlugins: string[] = ["company", "solution.discuss", "leetcode.cn"]; + +export enum DescriptionConfiguration { + InWebView = "In Webview", + InFileComment = "In File Comment", + Both = "Both", + None = "None", +} + +export const leetcodeHasInited: string = "leetcode.hasInited"; + +export enum SortingStrategy { + None = "None", + AcceptanceRateAsc = "Acceptance Rate (Ascending)", + AcceptanceRateDesc = "Acceptance Rate (Descending)", + FrequencyAsc = "Frequency (Ascending)", + FrequencyDesc = "Frequency (Descending)", +} + +export const PREMIUM_URL_CN = "https://leetcode.cn/premium-payment/?source=vscode"; +export const PREMIUM_URL_GLOBAL = "https://leetcode.com/subscribe/?ref=lp_pl&source=vscode"; + +const protocol = vscode.env.appName.includes('Insiders') ? "vscode-insiders" : "vscode" + +export const urls = { + // base urls + base: "https://leetcode.com", + graphql: "https://leetcode.com/graphql", + userGraphql: "https://leetcode.com/graphql", + login: "https://leetcode.com/accounts/login/", + authLoginUrl: `https://leetcode.com/authorize-login/${protocol}/?path=leetcode.vscode-leetcode`, +}; + +export const urlsCn = { + // base urls + base: "https://leetcode.cn", + graphql: "https://leetcode.cn/graphql", + userGraphql: "https://leetcode.cn/graphql/", + login: "https://leetcode.cn/accounts/login/", + authLoginUrl: `https://leetcode.cn/authorize-login/${protocol}/?path=leetcode.vscode-leetcode`, +}; + +export const getUrl = (key: string) => { + const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); + const point = leetCodeConfig.get("endpoint", Endpoint.LeetCode); + switch (point) { + case Endpoint.LeetCodeCN: + return urlsCn[key]; + case Endpoint.LeetCode: + default: + return urls[key]; + } +}; diff --git a/src/statusbar/LeetCodeStatusBarItem.ts b/src/statusbar/LeetCodeStatusBarItem.ts index 5ca9bde6..35ca7412 100644 --- a/src/statusbar/LeetCodeStatusBarItem.ts +++ b/src/statusbar/LeetCodeStatusBarItem.ts @@ -9,7 +9,7 @@ export class LeetCodeStatusBarItem implements vscode.Disposable { constructor() { this.statusBarItem = vscode.window.createStatusBarItem(); - this.statusBarItem.command = "leetcode.selectSessions"; + this.statusBarItem.command = "leetcode.manageSessions"; } public updateStatusBar(status: UserStatus, user?: string): void { diff --git a/src/utils/cpUtils.ts b/src/utils/cpUtils.ts index 59e907b6..c71ae61c 100644 --- a/src/utils/cpUtils.ts +++ b/src/utils/cpUtils.ts @@ -15,13 +15,13 @@ export async function executeCommand(command: string, args: string[], options: c const childProc: cp.ChildProcess = cp.spawn(command, args, { ...options, env: createEnvOption() }); - childProc.stdout.on("data", (data: string | Buffer) => { + childProc.stdout?.on("data", (data: string | Buffer) => { data = data.toString(); result = result.concat(data); leetCodeChannel.append(data); }); - childProc.stderr.on("data", (data: string | Buffer) => leetCodeChannel.append(data.toString())); + childProc.stderr?.on("data", (data: string | Buffer) => leetCodeChannel.append(data.toString())); childProc.on("error", reject); @@ -42,7 +42,7 @@ export async function executeCommand(command: string, args: string[], options: c export async function executeCommandWithProgress(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { let result: string = ""; await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (p: vscode.Progress<{}>) => { - return new Promise(async (resolve: () => void, reject: (e: Error) => void): Promise => { + return new Promise(async (resolve: () => void, reject: (e: Error) => void): Promise => { p.report({ message }); try { result = await executeCommand(command, args, options); diff --git a/src/utils/httpUtils.ts b/src/utils/httpUtils.ts new file mode 100644 index 00000000..b7771734 --- /dev/null +++ b/src/utils/httpUtils.ts @@ -0,0 +1,28 @@ +import axios, { AxiosRequestConfig, AxiosPromise } from "axios"; +import { omit } from "lodash"; +import { globalState } from "../globalState"; +import { DialogType, promptForOpenOutputChannel } from "./uiUtils"; + +const referer = "vscode-lc-extension"; + +export function LcAxios(path: string, settings?: AxiosRequestConfig): AxiosPromise { + const cookie = globalState.getCookie(); + if (!cookie) { + promptForOpenOutputChannel( + `Failed to obtain the cookie. Please log in again.`, + DialogType.error + ); + return Promise.reject("Failed to obtain the cookie."); + } + return axios(path, { + headers: { + referer, + "content-type": "application/json", + cookie, + ...(settings && settings.headers), + }, + xsrfCookieName: "csrftoken", + xsrfHeaderName: "X-CSRFToken", + ...(settings && omit(settings, "headers")), + }); +} diff --git a/src/utils/problemUtils.ts b/src/utils/problemUtils.ts index 10df523b..d2dcc3ed 100644 --- a/src/utils/problemUtils.ts +++ b/src/utils/problemUtils.ts @@ -1,7 +1,9 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. +import * as fse from "fs-extra"; import * as _ from "lodash"; +import * as path from "path"; import { IProblem, langExt } from "../shared"; export function genFileExt(language: string): string { @@ -17,3 +19,18 @@ export function genFileName(node: IProblem, language: string): string { const ext: string = genFileExt(language); return `${node.id}.${slug}.${ext}`; } + +export async function getNodeIdFromFile(fsPath: string): Promise { + const fileContent: string = await fse.readFile(fsPath, "utf8"); + let id: string = ""; + const matchResults: RegExpMatchArray | null = fileContent.match(/@lc.+id=(.+?) /); + if (matchResults && matchResults.length === 2) { + id = matchResults[1]; + } + // Try to get id from file name if getting from comments failed + if (!id) { + id = path.basename(fsPath).split(".")[0]; + } + + return id; +} diff --git a/src/utils/settingUtils.ts b/src/utils/settingUtils.ts new file mode 100644 index 00000000..7b6eb6c2 --- /dev/null +++ b/src/utils/settingUtils.ts @@ -0,0 +1,68 @@ +// Copyright (c) jdneo. All rights reserved. +// Licensed under the MIT license. + +import { workspace, WorkspaceConfiguration } from "vscode"; +import { DescriptionConfiguration } from "../shared"; + +export function getWorkspaceConfiguration(): WorkspaceConfiguration { + return workspace.getConfiguration("leetcode"); +} + +export function shouldHideSolvedProblem(): boolean { + return getWorkspaceConfiguration().get("hideSolved", false); +} + +export function getWorkspaceFolder(): string { + return getWorkspaceConfiguration().get("workspaceFolder", ""); +} + +export function getEditorShortcuts(): string[] { + return getWorkspaceConfiguration().get("editor.shortcuts", ["submit", "test"]); +} + +export function hasStarShortcut(): boolean { + const shortcuts: string[] = getWorkspaceConfiguration().get("editor.shortcuts", ["submit", "test"]); + return shortcuts.indexOf("star") >= 0; +} + +export function shouldUseEndpointTranslation(): boolean { + return getWorkspaceConfiguration().get("useEndpointTranslation", true); +} + +export function getDescriptionConfiguration(): IDescriptionConfiguration { + const setting: string = getWorkspaceConfiguration().get("showDescription", DescriptionConfiguration.InWebView); + const config: IDescriptionConfiguration = { + showInComment: false, + showInWebview: true, + }; + switch (setting) { + case DescriptionConfiguration.Both: + config.showInComment = true; + config.showInWebview = true; + break; + case DescriptionConfiguration.None: + config.showInComment = false; + config.showInWebview = false; + break; + case DescriptionConfiguration.InFileComment: + config.showInComment = true; + config.showInWebview = false; + break; + case DescriptionConfiguration.InWebView: + config.showInComment = false; + config.showInWebview = true; + break; + } + + // To be compatible with the deprecated setting: + if (getWorkspaceConfiguration().get("showCommentDescription")) { + config.showInComment = true; + } + + return config; +} + +export interface IDescriptionConfiguration { + showInComment: boolean; + showInWebview: boolean; +} diff --git a/src/utils/toolUtils.ts b/src/utils/toolUtils.ts new file mode 100644 index 00000000..ce37e185 --- /dev/null +++ b/src/utils/toolUtils.ts @@ -0,0 +1,26 @@ +export function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export function parseQuery(query: string): { [key: string]: string } { + const queryObject: { [key: string]: string } = {}; + + if (!query) { + return queryObject; + } + + const keyValuePairs = query.split("&"); + keyValuePairs.forEach((pair) => { + const firstEqualsIndex = pair.indexOf("="); + if (firstEqualsIndex !== -1) { + const key = pair.substring(0, firstEqualsIndex); + const value = pair.substring(firstEqualsIndex + 1); + queryObject[decodeURIComponent(key)] = decodeURIComponent(value); + } else { + // If no equals sign is found, treat the whole string as key with empty value + queryObject[decodeURIComponent(pair)] = ""; + } + }); + + return queryObject; +} diff --git a/src/utils/trackingUtils.ts b/src/utils/trackingUtils.ts new file mode 100644 index 00000000..56b1a6fb --- /dev/null +++ b/src/utils/trackingUtils.ts @@ -0,0 +1,130 @@ +import * as vscode from "vscode"; +import axios from "axios"; +import { getLeetCodeEndpoint } from "../commands/plugin"; +import { Endpoint } from "../shared"; +import { leetCodeManager } from "../leetCodeManager"; + +const getTimeZone = (): string => { + const endPoint: string = getLeetCodeEndpoint(); + if (endPoint === Endpoint.LeetCodeCN) { + return "Asia/Shanghai"; + } else { + return "UTC"; + } +}; + +interface IReportData { + event_key: string; + type?: "click" | "expose" | string; + anonymous_id?: string; + tid?: number; + ename?: string; // event name + href?: string; + referer?: string; + extra?: string; + target?: string; +} + +interface ITrackData { + reportCache: IReportData[]; + isSubmit: boolean; + report: (reportItems: IReportData | IReportData[]) => void; + submitReport: (useSendBeason: boolean) => Promise; + reportUrl: string; +} + +const testReportUrl = "https://analysis.lingkou.xyz/i/event"; +const prodReportUrl = "https://analysis.leetcode.cn/i/event"; + +function getReportUrl() { + if (process.env.NODE_ENV === "production") { + return prodReportUrl; + } else { + return testReportUrl; + } +} + +const _charStr = "abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+="; + +function RandomIndex(min: number, max: number, i: number) { + let index = Math.floor(Math.random() * (max - min + 1) + min); + const numStart = _charStr.length - 10; + if (i === 0 && index >= numStart) { + index = RandomIndex(min, max, i); + } + return index; +} + +function getRandomString(len: number) { + const min = 0; + const max = _charStr.length - 1; + let _str = ""; + len = len || 15; + for (let i = 0, index; i < len; i++) { + index = RandomIndex(min, max, i); + _str += _charStr[index]; + } + return _str; +} + +function getAllowReportDataConfig() { + const leetCodeConfig = vscode.workspace.getConfiguration("leetcode"); + const allowReportData = !!leetCodeConfig.get("allowReportData"); + return allowReportData; +} + +class TrackData implements ITrackData { + public reportCache: IReportData[] = []; + + public isSubmit: boolean = false; + + public reportUrl: string = getReportUrl(); + + private sendTimer: NodeJS.Timeout | undefined; + + public report = (reportItems: IReportData | IReportData[]) => { + if (!getAllowReportDataConfig()) return; + + this.sendTimer && clearTimeout(this.sendTimer); + + if (!Array.isArray(reportItems)) { + reportItems = [reportItems]; + } + const randomId = getRandomString(60); + reportItems.forEach((item) => { + this.reportCache.push({ + ...item, + referer: "vscode", + target: leetCodeManager.getUser() ?? "", + anonymous_id: item.anonymous_id ?? (randomId as string), + }); + }); + this.sendTimer = setTimeout(this.submitReport, 800); + }; + + public submitReport = async () => { + if (!getAllowReportDataConfig()) return; + const dataList = JSON.stringify(this.reportCache); + + if (!this.reportCache.length || this.isSubmit) { + return; + } + this.reportCache = []; + try { + this.isSubmit = true; + axios.defaults.withCredentials = true; + await axios.post(this.reportUrl, `dataList=${encodeURIComponent(dataList)}`, { + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "x-timezone": getTimeZone(), + }, + }); + } catch (e) { + this.reportCache = this.reportCache.concat(JSON.parse(dataList)); + } finally { + this.isSubmit = false; + } + }; +} + +export default new TrackData(); diff --git a/src/utils/uiUtils.ts b/src/utils/uiUtils.ts index 845865e8..9e251a55 100644 --- a/src/utils/uiUtils.ts +++ b/src/utils/uiUtils.ts @@ -4,7 +4,7 @@ import * as vscode from "vscode"; import { getLeetCodeEndpoint } from "../commands/plugin"; import { leetCodeChannel } from "../leetCodeChannel"; -import { getWorkspaceConfiguration } from "./workspaceUtils"; +import { getWorkspaceConfiguration } from "./settingUtils"; export namespace DialogOptions { export const open: vscode.MessageItem = { title: "Open" }; @@ -48,7 +48,7 @@ export async function promptForSignIn(): Promise { break; case DialogOptions.singUp: if (getLeetCodeEndpoint()) { - openUrl("https://leetcode-cn.com"); + openUrl("https://leetcode.cn"); } else { openUrl("https://leetcode.com"); } @@ -80,8 +80,8 @@ export async function openKeybindingsEditor(query?: string): Promise { await vscode.commands.executeCommand("workbench.action.openGlobalKeybindings", query); } -export async function showFileSelectDialog(): Promise { - const defaultUri: vscode.Uri | undefined = vscode.workspace.rootPath ? vscode.Uri.file(vscode.workspace.rootPath) : undefined; +export async function showFileSelectDialog(fsPath?: string): Promise { + const defaultUri: vscode.Uri | undefined = getBelongingWorkspaceFolderUri(fsPath); const options: vscode.OpenDialogOptions = { defaultUri, canSelectFiles: true, @@ -92,6 +92,29 @@ export async function showFileSelectDialog(): Promise return await vscode.window.showOpenDialog(options); } +function getBelongingWorkspaceFolderUri(fsPath: string | undefined): vscode.Uri | undefined { + let defaultUri: vscode.Uri | undefined; + if (fsPath) { + const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fsPath)); + if (workspaceFolder) { + defaultUri = workspaceFolder.uri; + } + } + return defaultUri; +} + +export async function showDirectorySelectDialog(fsPath?: string): Promise { + const defaultUri: vscode.Uri | undefined = getBelongingWorkspaceFolderUri(fsPath); + const options: vscode.OpenDialogOptions = { + defaultUri, + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: "Select", + }; + return await vscode.window.showOpenDialog(options); +} + export async function openUrl(url: string): Promise { vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url)); } diff --git a/src/utils/workspaceUtils.ts b/src/utils/workspaceUtils.ts index 425074df..48105d5a 100644 --- a/src/utils/workspaceUtils.ts +++ b/src/utils/workspaceUtils.ts @@ -1,26 +1,62 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the MIT license. +import * as fse from "fs-extra"; import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; +import { IQuickItemEx } from "../shared"; +import { getWorkspaceConfiguration, getWorkspaceFolder } from "./settingUtils"; +import { showDirectorySelectDialog } from "./uiUtils"; import * as wsl from "./wslUtils"; export async function selectWorkspaceFolder(): Promise { - let folder: vscode.WorkspaceFolder | undefined; - if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { - if (vscode.workspace.workspaceFolders.length > 1) { - folder = await vscode.window.showWorkspaceFolderPick({ - placeHolder: "Select the working directory you wish to use", - }); - } else { - folder = vscode.workspace.workspaceFolders[0]; + let workspaceFolderSetting: string = getWorkspaceFolder(); + if (workspaceFolderSetting.trim() === "") { + workspaceFolderSetting = await determineLeetCodeFolder(); + if (workspaceFolderSetting === "") { + // User cancelled + return workspaceFolderSetting; + } + } + let needAsk: boolean = true; + await fse.ensureDir(workspaceFolderSetting); + for (const folder of vscode.workspace.workspaceFolders || []) { + if (isSubFolder(folder.uri.fsPath, workspaceFolderSetting)) { + needAsk = false; } } - const workFolder: string = folder ? folder.uri.fsPath : path.join(os.homedir(), ".leetcode"); + if (needAsk) { + const choice: string | undefined = await vscode.window.showQuickPick( + [ + OpenOption.justOpenFile, + OpenOption.openInCurrentWindow, + OpenOption.openInNewWindow, + OpenOption.addToWorkspace, + ], + { placeHolder: "The LeetCode workspace folder is not opened in VS Code, would you like to open it?" }, + ); - return wsl.useWsl() ? wsl.toWslPath(workFolder) : workFolder; + // Todo: generate file first + switch (choice) { + case OpenOption.justOpenFile: + return workspaceFolderSetting; + case OpenOption.openInCurrentWindow: + await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), false); + return ""; + case OpenOption.openInNewWindow: + await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), true); + return ""; + case OpenOption.addToWorkspace: + vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders?.length ?? 0, 0, { uri: vscode.Uri.file(workspaceFolderSetting) }); + break; + default: + return ""; + } + } + + return wsl.useWsl() ? wsl.toWslPath(workspaceFolderSetting) : workspaceFolderSetting; } export async function getActiveFilePath(uri?: vscode.Uri): Promise { @@ -41,6 +77,53 @@ export async function getActiveFilePath(uri?: vscode.Uri): Promise { + let result: string; + const picks: Array> = []; + picks.push( + { + label: `Default location`, + detail: `${path.join(os.homedir(), ".leetcode")}`, + value: `${path.join(os.homedir(), ".leetcode")}`, + }, + { + label: "$(file-directory) Browse...", + value: ":browse", + }, + ); + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick( + picks, + { placeHolder: "Select where you would like to save your LeetCode files" }, + ); + if (!choice) { + result = ""; + } else if (choice.value === ":browse") { + const directory: vscode.Uri[] | undefined = await showDirectorySelectDialog(); + if (!directory || directory.length < 1) { + result = ""; + } else { + result = directory[0].fsPath; + } + } else { + result = choice.value; + } + + getWorkspaceConfiguration().update("workspaceFolder", result, vscode.ConfigurationTarget.Global); + + return result; +} + +enum OpenOption { + justOpenFile = "Just open the problem file", + openInCurrentWindow = "Open in current window", + openInNewWindow = "Open in new window", + addToWorkspace = "Add to workspace", } diff --git a/src/utils/wslUtils.ts b/src/utils/wslUtils.ts index d496b038..16d83cde 100644 --- a/src/utils/wslUtils.ts +++ b/src/utils/wslUtils.ts @@ -15,5 +15,8 @@ export async function toWslPath(path: string): Promise { } export async function toWinPath(path: string): Promise { - return (await executeCommand("wsl", ["wslpath", "-w", `"${path}"`])).trim(); + if (path.startsWith("\\mnt\\")) { + return (await executeCommand("wsl", ["wslpath", "-w", `"${path.replace(/\\/g, "/").substr(0, 6)}"`])).trim() + path.substr(7); + } + return (await executeCommand("wsl", ["wslpath", "-w", "/"])).trim() + path; } diff --git a/src/webview/leetCodePreviewProvider.ts b/src/webview/leetCodePreviewProvider.ts index 11b32fc4..86060de5 100644 --- a/src/webview/leetCodePreviewProvider.ts +++ b/src/webview/leetCodePreviewProvider.ts @@ -2,12 +2,12 @@ // Licensed under the MIT license. import { commands, ViewColumn } from "vscode"; -import { IProblem } from "../shared"; +import { getLeetCodeEndpoint } from "../commands/plugin"; +import { Endpoint, IProblem } from "../shared"; import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview"; import { markdownEngine } from "./markdownEngine"; class LeetCodePreviewProvider extends LeetCodeWebview { - protected readonly viewType: string = "leetcode.preview"; private node: IProblem; private description: IDescription; @@ -22,9 +22,6 @@ class LeetCodePreviewProvider extends LeetCodeWebview { this.node = node; this.sideMode = isSideMode; this.showWebviewInternal(); - if (this.sideMode) { - this.hideSideBar(); // For better view area - } } protected getWebviewOption(): ILeetCodeWebviewOption { @@ -43,7 +40,7 @@ class LeetCodePreviewProvider extends LeetCodeWebview { } protected getWebviewContent(): string { - const button: { element: string, script: string, style: string } = { + const button: { element: string; script: string; style: string } = { element: ``, script: `const button = document.getElementById('solve'); button.onclick = () => vscode.postMessage({ @@ -70,37 +67,36 @@ class LeetCodePreviewProvider extends LeetCodeWebview { }; const { title, url, category, difficulty, likes, dislikes, body } = this.description; const head: string = markdownEngine.render(`# [${title}](${url})`); - const info: string = markdownEngine.render([ - `| Category | Difficulty | Likes | Dislikes |`, - `| :------: | :--------: | :---: | :------: |`, - `| ${category} | ${difficulty} | ${likes} | ${dislikes} |`, - ].join("\n")); + const info: string = markdownEngine.render( + [ + `| Category | Difficulty | Likes | Dislikes |`, + `| :------: | :--------: | :---: | :------: |`, + `| ${category} | ${difficulty} | ${likes} | ${dislikes} |`, + ].join("\n") + ); const tags: string = [ `
`, `
Tags`, - markdownEngine.render( - this.description.tags - .map((t: string) => `[\`${t}\`](https://leetcode.com/tag/${t})`) - .join(" | "), - ), + markdownEngine.render(this.description.tags.map((t: string) => `[\`${t}\`](${this.getTagLink(t)})`).join(" | ")), ``, ].join("\n"); const companies: string = [ `
`, `Companies`, - markdownEngine.render( - this.description.companies - .map((c: string) => `\`${c}\``) - .join(" | "), - ), + markdownEngine.render(this.description.companies.map((c: string) => `\`${c}\``).join(" | ")), `
`, ].join("\n"); + const links: string = markdownEngine.render(`[Submissions](${this.getSubmissionsLink(url)}) | [Solution](${this.getSolutionsLink(url)})`); return ` + ${markdownEngine.getStyles()} ${!this.sideMode ? button.style : ""} + ${head} @@ -108,6 +104,8 @@ class LeetCodePreviewProvider extends LeetCodeWebview { ${tags} ${companies} ${body} +
+ ${links} ${!this.sideMode ? button.element : ""}