diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs index a4f4369..98ee7df 100644 --- a/.commitlintrc.cjs +++ b/.commitlintrc.cjs @@ -1,3 +1,3 @@ module.exports = { - extends: ['@commitlint/config-conventional'] + extends: ['@commitlint/config-conventional'], } diff --git a/.eslintrc.js b/.eslintrc.js index 97c5221..107e222 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,22 +2,22 @@ module.exports = { env: { browser: true, commonjs: true, - es2021: true + es2021: true, }, extends: '@antfu', overrides: [ { env: { - node: true + node: true, }, files: ['.eslintrc.{js,cjs}'], parserOptions: { - sourceType: 'script' - } - } + sourceType: 'script', + }, + }, ], parserOptions: { - ecmaVersion: 'latest' + ecmaVersion: 'latest', }, - rules: {} + rules: {}, } diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..a902735 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,29 @@ +[中文](./CONTRIBUTING_CN.md) · **English** + +# Contributor + +If you would like to contribute to our project, please carefully read the following development conventions. Only when we have a consensus can our project get better and better! + +## Contributing Code + +### 1. Branch Management + +Do not develop on the `master` branch. The `master` branch is only for merging pull requests and releasing versions. For daily development, please use the `dev` branch. For feature development, please create a feature branch named `feat-xxx`. Similarly, for bug fixes, please create a fix branch named `fix-xxx`. + +### 2. Commit Process + +After completing development and committing on the `dev` branch or a `feat-xxx` branch, please use `git rebase origin/master` for local merging. After resolving all code conflicts locally, submit a pull request to members with permission for timely merging. + +## 3. About Feature Branches and Dev Branch + +By default, after submitting a pull request (PR), feature branches and fix branches will be deleted upon merging into the `master` branch. + +The `dev` branch, however, will not be deleted. During development on this branch, please synchronize the main branch by performing `git rebase master` beforehand. This is because the `master` branch accepts merges from feature branches and fix branches, potentially causing the `master` branch to be ahead of the `dev` branch. + +## 4. Rebase Synchronization Procedure + +When synchronizing with the main repository using `rebase` to resolve conflicts, after resolving conflicts, you may notice indicators such as `pull [number]` and `push [number]` when using `git status`. These indicate the number of commits behind and ahead of the remote branch, respectively. This is a normal situation resulting from `rebase`. At this point, you need to execute `git push -f` to perform a forced push to the remote branch, ensuring synchronization with the `master` branch and avoiding unnecessary commits. + +## References + +Reference Link: [Branch Management](https://www.ruanyifeng.com/blog/2012/07/git.html) diff --git a/.github/CONTRIBUTING_CN.md b/.github/CONTRIBUTING_CN.md new file mode 100644 index 0000000..bba21da --- /dev/null +++ b/.github/CONTRIBUTING_CN.md @@ -0,0 +1,29 @@ +**中文** · [English](./CONTRIBUTING.md) + +# 贡献者 + +如果你也想参与我们的项目共建,请详细阅读以下开发约定,只有大家拥有一个共识,我们的项目才会越来越好! + +## 贡献代码 + +### 1. 分支管理 + +不要在`master`分支进行开发, `master`分支只进行`pr合并`与`发布版本`, 如果是日常开发, 请在`dev`分支进行开发, 如果是`新特性`开发,请创建特性分支`feat-xxx`,同理,`修复bug`, 请创建修复分支`fix-xxx`. + +### 2. 提交流程 + +在`dev`分支或者`feat-xxx`分支`开发完成`并`提交commit`之后, 请使用`git rebase origin/master`进行`本地合并`,在本地解决完成所有的代码冲突之后,再进行`pr请求`,`发送请求`到有权限的成员,会及时进行合并. + +## 3. 关于特性分支和dev分支 + +默认`特性分支`和`修复分支`提交`pr`合并到`master`之后,会进行`删除`分支. + +`dev`分支不会进行删除,但是在其上开发的时候,请先进行`git rebase master`同步主分支(因为`主分支`接受`特性分支`和`修复分支`的`合并`,所以会出现`master分支`早于`dev分支`的情况). + +## 4. rebase同步操作说明 + +在进行对`主仓库的同步`的时候,使用`rebase`解决完成`冲突`之后,使用`git status`你会发现出现`pull [数字]`和`push [数字]`标识,其含义为`落后`和`领先`远程分支的记录数, 这种是`rebase`产生的`正常情况`,在这个时候需要执行`git push -f`对远端进行`强制推送`,实现`同步`master分支,就不会产生多余的commit了. + +## 参考信息 + +参考链接: [分支管理](https://www.ruanyifeng.com/blog/2012/07/git.html) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..e525db4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: 'Bug report(缺陷问题反馈)' +about: 'Report a bug to help us improve' +title: '[Bug] say something' +labels: '' +assignees: '' +--- + +<!-- +感谢您向我们反馈问题,为了高效的解决问题,我们期望你能提供以下信息: +--> + +## What happens? + +<!-- A clear and concise description of what the bug is. --> +<!-- 清晰的描述下遇到的问题。--> + +<!-- 为节约大家的时间,无复现步骤的 ISSUE 会被关闭,提供之后再 REOPEN --> + +## How To Reproduce + +**Steps to reproduce the behavior:** 1. 2. + +**Expected behavior** 1. 2. + +<!-- 请提供复现链接/步骤,错误日志以及相关配置 --> + +## Context + +- **leetcode-practice Version**: +- **Node Version**: +- **Platform**: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..e9085cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: 'Feature request(新需求)' +about: 'Suggest an idea for this project' +title: '[Feature Request] say something' +labels: '' +assignees: '' +--- + +## Background + +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +## Proposal + +Describe the solution you'd like, better to provide some pseudo code. + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..2d9cac1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: npm # See documentation for possible values + directory: / # Location of package manifests + schedule: + interval: weekly diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..d118a88 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,3 @@ +## Git Commit Message Convention + +> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular). diff --git a/.github/workflows/test.yml b/.github/workflows/ci.yml similarity index 96% rename from .github/workflows/test.yml rename to .github/workflows/ci.yml index a7fd624..08a925d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Test +name: ci on: [push, pull_request] diff --git a/.gitignore b/.gitignore index efaa728..5de262b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ resources/stores/* # cli-dist pl-cli */colorFont.js +pl-build # package manager yarn.lock diff --git a/.husky/commit-msg b/.husky/commit-msg index 5e563eb..813b76e 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - npx --no-install commitlint --edit diff --git a/.husky/pre-commit b/.husky/pre-commit index d83d9c9..e152c44 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" -echo "lint and format before commit" -npm run lint && npm run format +# todo-highlight diff --git a/.prettierrc b/.prettierrc index 6a1775b..f14e494 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,9 +1,14 @@ { - "printWidth": 80, - "tabWidth": 2, - "useTabs": false, - "singleQuote": true, - "semi": false, - "trailingComma": "none", - "bracketSpacing": true + "singleQuote": true, + "semi": true, + "tabWidth": 4, + "trailingComma": "none", + "printWidth": 360, + "quoteProps": "consistent", + "bracketSpacing": true, + "bracketSameLine": true, + "arrowParens": "always", + "htmlWhitespaceSensitivity": "css", + "endOfLine": "lf", + "singleAttributePerLine": true } diff --git a/.release-it.json b/.release-it.json index a9c4073..c5d28fb 100644 --- a/.release-it.json +++ b/.release-it.json @@ -5,7 +5,7 @@ "autoGenerate": true }, "git": { - "commitMessage": "feat: v${version}", + "commitMessage": "chore: release v${version}", "tagName": "cli-v${version}", "tag": true, "push": true, @@ -15,7 +15,8 @@ "publish": false }, "hooks": { - "after:bump": "echo 更新版本成功" + "before:release": "prettier --write CHANGELOG.md && git add CHANGELOG.md ", + "after:release": "git checkout master && git push origin master:stable-v${version} || true && echo 更新版本 ${version} 成功!" }, "plugins": { "@release-it/bumper": { diff --git a/CHANGELOG.md b/CHANGELOG.md index 65fee24..23d5435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,133 +1,206 @@ +## [1.0.9](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.9-5...cli-v1.0.9) (2024-03-24) +### Features -## 1.0.5 (2024-03-11) +- add -v command to check info ([#74](https://github.com/wh131462/leetcode-practice/issues/74)) ([529a501](https://github.com/wh131462/leetcode-practice/commit/529a5015b4797d226fa4a1009326ba2ab67458fe)) +- add pr and issue template ([#69](https://github.com/wh131462/leetcode-practice/issues/69)) ([ae28bd0](https://github.com/wh131462/leetcode-practice/commit/ae28bd0f3abf3ca0422e32fffaea05ba62dd504f)) +- **security policy:** Create SECURITY.md ([#71](https://github.com/wh131462/leetcode-practice/issues/71)) ([2322cd0](https://github.com/wh131462/leetcode-practice/commit/2322cd0f4b5693173591e4b14b29c7f22b4a7103)) + +## [1.0.9-5](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.9-4...cli-v1.0.9-5) (2024-03-17) + +### Features + +- lc -a and lf and store all question ([#67](https://github.com/wh131462/leetcode-practice/issues/67)) ([f72a281](https://github.com/wh131462/leetcode-practice/commit/f72a281faa613024ba94e356a2a8d17ed9089f2b)), closes [#45](https://github.com/wh131462/leetcode-practice/issues/45) [#39](https://github.com/wh131462/leetcode-practice/issues/39) +## [1.0.9-4](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.9-3...cli-v1.0.9-4) (2024-03-14) + +### Features + +- ora loading ([#54](https://github.com/wh131462/leetcode-practice/issues/54)) ([b604316](https://github.com/wh131462/leetcode-practice/commit/b6043167752a74582e8d095721cf5b3849951e06)) + +## [1.0.9-3](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.9-2...cli-v1.0.9-3) (2024-03-14) ### Bug Fixes -* add break before default ([08094b4](https://github.com/wh131462/leetcode-practice/commit/08094b4389a3fd1e442615dd687a55a08bd5ac62)) -* change ([1eb6e3c](https://github.com/wh131462/leetcode-practice/commit/1eb6e3c5ba35b22d7d3ef6893b6ace2d80050d6e)) -* change ([0801a1d](https://github.com/wh131462/leetcode-practice/commit/0801a1d6c63fef76d570ed7d943bd0d6f85c70e6)) -* change template ([872e867](https://github.com/wh131462/leetcode-practice/commit/872e867021c347e1fe4236e94cbd67aed47010a9)) -* console table text length verflow dislocation error ([3a563a2](https://github.com/wh131462/leetcode-practice/commit/3a563a2169bae2dd0ef26fb16e9bdedce21c8be2)) -* correct packageManager's format (fix [#7](https://github.com/wh131462/leetcode-practice/issues/7)) ([faa2280](https://github.com/wh131462/leetcode-practice/commit/faa2280746facefd2bd11d45d85cc70026821c0c)) -* delete src ([a932ce4](https://github.com/wh131462/leetcode-practice/commit/a932ce42227a8fab5d83d8bbe7a2add78c0d26a6)) -* delete src file ([2a53e63](https://github.com/wh131462/leetcode-practice/commit/2a53e634bbb7da7f0bf9df129901bb4c7839ba57)) -* find question by keyword error ([69da517](https://github.com/wh131462/leetcode-practice/commit/69da51740ff7f78a89c05ea534f80cc56f588d7f)) -* find question list ([6f78bfa](https://github.com/wh131462/leetcode-practice/commit/6f78bfa8fbab5d375f48d541c1b50bbfec55f9aa)) -* fix all lint error ([e99e76b](https://github.com/wh131462/leetcode-practice/commit/e99e76b2e1c7c9d387ab658a4c1f4057bf1a60da)) -* format readme form ([f002d77](https://github.com/wh131462/leetcode-practice/commit/f002d77f6e3f9e9a1259de2a5fee4b1858768620)) -* format readme form ([df5e45c](https://github.com/wh131462/leetcode-practice/commit/df5e45c9d55fc98dbe6bbc5b7fc80d6716d5bd34)) -* format readme form ([2f182ca](https://github.com/wh131462/leetcode-practice/commit/2f182ca85575fa8d2963fc0e657ee425b2215153)) -* format readme lint ([85b97f6](https://github.com/wh131462/leetcode-practice/commit/85b97f64258eadf4dcf1b29747e0ed0c3d161440)) -* getTestCase ([4ac7f65](https://github.com/wh131462/leetcode-practice/commit/4ac7f6505a47ab60d4ea74c659bb49c0d19667e6)) -* **headers:** remove useless header configuration ([105c841](https://github.com/wh131462/leetcode-practice/commit/105c84141206dfcf11d6a4ea46775f7546150acd)) -* **headers:** remove useless header configuration ([3ba1a98](https://github.com/wh131462/leetcode-practice/commit/3ba1a982a5e1d4c3b29d09af40df910f9d9dd3a5)) -* ignore lint ([46a9135](https://github.com/wh131462/leetcode-practice/commit/46a91358376a387b1e395e99424012685c21e09b)) -* ignore lint ([d376299](https://github.com/wh131462/leetcode-practice/commit/d376299a7f7e20453aaee978bba4178079b1e931)) -* lint ([cc63e57](https://github.com/wh131462/leetcode-practice/commit/cc63e572de4afa50b82791e1e896234b8d6b8ee4)) -* listnode check ([b8b3b47](https://github.com/wh131462/leetcode-practice/commit/b8b3b475637647035ac3eb9bfc5b27b61bde9a49)) -* log ([bd1d01b](https://github.com/wh131462/leetcode-practice/commit/bd1d01b4a440f8f80dfc67b04180dde29bac9da9)) -* memory calc error ([c09b344](https://github.com/wh131462/leetcode-practice/commit/c09b3440f81d0a3d6bf740aec06b320e00574b2c)) -* perfect version for cli install ([5a257f4](https://github.com/wh131462/leetcode-practice/commit/5a257f43fe897be40dd64a8ff8532387290a15fa)) -* readme_cn ([63dab20](https://github.com/wh131462/leetcode-practice/commit/63dab20f3956ae5f2abbc5df721c4ccc61d90bd2)) -* rename README ([2b8c294](https://github.com/wh131462/leetcode-practice/commit/2b8c294b0259d3476285ca985b8ad1e3fb2c6c2b)) -* rewrite log ([53d15b4](https://github.com/wh131462/leetcode-practice/commit/53d15b491c57d9e36a6fd6c36193517edb915425)) -* search ([5bb93dd](https://github.com/wh131462/leetcode-practice/commit/5bb93dd323c0786a17b1a4e4eae1ae3e1ba9625b)) -* **store:** fix the bug for create dir outside ([7254f29](https://github.com/wh131462/leetcode-practice/commit/7254f2988a656c28c0e7fbc685e16ff85cc1cbe6)) -* **store:** fix the bug for create dir outside ([1c66484](https://github.com/wh131462/leetcode-practice/commit/1c664846431448410ce3ddfc68ca29161c8e2683)) -* **tempate:** 修复空格导致字符串匹配失效问题 ([07bdbdc](https://github.com/wh131462/leetcode-practice/commit/07bdbdc88b1e50c781a65863dd1ba45c98eb5d79)) -* **test:** 修复挂掉的测试用例 ([4593058](https://github.com/wh131462/leetcode-practice/commit/4593058a065accc9e55e916352013de7bc6d4533)) -* update view for cli ([0b8ecf0](https://github.com/wh131462/leetcode-practice/commit/0b8ecf0ac7b2567168e35a6513308825aa514070)) -* 优化代码 ([da6aa6d](https://github.com/wh131462/leetcode-practice/commit/da6aa6d5ab87c4ecb626f1762033062a9ac432e4)) -* 修复原始创建不中止问题 ([ddb0ea1](https://github.com/wh131462/leetcode-practice/commit/ddb0ea11ca02abe73ee80ec8b0130466efbce457)) -* 模版文件路径错误 ([e46c94c](https://github.com/wh131462/leetcode-practice/commit/e46c94c85583b367d831326e4e873512b6ccf504)) +- fix check info log ([#52](https://github.com/wh131462/leetcode-practice/issues/52)) ([6b710a1](https://github.com/wh131462/leetcode-practice/commit/6b710a1a2ff088d9806d33153bf811e5a5e19306)) +## [1.0.9-2](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.9-1...cli-v1.0.9-2) (2024-03-14) -### Code Refactoring +### Features + +- add loading and logger on/off ([#51](https://github.com/wh131462/leetcode-practice/issues/51)) ([bbff9b1](https://github.com/wh131462/leetcode-practice/commit/bbff9b1b80aea18255b089c5ad9c836bcbd18dae)) -* directory refactor ([7a3a948](https://github.com/wh131462/leetcode-practice/commit/7a3a94806a1843e1c4bb86ece65d4e19ef9817fa)) +## [1.0.9-1](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.9-0...cli-v1.0.9-1) (2024-03-14) +### Bug Fixes -* cli finish basically (#5) ([5af52e3](https://github.com/wh131462/leetcode-practice/commit/5af52e31b466517d2fdea9443376d27bff646bdf)), closes [#5](https://github.com/wh131462/leetcode-practice/issues/5) +- fix hidden check ([#43](https://github.com/wh131462/leetcode-practice/issues/43)) ([46a209e](https://github.com/wh131462/leetcode-practice/commit/46a209ea8be810b2c13aacfd8a84a87356300da1)), closes [#39](https://github.com/wh131462/leetcode-practice/issues/39) +## [1.0.9-0](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.8...cli-v1.0.9-0) (2024-03-14) ### Features -* add ([fb3fadc](https://github.com/wh131462/leetcode-practice/commit/fb3fadc7fca166be0eefe51a817899466ab48b27)) -* add cz plugin ([4fd5af1](https://github.com/wh131462/leetcode-practice/commit/4fd5af151ac32d3daabcdc862505962fcd32f129)) -* add eslint ([be523ea](https://github.com/wh131462/leetcode-practice/commit/be523ea0f3085e003a2e0b5fb1c568b65cc21714)) -* add get question ([e5572b6](https://github.com/wh131462/leetcode-practice/commit/e5572b6357c8c056aa32eab53476736561261ebe)) -* add get question by keyword function ([097302a](https://github.com/wh131462/leetcode-practice/commit/097302afe095ad70d1c58942dc8ac8fb516e1eed)) -* add getQuestionChineseName function to get chinese name ([9520e75](https://github.com/wh131462/leetcode-practice/commit/9520e757741ff008439affd20db582458a37b674)) -* add getQuestionCode ([dbdb255](https://github.com/wh131462/leetcode-practice/commit/dbdb2553a2c47c9ee40fada33bfec7458ae4ccb6)) -* add memory calculate ([e6c315a](https://github.com/wh131462/leetcode-practice/commit/e6c315ab1524327697278e3b41c622fb22928896)) -* add memory demo ([8065924](https://github.com/wh131462/leetcode-practice/commit/8065924ca451e043f80644a31eb5d9543946f026)) -* add open process ([80dc9f5](https://github.com/wh131462/leetcode-practice/commit/80dc9f530eaae98e5449b3ebdf5c9e69ec452a17)) -* add prettier and commitlint ([608f4df](https://github.com/wh131462/leetcode-practice/commit/608f4dfdc4c0aebb9ead3e46abcde71fcc962b39)) -* change git push rules ([ee3e558](https://github.com/wh131462/leetcode-practice/commit/ee3e558496ef72f2daee071b88e79ddd06503e7c)) -* **cli:** 简化命令 使得命令可以在任何路径下运行 ([26fcffb](https://github.com/wh131462/leetcode-practice/commit/26fcffb8daa0e0a70e78c47772ef5059c1c825d1)) -* **commit:** finish set question range tag in file and get code in file by range tag ([61e2924](https://github.com/wh131462/leetcode-practice/commit/61e2924d2607e96bbd37947f05e718a10ac9edd6)) -* **commit:** finish set question range tag in file and get code in file by range tag ([b7eccdd](https://github.com/wh131462/leetcode-practice/commit/b7eccddb725ef460d04e8574ce5e02db533ccfd9)) -* **create:** can log file path and func start line number after create ([3b1365c](https://github.com/wh131462/leetcode-practice/commit/3b1365cbf9e86d4c0959817cbb845dd3495a12ab)) -* eslint忽略文件 ([f91889c](https://github.com/wh131462/leetcode-practice/commit/f91889c8348766a63136ada6fcd49e79a0e54378)) -* finish the view create & check ([9e96e0a](https://github.com/wh131462/leetcode-practice/commit/9e96e0a24f0232827196ce2bdb6c3d04966f42bd)) -* get js code ([b1fd6bb](https://github.com/wh131462/leetcode-practice/commit/b1fd6bb8d85d080c1f89a53cd99416c84e3abd10)) -* hot100合并代码 ([3ddd7c6](https://github.com/wh131462/leetcode-practice/commit/3ddd7c6237bd43655c4e3d0e490bd997afb1df5a)) -* node vm执行index.js脚本 ([f894e30](https://github.com/wh131462/leetcode-practice/commit/f894e3096c15d9939e0b93688f37c4272775d300)) -* publish config & build config ([1affd2a](https://github.com/wh131462/leetcode-practice/commit/1affd2ab7b1e1ad942d5dc3fbe5c300b5a92f240)) -* sucess log with green and fail log with red ([1eccefb](https://github.com/wh131462/leetcode-practice/commit/1eccefb023d28ca734c1886e0dc64a576d03f860)) -* update function basic ([a01c873](https://github.com/wh131462/leetcode-practice/commit/a01c8738aa060221421f2f17158c92a9069929a0)) -* update project using github ([a879d29](https://github.com/wh131462/leetcode-practice/commit/a879d29f9686f5c71d02bfe5c9122bc6fc90dc81)) -* version 1.0.2 ([4afe55e](https://github.com/wh131462/leetcode-practice/commit/4afe55e35ecea82dedbba3e6a3d9a2738365aa79)) -* **忽略测试覆盖率文件:** 忽略测试覆盖率文件 ([b05e380](https://github.com/wh131462/leetcode-practice/commit/b05e380ef84384f5f1ebbfb64628bd689933f755)) -* 新增填充markdown功能 ([1b8324d](https://github.com/wh131462/leetcode-practice/commit/1b8324d212898e8d0b7b2edc15244da31157a3c9)) -* 新增无向连通图数据结构 parse toArray实现,补充测试用例等 fix: 优化了转换逻辑 ([08f3787](https://github.com/wh131462/leetcode-practice/commit/08f3787f70de41d82610c1ce940f35c878dbf0d1)) -* 新增测试覆盖率 ([2627ecd](https://github.com/wh131462/leetcode-practice/commit/2627ecd00105d4af59e5c2fa59608da1144f17a8)) -* 测试用例中补充树和链表的数据结构以及转换逻辑,新增单元测试模块 ([ac9ccd1](https://github.com/wh131462/leetcode-practice/commit/ac9ccd155358306f667e9ffaa0aac9f16d58988a)) -* 统一数据结构 ([f15a8da](https://github.com/wh131462/leetcode-practice/commit/f15a8dad2500cef476e1340b93053be48364bf3e)) +- check update with first lc run ([#41](https://github.com/wh131462/leetcode-practice/issues/41)) ([81a1439](https://github.com/wh131462/leetcode-practice/commit/81a1439cb970aa2cfe552ec70b8d1ad3ee9bbab7)) +## [1.0.8](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.7...cli-v1.0.8) (2024-03-14) -### Performance Improvements +### Bug Fixes + +- page size ([f3fd27c](https://github.com/wh131462/leetcode-practice/commit/f3fd27cc31a4d82dc9e8641a865a750b173f43f5)) +- page size ([1905454](https://github.com/wh131462/leetcode-practice/commit/1905454d71ece043da1badc3a604c72f23995ae5)) + +### Features + +- add fetch qurtion list ([4485182](https://github.com/wh131462/leetcode-practice/commit/44851825eb92b2f1da98f1bb78c71c3f0fe27856)) +- lk check question by file ([bec7081](https://github.com/wh131462/leetcode-practice/commit/bec708107f67a2ce6c1d361911f1f9ce2ed3ed26)) +- 获取全部学习计划题目 ([c8ec9dc](https://github.com/wh131462/leetcode-practice/commit/c8ec9dc82f7310759fa949dce771aa665906e2f8)) + +## [1.0.7](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.6...cli-v1.0.7) (2024-03-12) + +### Bug Fixes + +- change plan list question title to cn ([57f15d5](https://github.com/wh131462/leetcode-practice/commit/57f15d5befc23d11ce6211c30e3ee7a7e8bbe52d)) +- change plan list question title to cn ([cb6fbfd](https://github.com/wh131462/leetcode-practice/commit/cb6fbfd4cd783f57d031abe3add9d85f3e271a4c)) +- change the config ([2b9bb11](https://github.com/wh131462/leetcode-practice/commit/2b9bb1149c6db0dbede22f10830ccd8661b0a83f)) +- delete hot100 add study plan list ([e94aaa1](https://github.com/wh131462/leetcode-practice/commit/e94aaa166e80e7e54f3ce5b570352cb798799b77)) +- delete hot100 add study plan list ([9d7a22f](https://github.com/wh131462/leetcode-practice/commit/9d7a22fde8cc72264766f707ea3f51e81956c111)) +- get all is not success ([9108219](https://github.com/wh131462/leetcode-practice/commit/91082196dc005b0b23314966a09304ba948416b8)) +- get all is not success ([3f5bfef](https://github.com/wh131462/leetcode-practice/commit/3f5bfef7857e6c9869c40e3d12a60d50b14be2cd)) +- update realm version to fix windows env ([00d2bc4](https://github.com/wh131462/leetcode-practice/commit/00d2bc4942b2b02f97ad41d23da64f8bedc23741)) +- use logger instead console ([fddc458](https://github.com/wh131462/leetcode-practice/commit/fddc4581efbd5186a17aa1415aa2738283f820b7)) + +## [1.0.6](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.5...cli-v1.0.6) (2024-03-11) + +### Bug Fixes + +- realm-compatible-problem ([#25](https://github.com/wh131462/leetcode-practice/issues/25)) ([d2d37d6](https://github.com/wh131462/leetcode-practice/commit/d2d37d68e6405507340b115d55bec15e070cf3ba)) + +### Features + +- change lf feature and update docs ([#27](https://github.com/wh131462/leetcode-practice/issues/27)) ([3b7e129](https://github.com/wh131462/leetcode-practice/commit/3b7e129b722391b50d32e48e782f244a12faad05)) + +## 1.0.5 (2024-03-11) -* better scripts and easy mode to create question in project ([ffd9e29](https://github.com/wh131462/leetcode-practice/commit/ffd9e29ca35d9f4b8b6b2f8b94516e8f053261a5)) -* http dir structure and functions modify ([553ad58](https://github.com/wh131462/leetcode-practice/commit/553ad5861aa67423c1092f798f39b2bd4faf68f6)) +### Bug Fixes + +- add break before default ([08094b4](https://github.com/wh131462/leetcode-practice/commit/08094b4389a3fd1e442615dd687a55a08bd5ac62)) +- change ([1eb6e3c](https://github.com/wh131462/leetcode-practice/commit/1eb6e3c5ba35b22d7d3ef6893b6ace2d80050d6e)) +- change ([0801a1d](https://github.com/wh131462/leetcode-practice/commit/0801a1d6c63fef76d570ed7d943bd0d6f85c70e6)) +- change template ([872e867](https://github.com/wh131462/leetcode-practice/commit/872e867021c347e1fe4236e94cbd67aed47010a9)) +- console table text length verflow dislocation error ([3a563a2](https://github.com/wh131462/leetcode-practice/commit/3a563a2169bae2dd0ef26fb16e9bdedce21c8be2)) +- correct packageManager's format (fix [#7](https://github.com/wh131462/leetcode-practice/issues/7)) ([faa2280](https://github.com/wh131462/leetcode-practice/commit/faa2280746facefd2bd11d45d85cc70026821c0c)) +- delete src ([a932ce4](https://github.com/wh131462/leetcode-practice/commit/a932ce42227a8fab5d83d8bbe7a2add78c0d26a6)) +- delete src file ([2a53e63](https://github.com/wh131462/leetcode-practice/commit/2a53e634bbb7da7f0bf9df129901bb4c7839ba57)) +- find question by keyword error ([69da517](https://github.com/wh131462/leetcode-practice/commit/69da51740ff7f78a89c05ea534f80cc56f588d7f)) +- find question list ([6f78bfa](https://github.com/wh131462/leetcode-practice/commit/6f78bfa8fbab5d375f48d541c1b50bbfec55f9aa)) +- fix all lint error ([e99e76b](https://github.com/wh131462/leetcode-practice/commit/e99e76b2e1c7c9d387ab658a4c1f4057bf1a60da)) +- format readme form ([f002d77](https://github.com/wh131462/leetcode-practice/commit/f002d77f6e3f9e9a1259de2a5fee4b1858768620)) +- format readme form ([df5e45c](https://github.com/wh131462/leetcode-practice/commit/df5e45c9d55fc98dbe6bbc5b7fc80d6716d5bd34)) +- format readme form ([2f182ca](https://github.com/wh131462/leetcode-practice/commit/2f182ca85575fa8d2963fc0e657ee425b2215153)) +- format readme lint ([85b97f6](https://github.com/wh131462/leetcode-practice/commit/85b97f64258eadf4dcf1b29747e0ed0c3d161440)) +- getTestCase ([4ac7f65](https://github.com/wh131462/leetcode-practice/commit/4ac7f6505a47ab60d4ea74c659bb49c0d19667e6)) +- **headers:** remove useless header configuration ([105c841](https://github.com/wh131462/leetcode-practice/commit/105c84141206dfcf11d6a4ea46775f7546150acd)) +- **headers:** remove useless header configuration ([3ba1a98](https://github.com/wh131462/leetcode-practice/commit/3ba1a982a5e1d4c3b29d09af40df910f9d9dd3a5)) +- ignore lint ([46a9135](https://github.com/wh131462/leetcode-practice/commit/46a91358376a387b1e395e99424012685c21e09b)) +- ignore lint ([d376299](https://github.com/wh131462/leetcode-practice/commit/d376299a7f7e20453aaee978bba4178079b1e931)) +- lint ([cc63e57](https://github.com/wh131462/leetcode-practice/commit/cc63e572de4afa50b82791e1e896234b8d6b8ee4)) +- listnode check ([b8b3b47](https://github.com/wh131462/leetcode-practice/commit/b8b3b475637647035ac3eb9bfc5b27b61bde9a49)) +- log ([bd1d01b](https://github.com/wh131462/leetcode-practice/commit/bd1d01b4a440f8f80dfc67b04180dde29bac9da9)) +- memory calc error ([c09b344](https://github.com/wh131462/leetcode-practice/commit/c09b3440f81d0a3d6bf740aec06b320e00574b2c)) +- perfect version for cli install ([5a257f4](https://github.com/wh131462/leetcode-practice/commit/5a257f43fe897be40dd64a8ff8532387290a15fa)) +- readme_cn ([63dab20](https://github.com/wh131462/leetcode-practice/commit/63dab20f3956ae5f2abbc5df721c4ccc61d90bd2)) +- rename README ([2b8c294](https://github.com/wh131462/leetcode-practice/commit/2b8c294b0259d3476285ca985b8ad1e3fb2c6c2b)) +- rewrite log ([53d15b4](https://github.com/wh131462/leetcode-practice/commit/53d15b491c57d9e36a6fd6c36193517edb915425)) +- search ([5bb93dd](https://github.com/wh131462/leetcode-practice/commit/5bb93dd323c0786a17b1a4e4eae1ae3e1ba9625b)) +- **store:** fix the bug for create dir outside ([7254f29](https://github.com/wh131462/leetcode-practice/commit/7254f2988a656c28c0e7fbc685e16ff85cc1cbe6)) +- **store:** fix the bug for create dir outside ([1c66484](https://github.com/wh131462/leetcode-practice/commit/1c664846431448410ce3ddfc68ca29161c8e2683)) +- **tempate:** 修复空格导致字符串匹配失效问题 ([07bdbdc](https://github.com/wh131462/leetcode-practice/commit/07bdbdc88b1e50c781a65863dd1ba45c98eb5d79)) +- **test:** 修复挂掉的测试用例 ([4593058](https://github.com/wh131462/leetcode-practice/commit/4593058a065accc9e55e916352013de7bc6d4533)) +- update view for cli ([0b8ecf0](https://github.com/wh131462/leetcode-practice/commit/0b8ecf0ac7b2567168e35a6513308825aa514070)) +- 优化代码 ([da6aa6d](https://github.com/wh131462/leetcode-practice/commit/da6aa6d5ab87c4ecb626f1762033062a9ac432e4)) +- 修复原始创建不中止问题 ([ddb0ea1](https://github.com/wh131462/leetcode-practice/commit/ddb0ea11ca02abe73ee80ec8b0130466efbce457)) +- 模版文件路径错误 ([e46c94c](https://github.com/wh131462/leetcode-practice/commit/e46c94c85583b367d831326e4e873512b6ccf504)) + +### Code Refactoring + +- directory refactor ([7a3a948](https://github.com/wh131462/leetcode-practice/commit/7a3a94806a1843e1c4bb86ece65d4e19ef9817fa)) + +- cli finish basically (#5) ([5af52e3](https://github.com/wh131462/leetcode-practice/commit/5af52e31b466517d2fdea9443376d27bff646bdf)), closes [#5](https://github.com/wh131462/leetcode-practice/issues/5) + +### Features + +- add ([fb3fadc](https://github.com/wh131462/leetcode-practice/commit/fb3fadc7fca166be0eefe51a817899466ab48b27)) +- add cz plugin ([4fd5af1](https://github.com/wh131462/leetcode-practice/commit/4fd5af151ac32d3daabcdc862505962fcd32f129)) +- add eslint ([be523ea](https://github.com/wh131462/leetcode-practice/commit/be523ea0f3085e003a2e0b5fb1c568b65cc21714)) +- add get question ([e5572b6](https://github.com/wh131462/leetcode-practice/commit/e5572b6357c8c056aa32eab53476736561261ebe)) +- add get question by keyword function ([097302a](https://github.com/wh131462/leetcode-practice/commit/097302afe095ad70d1c58942dc8ac8fb516e1eed)) +- add getQuestionChineseName function to get chinese name ([9520e75](https://github.com/wh131462/leetcode-practice/commit/9520e757741ff008439affd20db582458a37b674)) +- add getQuestionCode ([dbdb255](https://github.com/wh131462/leetcode-practice/commit/dbdb2553a2c47c9ee40fada33bfec7458ae4ccb6)) +- add memory calculate ([e6c315a](https://github.com/wh131462/leetcode-practice/commit/e6c315ab1524327697278e3b41c622fb22928896)) +- add memory demo ([8065924](https://github.com/wh131462/leetcode-practice/commit/8065924ca451e043f80644a31eb5d9543946f026)) +- add open process ([80dc9f5](https://github.com/wh131462/leetcode-practice/commit/80dc9f530eaae98e5449b3ebdf5c9e69ec452a17)) +- add prettier and commitlint ([608f4df](https://github.com/wh131462/leetcode-practice/commit/608f4dfdc4c0aebb9ead3e46abcde71fcc962b39)) +- change git push rules ([ee3e558](https://github.com/wh131462/leetcode-practice/commit/ee3e558496ef72f2daee071b88e79ddd06503e7c)) +- **cli:** 简化命令 使得命令可以在任何路径下运行 ([26fcffb](https://github.com/wh131462/leetcode-practice/commit/26fcffb8daa0e0a70e78c47772ef5059c1c825d1)) +- **commit:** finish set question range tag in file and get code in file by range tag ([61e2924](https://github.com/wh131462/leetcode-practice/commit/61e2924d2607e96bbd37947f05e718a10ac9edd6)) +- **commit:** finish set question range tag in file and get code in file by range tag ([b7eccdd](https://github.com/wh131462/leetcode-practice/commit/b7eccddb725ef460d04e8574ce5e02db533ccfd9)) +- **create:** can log file path and func start line number after create ([3b1365c](https://github.com/wh131462/leetcode-practice/commit/3b1365cbf9e86d4c0959817cbb845dd3495a12ab)) +- eslint忽略文件 ([f91889c](https://github.com/wh131462/leetcode-practice/commit/f91889c8348766a63136ada6fcd49e79a0e54378)) +- finish the view create & check ([9e96e0a](https://github.com/wh131462/leetcode-practice/commit/9e96e0a24f0232827196ce2bdb6c3d04966f42bd)) +- get js code ([b1fd6bb](https://github.com/wh131462/leetcode-practice/commit/b1fd6bb8d85d080c1f89a53cd99416c84e3abd10)) +- hot100合并代码 ([3ddd7c6](https://github.com/wh131462/leetcode-practice/commit/3ddd7c6237bd43655c4e3d0e490bd997afb1df5a)) +- node vm执行index.js脚本 ([f894e30](https://github.com/wh131462/leetcode-practice/commit/f894e3096c15d9939e0b93688f37c4272775d300)) +- publish config & build config ([1affd2a](https://github.com/wh131462/leetcode-practice/commit/1affd2ab7b1e1ad942d5dc3fbe5c300b5a92f240)) +- sucess log with green and fail log with red ([1eccefb](https://github.com/wh131462/leetcode-practice/commit/1eccefb023d28ca734c1886e0dc64a576d03f860)) +- update function basic ([a01c873](https://github.com/wh131462/leetcode-practice/commit/a01c8738aa060221421f2f17158c92a9069929a0)) +- update project using github ([a879d29](https://github.com/wh131462/leetcode-practice/commit/a879d29f9686f5c71d02bfe5c9122bc6fc90dc81)) +- version 1.0.2 ([4afe55e](https://github.com/wh131462/leetcode-practice/commit/4afe55e35ecea82dedbba3e6a3d9a2738365aa79)) +- **忽略测试覆盖率文件:** 忽略测试覆盖率文件 ([b05e380](https://github.com/wh131462/leetcode-practice/commit/b05e380ef84384f5f1ebbfb64628bd689933f755)) +- 新增填充markdown功能 ([1b8324d](https://github.com/wh131462/leetcode-practice/commit/1b8324d212898e8d0b7b2edc15244da31157a3c9)) +- 新增无向连通图数据结构 parse toArray实现,补充测试用例等 fix: 优化了转换逻辑 ([08f3787](https://github.com/wh131462/leetcode-practice/commit/08f3787f70de41d82610c1ce940f35c878dbf0d1)) +- 新增测试覆盖率 ([2627ecd](https://github.com/wh131462/leetcode-practice/commit/2627ecd00105d4af59e5c2fa59608da1144f17a8)) +- 测试用例中补充树和链表的数据结构以及转换逻辑,新增单元测试模块 ([ac9ccd1](https://github.com/wh131462/leetcode-practice/commit/ac9ccd155358306f667e9ffaa0aac9f16d58988a)) +- 统一数据结构 ([f15a8da](https://github.com/wh131462/leetcode-practice/commit/f15a8dad2500cef476e1340b93053be48364bf3e)) + +### Performance Improvements +- better scripts and easy mode to create question in project ([ffd9e29](https://github.com/wh131462/leetcode-practice/commit/ffd9e29ca35d9f4b8b6b2f8b94516e8f053261a5)) +- http dir structure and functions modify ([553ad58](https://github.com/wh131462/leetcode-practice/commit/553ad5861aa67423c1092f798f39b2bd4faf68f6)) ### BREAKING CHANGES -* srcipts即将废弃,视图交互性代码完善1/3 +- srcipts即将废弃,视图交互性代码完善1/3 -* feat: finish the view create & check +- feat: finish the view create & check -* feat:完成lc&lk指令 +- feat:完成lc&lk指令 -* fix: 优化代码 +- fix: 优化代码 -* feat: add getQuestionChineseName function to get chinese name +- feat: add getQuestionChineseName function to get chinese name -* chore: del scripts and .vscode files & ignore .vscode +- chore: del scripts and .vscode files & ignore .vscode -* docs: update todo & achive +- docs: update todo & achive -* perf: better scripts and easy mode to create question in project +- perf: better scripts and easy mode to create question in project -* feat: publish config & build config +- feat: publish config & build config -* chore: del src +- chore: del src -* fix: perfect version for cli install +- fix: perfect version for cli install -* fix:指令打包完善 +- fix:指令打包完善 -* fix:easy mode script +- fix:easy mode script -* docs:todo 拆分成单独文件 +- docs:todo 拆分成单独文件 -* chore:路径调整成全局路径 +- chore:路径调整成全局路径 -* docs: add CHANGELOG and TO-DO -* srcipts即将废弃,视图交互性代码完善1/3 +- docs: add CHANGELOG and TO-DO +- srcipts即将废弃,视图交互性代码完善1/3 ## [1.0.5-bera.0](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.4-beta...cli-v1.0.5-bera.0) (2024-03-11) @@ -137,148 +210,148 @@ ### Bug Fixes -- add break before default ([08094b4](https://github.com/wh131462/leetcode-practice/commit/08094b4389a3fd1e442615dd687a55a08bd5ac62)) -- change ([1eb6e3c](https://github.com/wh131462/leetcode-practice/commit/1eb6e3c5ba35b22d7d3ef6893b6ace2d80050d6e)) -- change ([0801a1d](https://github.com/wh131462/leetcode-practice/commit/0801a1d6c63fef76d570ed7d943bd0d6f85c70e6)) -- change template ([872e867](https://github.com/wh131462/leetcode-practice/commit/872e867021c347e1fe4236e94cbd67aed47010a9)) -- console table text length verflow dislocation error ([3a563a2](https://github.com/wh131462/leetcode-practice/commit/3a563a2169bae2dd0ef26fb16e9bdedce21c8be2)) -- correct packageManager's format (fix [#7](https://github.com/wh131462/leetcode-practice/issues/7)) ([faa2280](https://github.com/wh131462/leetcode-practice/commit/faa2280746facefd2bd11d45d85cc70026821c0c)) -- delete src ([a932ce4](https://github.com/wh131462/leetcode-practice/commit/a932ce42227a8fab5d83d8bbe7a2add78c0d26a6)) -- delete src file ([2a53e63](https://github.com/wh131462/leetcode-practice/commit/2a53e634bbb7da7f0bf9df129901bb4c7839ba57)) -- find question by keyword error ([69da517](https://github.com/wh131462/leetcode-practice/commit/69da51740ff7f78a89c05ea534f80cc56f588d7f)) -- find question list ([6f78bfa](https://github.com/wh131462/leetcode-practice/commit/6f78bfa8fbab5d375f48d541c1b50bbfec55f9aa)) -- fix all lint error ([e99e76b](https://github.com/wh131462/leetcode-practice/commit/e99e76b2e1c7c9d387ab658a4c1f4057bf1a60da)) -- format readme form ([f002d77](https://github.com/wh131462/leetcode-practice/commit/f002d77f6e3f9e9a1259de2a5fee4b1858768620)) -- format readme form ([df5e45c](https://github.com/wh131462/leetcode-practice/commit/df5e45c9d55fc98dbe6bbc5b7fc80d6716d5bd34)) -- format readme form ([2f182ca](https://github.com/wh131462/leetcode-practice/commit/2f182ca85575fa8d2963fc0e657ee425b2215153)) -- format readme lint ([85b97f6](https://github.com/wh131462/leetcode-practice/commit/85b97f64258eadf4dcf1b29747e0ed0c3d161440)) -- getTestCase ([4ac7f65](https://github.com/wh131462/leetcode-practice/commit/4ac7f6505a47ab60d4ea74c659bb49c0d19667e6)) -- **headers:** remove useless header configuration ([105c841](https://github.com/wh131462/leetcode-practice/commit/105c84141206dfcf11d6a4ea46775f7546150acd)) -- **headers:** remove useless header configuration ([3ba1a98](https://github.com/wh131462/leetcode-practice/commit/3ba1a982a5e1d4c3b29d09af40df910f9d9dd3a5)) -- ignore lint ([46a9135](https://github.com/wh131462/leetcode-practice/commit/46a91358376a387b1e395e99424012685c21e09b)) -- ignore lint ([d376299](https://github.com/wh131462/leetcode-practice/commit/d376299a7f7e20453aaee978bba4178079b1e931)) -- lint ([cc63e57](https://github.com/wh131462/leetcode-practice/commit/cc63e572de4afa50b82791e1e896234b8d6b8ee4)) -- listnode check ([b8b3b47](https://github.com/wh131462/leetcode-practice/commit/b8b3b475637647035ac3eb9bfc5b27b61bde9a49)) -- log ([bd1d01b](https://github.com/wh131462/leetcode-practice/commit/bd1d01b4a440f8f80dfc67b04180dde29bac9da9)) -- memory calc error ([c09b344](https://github.com/wh131462/leetcode-practice/commit/c09b3440f81d0a3d6bf740aec06b320e00574b2c)) -- perfect version for cli install ([5a257f4](https://github.com/wh131462/leetcode-practice/commit/5a257f43fe897be40dd64a8ff8532387290a15fa)) -- readme_cn ([63dab20](https://github.com/wh131462/leetcode-practice/commit/63dab20f3956ae5f2abbc5df721c4ccc61d90bd2)) -- rename README ([2b8c294](https://github.com/wh131462/leetcode-practice/commit/2b8c294b0259d3476285ca985b8ad1e3fb2c6c2b)) -- rewrite log ([53d15b4](https://github.com/wh131462/leetcode-practice/commit/53d15b491c57d9e36a6fd6c36193517edb915425)) -- search ([5bb93dd](https://github.com/wh131462/leetcode-practice/commit/5bb93dd323c0786a17b1a4e4eae1ae3e1ba9625b)) -- **store:** fix the bug for create dir outside ([7254f29](https://github.com/wh131462/leetcode-practice/commit/7254f2988a656c28c0e7fbc685e16ff85cc1cbe6)) -- **tempate:** 修复空格导致字符串匹配失效问题 ([07bdbdc](https://github.com/wh131462/leetcode-practice/commit/07bdbdc88b1e50c781a65863dd1ba45c98eb5d79)) -- **test:** 修复挂掉的测试用例 ([4593058](https://github.com/wh131462/leetcode-practice/commit/4593058a065accc9e55e916352013de7bc6d4533)) -- update view for cli ([0b8ecf0](https://github.com/wh131462/leetcode-practice/commit/0b8ecf0ac7b2567168e35a6513308825aa514070)) -- 优化代码 ([da6aa6d](https://github.com/wh131462/leetcode-practice/commit/da6aa6d5ab87c4ecb626f1762033062a9ac432e4)) -- 修复原始创建不中止问题 ([ddb0ea1](https://github.com/wh131462/leetcode-practice/commit/ddb0ea11ca02abe73ee80ec8b0130466efbce457)) -- 模版文件路径错误 ([e46c94c](https://github.com/wh131462/leetcode-practice/commit/e46c94c85583b367d831326e4e873512b6ccf504)) +- add break before default ([08094b4](https://github.com/wh131462/leetcode-practice/commit/08094b4389a3fd1e442615dd687a55a08bd5ac62)) +- change ([1eb6e3c](https://github.com/wh131462/leetcode-practice/commit/1eb6e3c5ba35b22d7d3ef6893b6ace2d80050d6e)) +- change ([0801a1d](https://github.com/wh131462/leetcode-practice/commit/0801a1d6c63fef76d570ed7d943bd0d6f85c70e6)) +- change template ([872e867](https://github.com/wh131462/leetcode-practice/commit/872e867021c347e1fe4236e94cbd67aed47010a9)) +- console table text length verflow dislocation error ([3a563a2](https://github.com/wh131462/leetcode-practice/commit/3a563a2169bae2dd0ef26fb16e9bdedce21c8be2)) +- correct packageManager's format (fix [#7](https://github.com/wh131462/leetcode-practice/issues/7)) ([faa2280](https://github.com/wh131462/leetcode-practice/commit/faa2280746facefd2bd11d45d85cc70026821c0c)) +- delete src ([a932ce4](https://github.com/wh131462/leetcode-practice/commit/a932ce42227a8fab5d83d8bbe7a2add78c0d26a6)) +- delete src file ([2a53e63](https://github.com/wh131462/leetcode-practice/commit/2a53e634bbb7da7f0bf9df129901bb4c7839ba57)) +- find question by keyword error ([69da517](https://github.com/wh131462/leetcode-practice/commit/69da51740ff7f78a89c05ea534f80cc56f588d7f)) +- find question list ([6f78bfa](https://github.com/wh131462/leetcode-practice/commit/6f78bfa8fbab5d375f48d541c1b50bbfec55f9aa)) +- fix all lint error ([e99e76b](https://github.com/wh131462/leetcode-practice/commit/e99e76b2e1c7c9d387ab658a4c1f4057bf1a60da)) +- format readme form ([f002d77](https://github.com/wh131462/leetcode-practice/commit/f002d77f6e3f9e9a1259de2a5fee4b1858768620)) +- format readme form ([df5e45c](https://github.com/wh131462/leetcode-practice/commit/df5e45c9d55fc98dbe6bbc5b7fc80d6716d5bd34)) +- format readme form ([2f182ca](https://github.com/wh131462/leetcode-practice/commit/2f182ca85575fa8d2963fc0e657ee425b2215153)) +- format readme lint ([85b97f6](https://github.com/wh131462/leetcode-practice/commit/85b97f64258eadf4dcf1b29747e0ed0c3d161440)) +- getTestCase ([4ac7f65](https://github.com/wh131462/leetcode-practice/commit/4ac7f6505a47ab60d4ea74c659bb49c0d19667e6)) +- **headers:** remove useless header configuration ([105c841](https://github.com/wh131462/leetcode-practice/commit/105c84141206dfcf11d6a4ea46775f7546150acd)) +- **headers:** remove useless header configuration ([3ba1a98](https://github.com/wh131462/leetcode-practice/commit/3ba1a982a5e1d4c3b29d09af40df910f9d9dd3a5)) +- ignore lint ([46a9135](https://github.com/wh131462/leetcode-practice/commit/46a91358376a387b1e395e99424012685c21e09b)) +- ignore lint ([d376299](https://github.com/wh131462/leetcode-practice/commit/d376299a7f7e20453aaee978bba4178079b1e931)) +- lint ([cc63e57](https://github.com/wh131462/leetcode-practice/commit/cc63e572de4afa50b82791e1e896234b8d6b8ee4)) +- listnode check ([b8b3b47](https://github.com/wh131462/leetcode-practice/commit/b8b3b475637647035ac3eb9bfc5b27b61bde9a49)) +- log ([bd1d01b](https://github.com/wh131462/leetcode-practice/commit/bd1d01b4a440f8f80dfc67b04180dde29bac9da9)) +- memory calc error ([c09b344](https://github.com/wh131462/leetcode-practice/commit/c09b3440f81d0a3d6bf740aec06b320e00574b2c)) +- perfect version for cli install ([5a257f4](https://github.com/wh131462/leetcode-practice/commit/5a257f43fe897be40dd64a8ff8532387290a15fa)) +- readme_cn ([63dab20](https://github.com/wh131462/leetcode-practice/commit/63dab20f3956ae5f2abbc5df721c4ccc61d90bd2)) +- rename README ([2b8c294](https://github.com/wh131462/leetcode-practice/commit/2b8c294b0259d3476285ca985b8ad1e3fb2c6c2b)) +- rewrite log ([53d15b4](https://github.com/wh131462/leetcode-practice/commit/53d15b491c57d9e36a6fd6c36193517edb915425)) +- search ([5bb93dd](https://github.com/wh131462/leetcode-practice/commit/5bb93dd323c0786a17b1a4e4eae1ae3e1ba9625b)) +- **store:** fix the bug for create dir outside ([7254f29](https://github.com/wh131462/leetcode-practice/commit/7254f2988a656c28c0e7fbc685e16ff85cc1cbe6)) +- **tempate:** 修复空格导致字符串匹配失效问题 ([07bdbdc](https://github.com/wh131462/leetcode-practice/commit/07bdbdc88b1e50c781a65863dd1ba45c98eb5d79)) +- **test:** 修复挂掉的测试用例 ([4593058](https://github.com/wh131462/leetcode-practice/commit/4593058a065accc9e55e916352013de7bc6d4533)) +- update view for cli ([0b8ecf0](https://github.com/wh131462/leetcode-practice/commit/0b8ecf0ac7b2567168e35a6513308825aa514070)) +- 优化代码 ([da6aa6d](https://github.com/wh131462/leetcode-practice/commit/da6aa6d5ab87c4ecb626f1762033062a9ac432e4)) +- 修复原始创建不中止问题 ([ddb0ea1](https://github.com/wh131462/leetcode-practice/commit/ddb0ea11ca02abe73ee80ec8b0130466efbce457)) +- 模版文件路径错误 ([e46c94c](https://github.com/wh131462/leetcode-practice/commit/e46c94c85583b367d831326e4e873512b6ccf504)) ### Code Refactoring -- directory refactor ([7a3a948](https://github.com/wh131462/leetcode-practice/commit/7a3a94806a1843e1c4bb86ece65d4e19ef9817fa)) +- directory refactor ([7a3a948](https://github.com/wh131462/leetcode-practice/commit/7a3a94806a1843e1c4bb86ece65d4e19ef9817fa)) -- cli finish basically (#5) ([5af52e3](https://github.com/wh131462/leetcode-practice/commit/5af52e31b466517d2fdea9443376d27bff646bdf)), closes [#5](https://github.com/wh131462/leetcode-practice/issues/5) +- cli finish basically (#5) ([5af52e3](https://github.com/wh131462/leetcode-practice/commit/5af52e31b466517d2fdea9443376d27bff646bdf)), closes [#5](https://github.com/wh131462/leetcode-practice/issues/5) ### Features -- add ([fb3fadc](https://github.com/wh131462/leetcode-practice/commit/fb3fadc7fca166be0eefe51a817899466ab48b27)) -- add cz plugin ([4fd5af1](https://github.com/wh131462/leetcode-practice/commit/4fd5af151ac32d3daabcdc862505962fcd32f129)) -- add eslint ([be523ea](https://github.com/wh131462/leetcode-practice/commit/be523ea0f3085e003a2e0b5fb1c568b65cc21714)) -- add get question ([e5572b6](https://github.com/wh131462/leetcode-practice/commit/e5572b6357c8c056aa32eab53476736561261ebe)) -- add get question by keyword function ([097302a](https://github.com/wh131462/leetcode-practice/commit/097302afe095ad70d1c58942dc8ac8fb516e1eed)) -- add getQuestionChineseName function to get chinese name ([9520e75](https://github.com/wh131462/leetcode-practice/commit/9520e757741ff008439affd20db582458a37b674)) -- add getQuestionCode ([dbdb255](https://github.com/wh131462/leetcode-practice/commit/dbdb2553a2c47c9ee40fada33bfec7458ae4ccb6)) -- add memory calculate ([e6c315a](https://github.com/wh131462/leetcode-practice/commit/e6c315ab1524327697278e3b41c622fb22928896)) -- add memory demo ([8065924](https://github.com/wh131462/leetcode-practice/commit/8065924ca451e043f80644a31eb5d9543946f026)) -- add open process ([80dc9f5](https://github.com/wh131462/leetcode-practice/commit/80dc9f530eaae98e5449b3ebdf5c9e69ec452a17)) -- add prettier and commitlint ([608f4df](https://github.com/wh131462/leetcode-practice/commit/608f4dfdc4c0aebb9ead3e46abcde71fcc962b39)) -- change git push rules ([ee3e558](https://github.com/wh131462/leetcode-practice/commit/ee3e558496ef72f2daee071b88e79ddd06503e7c)) -- **cli:** 简化命令 使得命令可以在任何路径下运行 ([26fcffb](https://github.com/wh131462/leetcode-practice/commit/26fcffb8daa0e0a70e78c47772ef5059c1c825d1)) -- **commit:** finish set question range tag in file and get code in file by range tag ([61e2924](https://github.com/wh131462/leetcode-practice/commit/61e2924d2607e96bbd37947f05e718a10ac9edd6)) -- eslint忽略文件 ([f91889c](https://github.com/wh131462/leetcode-practice/commit/f91889c8348766a63136ada6fcd49e79a0e54378)) -- finish the view create & check ([9e96e0a](https://github.com/wh131462/leetcode-practice/commit/9e96e0a24f0232827196ce2bdb6c3d04966f42bd)) -- get js code ([b1fd6bb](https://github.com/wh131462/leetcode-practice/commit/b1fd6bb8d85d080c1f89a53cd99416c84e3abd10)) -- hot100合并代码 ([3ddd7c6](https://github.com/wh131462/leetcode-practice/commit/3ddd7c6237bd43655c4e3d0e490bd997afb1df5a)) -- node vm执行index.js脚本 ([f894e30](https://github.com/wh131462/leetcode-practice/commit/f894e3096c15d9939e0b93688f37c4272775d300)) -- publish config & build config ([1affd2a](https://github.com/wh131462/leetcode-practice/commit/1affd2ab7b1e1ad942d5dc3fbe5c300b5a92f240)) -- sucess log with green and fail log with red ([1eccefb](https://github.com/wh131462/leetcode-practice/commit/1eccefb023d28ca734c1886e0dc64a576d03f860)) -- update function basic ([a01c873](https://github.com/wh131462/leetcode-practice/commit/a01c8738aa060221421f2f17158c92a9069929a0)) -- update project using github ([a879d29](https://github.com/wh131462/leetcode-practice/commit/a879d29f9686f5c71d02bfe5c9122bc6fc90dc81)) -- v1.0.4 ([87428c2](https://github.com/wh131462/leetcode-practice/commit/87428c2c18200492e79e332a149d5af3c8eb6408)) -- v1.0.4 ([8356a57](https://github.com/wh131462/leetcode-practice/commit/8356a57b4d6908d40906d4759cb04367f34e09c3)) -- v1.0.4 ([9c6fca0](https://github.com/wh131462/leetcode-practice/commit/9c6fca0e433f013340dfed5c3e495789dc7e84ca)) -- version 1.0.2 ([4afe55e](https://github.com/wh131462/leetcode-practice/commit/4afe55e35ecea82dedbba3e6a3d9a2738365aa79)) -- **忽略测试覆盖率文件:** 忽略测试覆盖率文件 ([b05e380](https://github.com/wh131462/leetcode-practice/commit/b05e380ef84384f5f1ebbfb64628bd689933f755)) -- 新增填充markdown功能 ([1b8324d](https://github.com/wh131462/leetcode-practice/commit/1b8324d212898e8d0b7b2edc15244da31157a3c9)) -- 新增无向连通图数据结构 parse toArray实现,补充测试用例等 fix: 优化了转换逻辑 ([08f3787](https://github.com/wh131462/leetcode-practice/commit/08f3787f70de41d82610c1ce940f35c878dbf0d1)) -- 新增测试覆盖率 ([2627ecd](https://github.com/wh131462/leetcode-practice/commit/2627ecd00105d4af59e5c2fa59608da1144f17a8)) -- 测试用例中补充树和链表的数据结构以及转换逻辑,新增单元测试模块 ([ac9ccd1](https://github.com/wh131462/leetcode-practice/commit/ac9ccd155358306f667e9ffaa0aac9f16d58988a)) -- 统一数据结构 ([f15a8da](https://github.com/wh131462/leetcode-practice/commit/f15a8dad2500cef476e1340b93053be48364bf3e)) +- add ([fb3fadc](https://github.com/wh131462/leetcode-practice/commit/fb3fadc7fca166be0eefe51a817899466ab48b27)) +- add cz plugin ([4fd5af1](https://github.com/wh131462/leetcode-practice/commit/4fd5af151ac32d3daabcdc862505962fcd32f129)) +- add eslint ([be523ea](https://github.com/wh131462/leetcode-practice/commit/be523ea0f3085e003a2e0b5fb1c568b65cc21714)) +- add get question ([e5572b6](https://github.com/wh131462/leetcode-practice/commit/e5572b6357c8c056aa32eab53476736561261ebe)) +- add get question by keyword function ([097302a](https://github.com/wh131462/leetcode-practice/commit/097302afe095ad70d1c58942dc8ac8fb516e1eed)) +- add getQuestionChineseName function to get chinese name ([9520e75](https://github.com/wh131462/leetcode-practice/commit/9520e757741ff008439affd20db582458a37b674)) +- add getQuestionCode ([dbdb255](https://github.com/wh131462/leetcode-practice/commit/dbdb2553a2c47c9ee40fada33bfec7458ae4ccb6)) +- add memory calculate ([e6c315a](https://github.com/wh131462/leetcode-practice/commit/e6c315ab1524327697278e3b41c622fb22928896)) +- add memory demo ([8065924](https://github.com/wh131462/leetcode-practice/commit/8065924ca451e043f80644a31eb5d9543946f026)) +- add open process ([80dc9f5](https://github.com/wh131462/leetcode-practice/commit/80dc9f530eaae98e5449b3ebdf5c9e69ec452a17)) +- add prettier and commitlint ([608f4df](https://github.com/wh131462/leetcode-practice/commit/608f4dfdc4c0aebb9ead3e46abcde71fcc962b39)) +- change git push rules ([ee3e558](https://github.com/wh131462/leetcode-practice/commit/ee3e558496ef72f2daee071b88e79ddd06503e7c)) +- **cli:** 简化命令 使得命令可以在任何路径下运行 ([26fcffb](https://github.com/wh131462/leetcode-practice/commit/26fcffb8daa0e0a70e78c47772ef5059c1c825d1)) +- **commit:** finish set question range tag in file and get code in file by range tag ([61e2924](https://github.com/wh131462/leetcode-practice/commit/61e2924d2607e96bbd37947f05e718a10ac9edd6)) +- eslint忽略文件 ([f91889c](https://github.com/wh131462/leetcode-practice/commit/f91889c8348766a63136ada6fcd49e79a0e54378)) +- finish the view create & check ([9e96e0a](https://github.com/wh131462/leetcode-practice/commit/9e96e0a24f0232827196ce2bdb6c3d04966f42bd)) +- get js code ([b1fd6bb](https://github.com/wh131462/leetcode-practice/commit/b1fd6bb8d85d080c1f89a53cd99416c84e3abd10)) +- hot100合并代码 ([3ddd7c6](https://github.com/wh131462/leetcode-practice/commit/3ddd7c6237bd43655c4e3d0e490bd997afb1df5a)) +- node vm执行index.js脚本 ([f894e30](https://github.com/wh131462/leetcode-practice/commit/f894e3096c15d9939e0b93688f37c4272775d300)) +- publish config & build config ([1affd2a](https://github.com/wh131462/leetcode-practice/commit/1affd2ab7b1e1ad942d5dc3fbe5c300b5a92f240)) +- sucess log with green and fail log with red ([1eccefb](https://github.com/wh131462/leetcode-practice/commit/1eccefb023d28ca734c1886e0dc64a576d03f860)) +- update function basic ([a01c873](https://github.com/wh131462/leetcode-practice/commit/a01c8738aa060221421f2f17158c92a9069929a0)) +- update project using github ([a879d29](https://github.com/wh131462/leetcode-practice/commit/a879d29f9686f5c71d02bfe5c9122bc6fc90dc81)) +- v1.0.4 ([87428c2](https://github.com/wh131462/leetcode-practice/commit/87428c2c18200492e79e332a149d5af3c8eb6408)) +- v1.0.4 ([8356a57](https://github.com/wh131462/leetcode-practice/commit/8356a57b4d6908d40906d4759cb04367f34e09c3)) +- v1.0.4 ([9c6fca0](https://github.com/wh131462/leetcode-practice/commit/9c6fca0e433f013340dfed5c3e495789dc7e84ca)) +- version 1.0.2 ([4afe55e](https://github.com/wh131462/leetcode-practice/commit/4afe55e35ecea82dedbba3e6a3d9a2738365aa79)) +- **忽略测试覆盖率文件:** 忽略测试覆盖率文件 ([b05e380](https://github.com/wh131462/leetcode-practice/commit/b05e380ef84384f5f1ebbfb64628bd689933f755)) +- 新增填充markdown功能 ([1b8324d](https://github.com/wh131462/leetcode-practice/commit/1b8324d212898e8d0b7b2edc15244da31157a3c9)) +- 新增无向连通图数据结构 parse toArray实现,补充测试用例等 fix: 优化了转换逻辑 ([08f3787](https://github.com/wh131462/leetcode-practice/commit/08f3787f70de41d82610c1ce940f35c878dbf0d1)) +- 新增测试覆盖率 ([2627ecd](https://github.com/wh131462/leetcode-practice/commit/2627ecd00105d4af59e5c2fa59608da1144f17a8)) +- 测试用例中补充树和链表的数据结构以及转换逻辑,新增单元测试模块 ([ac9ccd1](https://github.com/wh131462/leetcode-practice/commit/ac9ccd155358306f667e9ffaa0aac9f16d58988a)) +- 统一数据结构 ([f15a8da](https://github.com/wh131462/leetcode-practice/commit/f15a8dad2500cef476e1340b93053be48364bf3e)) ### Performance Improvements -- better scripts and easy mode to create question in project ([ffd9e29](https://github.com/wh131462/leetcode-practice/commit/ffd9e29ca35d9f4b8b6b2f8b94516e8f053261a5)) -- http dir structure and functions modify ([553ad58](https://github.com/wh131462/leetcode-practice/commit/553ad5861aa67423c1092f798f39b2bd4faf68f6)) +- better scripts and easy mode to create question in project ([ffd9e29](https://github.com/wh131462/leetcode-practice/commit/ffd9e29ca35d9f4b8b6b2f8b94516e8f053261a5)) +- http dir structure and functions modify ([553ad58](https://github.com/wh131462/leetcode-practice/commit/553ad5861aa67423c1092f798f39b2bd4faf68f6)) ### BREAKING CHANGES -- srcipts即将废弃,视图交互性代码完善1/3 +- srcipts即将废弃,视图交互性代码完善1/3 -- feat: finish the view create & check +- feat: finish the view create & check -- feat:完成lc&lk指令 +- feat:完成lc&lk指令 -- fix: 优化代码 +- fix: 优化代码 -- feat: add getQuestionChineseName function to get chinese name +- feat: add getQuestionChineseName function to get chinese name -- chore: del scripts and .vscode files & ignore .vscode +- chore: del scripts and .vscode files & ignore .vscode -- docs: update todo & achive +- docs: update todo & achive -- perf: better scripts and easy mode to create question in project +- perf: better scripts and easy mode to create question in project -- feat: publish config & build config +- feat: publish config & build config -- chore: del src +- chore: del src -- fix: perfect version for cli install +- fix: perfect version for cli install -- fix:指令打包完善 +- fix:指令打包完善 -- fix:easy mode script +- fix:easy mode script -- docs:todo 拆分成单独文件 +- docs:todo 拆分成单独文件 -- chore:路径调整成全局路径 +- chore:路径调整成全局路径 -- docs: add CHANGELOG and TO-DO -- srcipts即将废弃,视图交互性代码完善1/3 +- docs: add CHANGELOG and TO-DO +- srcipts即将废弃,视图交互性代码完善1/3 # 1.0.3 [2024-03-03] ### Features -- You can now create questions in any supported language file. -- Renamed the file from 'index' to 'question'. +- You can now create questions in any supported language file. +- Renamed the file from 'index' to 'question'. # 1.0.2 [2024-02-29] ### Features -- Added i18n docs. +- Added i18n docs. # 1.0.1 [2024-02-08] ### Features -- Added `author` info and `repository` in package.json. +- Added `author` info and `repository` in package.json. # 1.0.0 [2024-02-08] ### Features -- **CLI:** Implemented scripts lk/lf/lc for detection, search, and creation functions, providing convenient creation of questions. -- **Template Project:** Implemented interactive creation with easy mode, leet-create and leet-check now create solutions under the src directory. -- **Plugin:** Perfected the plugin design and initiated the project. +- **CLI:** Implemented scripts lk/lf/lc for detection, search, and creation functions, providing convenient creation of questions. +- **Template Project:** Implemented interactive creation with easy mode, leet-create and leet-check now create solutions under the src directory. +- **Plugin:** Perfected the plugin design and initiated the project. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d983309 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or + advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +hao131462@qq.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/README.md b/README.md index d1ed329..9d266bd 100644 --- a/README.md +++ b/README.md @@ -1,502 +1,296 @@ -# Leetcode practice +# Leetcode practice [](https://www.npmjs.com/package/leetcode-practice) [](https://github.com/EternalHeartTeam/leetcode-practice/actions/workflows/ci.yml) -[Chinese Document](docs/README_CN.md)|**English Document**|[Japanese Document](docs/README_JP.md)|[Korean Document](docs/README_KR.md) +[中文](./README_CN.md) · **English** ·[日本語](./README_JP.md) -## Introduction +## I. Project Information -A brief introduction: "Start practicing your daily LeetCode questions in the editor!" +### 1. Introduction + +One-sentence introduction: "Start practicing your `LeetCode` daily questions in the editor!" If you want to write your solutions in the editor... -If you want to quickly access daily questions... +If you want a simple and quick way to get daily questions... + +If you want to create your own repository for solutions... -If you want to create your own solution repository... +Then, `leetcode-practice` is all you need! -Then, leetcode-practice will meet all your needs! +### 2. Preview -## Preview + - +## II. Instructions for Use -## How should I use it? (Three options for you to choose from) +### 0. Prerequisites -### Option A: CLI (Recommended) +| Tool | Remarks | +| -------- | :---------------------------------------------: | +| nodejs | lts | +| git | lts | +| patience | A heart that can persist in practicing problems | -The best and most flexible way to use it is to use our CLI in the terminal. You can create and check your solutions using three core commands: `lk`, `lf`, and `lc`. +### 1. How Can I Use It? (Three Options for You to Choose From) -[Installation](<#I-Global-Installation-of-CLI-(Option-A)>) · [Usage](#using-cli) +#### Option A. Command-Line Interface (CLI) (Recommended) -### Option B: Fork (Supported) +This option is the most recommended way to use the tool. You can freely create and check your solutions in any directory using the CLI commands `lc`, `lk`, and `lf`. -You can also use GitHub's fork feature to create a copy of our project. Then, you can directly use the built-in commands within the project to create and check solutions. +> Usage Preview -[Installation](<#II-Fork-the-Repository-to-Create-Your-Own-leetcode-practice-Repository-(Option-B)>) · [Usage](#using-the-forked-project) +#### Option B. Template Project (Supported) -### Option C: Plugin (Supported) +If you want to quickly create your own repository for solutions, you can use our template project to quickly create a GitHub project and get comprehensive initialization content. -You can also use our `leetcode-practice` plugin available in the plugin marketplace for interactive creation and checking of solutions. (Supported on two popular editors: `WebStorm` and `VS Code`) +> Usage Preview -[Installation](<#III-Install-Plugins-from-the-Editor's-Marketplace-(Option-C)>) · [Usage](#plugin-usage) +#### Option C. Plugin (Supported, Under Development) -## Prerequisites +If you want to create solutions in your editor by clicking buttons, you can use our editor plugin (planned support for `WebStorm` and `VSCode`) to create solutions in your editor. -| Dependency | Version | -| ---------- | ------- | -| nodejs | lts | -| git | lts | +> Usage Preview -> note: nodejs:[Node.js Installation Guide](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs) -> -> git:[Git Download Link](https://git-scm.com/downloads) +### 2. How Should I Use It? (Detailed Installation and Usage Guides for Three Options) -## Installation +#### Option A. Command-Line Interface (CLI) -### I. Global Installation of CLI (Option A) +##### 1. Installation -You can install the CLI globally using any npm package manager such as `npm`, `yarn`, `pnpm`, etc. +You can install it globally or locally in your project using any npm package manager (e.g., `npm`, `yarn`, `pnpm`). ```shell -# Using npm +# Example: Global Installation +# Using npm for global installation npm install -g leetcode-practice -# Using pnpm +# Using pnpm for installation pnpm install -g leetcode-practice -# Using yarn +# Using yarn for installation yarn global install leetcode-practice -``` - -### II. Fork the Repository to Create Your Own leetcode-practice Repository (Option B) - -#### Regular Method - -1. Open our project link: [leetcode-practice](https://github.com/wh131462/leetcode-practice) - - - -2. Click the `fork` button - -You will see a page like this, then modify the repository name and description, make sure to check `Copy the master branch only`. - - -3. Click confirm to create, wait for creation - - - -4. Once created, pull this repository and start solving problems happily! - - - -#### Simplified Method - -1. Pull our repository to your local machine -```shell -git clone https://github.com/wh131462/leetcode-practice.git -``` - -2. Execute our deployment script - -```shell -# Use your preferred package manager to execute the script -npm run easy-fork +# Example: Installation in the Project +yarn add --dev leetcode-practice ``` -3. Deployment completed - -### III. Install Plugins from the Editor's Marketplace (Option C) - -To be developed... - -## Usage +> Note: The difference between installing in the project and globally lies in the scope of the CLI commands. If installed in the project, the commands can only be used within that project, and cannot be used in other projects (where the `leetcode-practice` package is not installed). Global installation allows you to use the commands in any directory. -### Using CLI +##### 2. Usage -#### 1. Creating Solutions - `lc` +Here's a simple introduction to creating and checking daily questions, as well as using keyword search. For more detailed instructions and parameters, please refer to the [KFC and its Key Parameter Explanation](#3-kfc-and-its-key-parameter-explanation-universal-reference-manual) section. -##### [1]. Get Today's Problem - [`-t`/`--today`] +###### 2.1 Creating a Question -Type `lc` in the terminal to get today's problem in the current working directory by default. +Within the command scope, use the command `lc` to create today's daily question: ```shell +# Move to my workspace directory +cd my-workspace +# Create the daily question lc -# Full command -lc -t ``` -Example of getting today's problem: +When you see the prompt: ```shell -# For example, the current execution directory is src -➜ src git:(dev) ✗ lc MODE: today -Successfully obtained problem [2867.Count the Number of Valid Paths in a Tree]! -Problem file address is: /home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js +题目[299.猜数字游戏]获取成功! +题目文件地址为:/my-workspace/299.bulls-and-cows/question.js ``` -##### [2]. Get Specified Problem - [`-i`/`--identity`] +Your question has been created! You can now solve it happily in the editor! -Type `lc` followed by the corresponding problem number in the terminal to get the specified problem in the current working directory. +###### 2.2 Checking a Question -```shell -lc 1314 -# Full command -lc -i 1314 -# Use double quotation marks (") to ensure accurate identification, especially for problem numbers with spaces -lc -i "LCP 50" -``` - -Example of getting problem `LCP 50`: +Once you've written your solution code, you can use the `lk` command to perform a simple check of the solution! ```shell -➜ src git:(dev) ✗ lc "LCP 50" -MODE: identity -Successfully obtained problem [LCP 50.Supply of Jewel]! -Problem file address is: /home/wh131462/workspace/leetcode-practice/src/LCP 50.WHnhjV/index.js -``` - -##### [3]. Get Random Problem - [`-r`/`--random`] - -Type `lc` followed by the `-r` parameter in the terminal to get a random problem in the current working directory. It will prioritize obtaining problems not currently in the directory. - -```shell -# Full command -lc -r -``` - -Example of getting a random problem: - -```shell -➜ src git:(dev) ✗ lc -r -MODE: random -Successfully obtained problem [14.Longest Common Prefix]! -Problem file address is: /home/wh131462/workspace/leetcode-practice/src/14.longest-common-prefix/index.js -``` - -##### [5]. Easy Creation Mode (Interactive Creation) - [`-e`/`--easy`] - -In addition to creating problems quickly with precise commands as mentioned above, you can also use easy creation mode for interactive creation. - -```shell -lc -e -``` - -Example of creating today's problem using easy mode: - -```shell -➜ src git:(dev) ✗ lc -e -? Select the problem creation mode: today -? Create the problem [ 2867.count-valid-paths-in-a-tree ] in the directory [ /home/wh131462/workspace/leetcode-practice/src ]? Yes -Problem [2867.count-valid-paths-in-a-tree] created! -File address is: /home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js - -``` - -#### 2. Checking Solutions - `lk` - -##### [1]. Check Today's Solution [`-t`/`--today`] - -Type `lk` in the terminal to check today's solution in the current working directory. - -```shell -# By default, check today's solution +# The lk command corresponds to the lc command mode, and when used without parameters, it means checking today's question lk -# Full command -lk -t ``` -Example of checking today's solution: +You will receive information like this: ```shell -# Specified src directory as the root directory -workspace/leetcode-practice [dev●] » lk -d src -t MODE: today -Check result for problem [2581.Count Possible Trees]: -``` - -| index | Test Result | Expected Result | Execution Result | Execution Time | Memory Usage | -| ----- | ----------- | --------------- | ---------------- | -------------- | ------------ | -| 0 | 'Failed' | '3' | undefined | 0.0921ms | 2.52 KB | -| 1 | 'Passed' | '5' | undefined | 0.0119ms | 2.66 KB | - -> Click to jump to problem submission: <https://leetcode.com/problems/count-number-of-possible-root-nodes/> - -##### [2]. Check Specified Solution [`-i`/`--identity` + `<identity>`] - -Type `lk` followed by the problem number in the terminal to check the specified solution in the current working directory. - -```shell -# Check specified solution -lk 2581 -# Full command -lk -i 2581 -# For problem numbers with spaces, use double quotation marks -lk "LCP 50" +题目[299.猜数字游戏]检测结果: +┌────────────┬──────────────────────────────────────────┬──────────────────────────────────────────┬────────────┬────────────┐ +│ 测试结果 │ 预期结果 │ 执行结果 │ 执行用时 │ 内存占用 │ +├────────────┼──────────────────────────────────────────┼──────────────────────────────────────────┼────────────┼────────────┤ +│ 通过 │ "1A3B" │ "1A3B" │ 0.1361ms │ 2.79 KB │ +│ 通过 │ "1A1B" │ "1A1B" │ 0.0623ms │ 2.93 KB │ +└────────────┴──────────────────────────────────────────┴──────────────────────────────────────────┴────────────┴────────────┘ +Click here to submit the question: https://leetcode-cn.com/problems/bulls-and-cows/ ``` -Example of checking the specified solution: +You can see the `Test Result`, `Expected Result`, `Execution Result`, `Execution Time`, and `Memory Usage` information. -```shell -workspace/leetcode-practice [dev●] » lk -d src 2581 -MODE: identity -Check result for problem [2581.Count Possible Trees]: -``` - -| index | Test Result | Expected Result | Execution Result | Execution Time | Memory Usage | -| ----- | ----------- | --------------- | ---------------- | -------------- | ------------ | -| 0 | 'Passed' | '3' | '3' | 0.1668ms | 2.52 KB | -| 1 | 'Passed' | '5' | '5' | 0.0234ms | 2.66 KB | +###### 2.3 Searching for a Question -> Click to jump to problem submission: <https://leetcode.com/problems/count-number-of-possible-root-nodes/> - -##### [3]. Check Randomly Obtained Solution [`-r`/`--random`] - -Type `lk` followed by the `-r` parameter in the terminal to check the previously randomly obtained solution in the current working directory. +Keyword search is a basic function of the core command `lf`, which allows you to quickly search for the question you want and choose to create it. ```shell -# Full command -lk -r -``` - -Example of checking a randomly obtained solution: - -```shell -workspace/leetcode-practice [dev●] » lk -r -MODE: random -Check result for problem [41.First Missing Positive]: +# The lf command is completely interactive. Follow the prompts to enter the desired information +lf ``` -| index | Test Result | Expected Result | Execution Result | Execution Time | Memory Usage | -| ----- | ----------- | --------------- | ---------------- | -------------- | ------------ | -| 0 | 'Failed' | '3' | undefined | 0.0896ms | 2.42 KB | -| 1 | 'Failed' | '2' | undefined | 0.0110ms | 2.56 KB | -| 2 | 'Failed' | '1' | undefined | 0.0045ms | 2.56 KB | - -> Click to jump to problem submission: <https://leetcode.com/problems/first-missing-positive/> -> -> Note: Ensure that `lc -r` has been executed before this command to create a random problem. - -##### [4]. Easy Mode (Interactive Checking) [`-e`/`--easy`] - -Type `lk` followed by the `-e` parameter in the terminal to use interactive mode for checking the problem. +The following demonstrates how to use keyword search to create the `Two Sum` question: ```shell -# Full command -lk -e -``` +# After entering the keyword `two sum` and pressing Enter, all questions related to `two sum` will appear. Use the up and down arrow keys on the keyboard to select, and press Enter to confirm. +? Choose the search mode? Keyword search +? Enter keywords two sum +? Choose a question + LCR 025.两数相加 II + 2.两数相加 + 29.两数相除 +❯ 1.两数之和 + LCR 006.两数之和 II - 输入有序数组 + 445.两数相加 II + LCR 056.两数之和 IV - 输入二叉搜索树 +(Use arrow keys to reveal more choices) -Example of checking the specified problem using easy mode: - -```shell -workspace/leetcode-practice [dev●] » lk -e -? Select the mode of problem checking: identity -? Enter the problem number: 41 -? Do you want to check the problem [ 41.first-missing-positive ] in the current directory [ /Users/mac-106/wh131462/workspace/leetcode-practice ]? Yes +# After confirmation, the question will be created, and a success message will be returned +? Choose the search mode? Keyword search +? Enter keywords two sum +? Choose a question 1.两数之和 +1 +MODE: identity +题目[1.两数之和]获取成功! +题目文件地址为:fill:///my-workspace/1.two-sum/question.js:36 ``` -| index | Test Result | Expected Result | Execution Result | Execution Time | Memory Usage | -| ----- | ----------- | --------------- | ---------------- | -------------- | ------------ | -| 0 | 'Failed' | '3' | undefined | 0.0969ms | 2.42 KB | -| 1 | 'Failed' | '2' | undefined | 0.0139ms | 2.56 KB | -| 2 | 'Failed' | '1' | undefined | 0.0051ms | 2.56 KB | - -> Click to jump to problem submission: <https://leetcode.com/problems/first-missing-positive/> -> Problem [41.first-missing-positive] checked! -> File address is: /Users/mac-106/wh131462/workspace/leetcode-practice/41.first-missing-positive/index.js +> Note: When the creation is complete, a clickable file address will be output. If clicked in the editor console, it will directly open the corresponding file to the start of the function. -#### 3. Problem Lookup - `lf` +#### Option B. Template Project -To be developed... +##### 1. Creating a Template Project -##### [1]. View Problem List [To be developed] +1. Open -#### 4. Common Parameters +our template project [leetcodePracticeTemplate](https://github.com/EternalHeartTeam/LeetcodePracticeTemplate) on GitHub. 2. Click on `Use this template` in the upper right corner and select `Create a new repository`. 3. Fill in the information as you would when creating a normal repository. 4. Wait... and you're done. You now have your own `LeetCode solutions repository` and will receive long-term support from the `leetcode-practice` official team! -##### [1]. Get or specify the current programming language - [-l/-language [language]] +> Fill in the creation process chart -You can use -l without arguments to get the current programming language setting, or you can specify the language parameter to set the language environment of the current CLI to the specified language. +##### 2. Using the Template Project -```shell -# This parameter behaves consistently in lc/lk/lf -lc -l -lk -l java -``` +###### 1. Clone the project and initialize the dependencies. -Usage example: +e.g. Using my personal project as an example ```shell -# Get language environment -➜ leetcode-practice git:(dev) ✗ lc -l -Current CLI language environment is: javascript -# Change language environment -➜ leetcode-practice git:(dev) ✗ lc -l java -? Please confirm the language environment you want to set for the CLI (Press Enter to confirm if the option matches) java -Setting language environment to: java +# This is just an example. Please clone your own project (when you attempt this, the project may have been cleared, which is a normal phenomenon, please don't be surprised) +git clone git@github.com:wh131462/my-leetcode-practice.git +# Move into the project directory +cd my-leetcode-practice +# Initialize +npm i ``` -Note: Unable to execute test cases in this environment. +###### 2. Usage in the project -##### [2]. Specify Directory - [`-d`/`-directory`] - -The `create` and `check` commands can also use the `-d` parameter to specify a relative address based on the current working directory as the specified directory. -When specifying a directory, the operation will be performed in that directory. +There are two ways to use the `leetcode-practice` in the template project: `project internal commands` and `npm scripts`. The process of creation is demonstrated below, and other command usages and parameters are consistent with the scaffold. Please refer to the [KFC and its Key Parameter Explanation](#3-kfc-and-its-key-parameter-explanation-universal-reference-manual) section. ```shell -# Use the src directory as the generation directory -lc -d src -t -# Use the src directory as the check directory -lk -d src -i +# Under the root directory of the project, execute npm run lc to create today's question. Because -d src is configured by default, the creation will be done under the src directory +npm run lc +# You can also use yarn: any package management tool you like +yarn lc ``` -Example: +You can also use the `lc` command to create, of course, you can only use our script in the project (if you haven't installed the `leetcode-practice` package globally). ```shell -➜ src git:(dev) ✗ lc -d src -t -MODE: today -Successfully obtained problem [2867.Count the Number of Valid Paths in a Tree]! -Problem file address is: /home/wh131462/workspace/leetcode-practice/src/src/2867.count-valid-paths-in-a-tree/index.js -``` - -> Note: If the specified directory does not exist, an empty directory will be created. - -##### [3]. Check Version [`-V`/`--version`] - -```shell -# Check lc version -lc -V -# Check lk version -lk -V -# Check lf version -lf - - -V +# Using lc will create in the current working directory. If you need to keep consistent with the script's behavior (creating under src directory), please use the -d src parameter +lc ``` -Example of checking the lc version: - -```shell -workspace/leetcode-practice [dev●] » lc -V -0.0.0 -``` +> Note: Here's an emphasis. The term "project internal command" means that the scope of the command is limited to the current project directory, meaning that if you try to use the lc command in another directory, you'll find that it doesn't work. Similarly, you'll find that when you first install it, the lc command doesn't work in the project until you close and reopen the terminal (terminal) to manually refresh the cache. npm script refers to a script command encapsulated under the scripts field in package.json. -##### [4]. Update Check [`-u`/`--update`] +###### 3. Updating Dependencies -Using the `-u` or `--update` parameter, you can check whether the current version is the latest version. If the current version is not the latest version, you will be prompted whether to update. +When you want to update, you can execute the encapsulated npm command `update`, which can help you install the `latest version (latest)` of `leetcode-practice`. ```shell -lk -u -lf -u -lc -u +# Execute using any package management tool +npm run update +# Of course, you can also execute the command yourself +npm i -D leetcode-practice ``` -```shell -? Automatically detected environment is [ project ], if not, please make a selection, if yes, please press Enter to confirm. project -Start getting version number in npm repository... -Successfully obtained version number in npm repository! -Start getting version number in github repository... -Successfully obtained version number in github repository! -Start getting local version number... -Successfully obtained local version number! -Current version:[ 1.0.0 ] npm package latest version:[ 1.0.1 ] github version:[ 1.0.1 ] -? Detected [ project ] can update to version[ 1.0.1 ], whether to update? (Y/n) Yes -Update completed~Enjoy your use~ -``` +#### Option C. Plugin (Under Development) -### Using the Forked Project +### 3. KFC and its Key Parameter Explanation (Universal Reference Manual) -#### [0]. Dependency Installation +#### [0]. What is KFC? -Before using, install dependencies using a package manager. +`KFC` is a simple mnemonic that can quickly remember our three core commands: `lk`, `lf`, and `lc`. -```shell -# Install dependencies -npm install -# Or use yarn (you can use any package manager you like) -yarn -``` +| Command | Explanation | +| ------- | --------------------------------------------------------------------------------------------------------------------------------- | +| lk | Core checking command, supports three modes corresponding to the question for checking questions | +| lf | Core search command, which can quickly search for the question you want based on prompts | +| lc | Core creation command, supports three creation modes (daily question, specified question, random question) for creating questions | -The commands in the forked project are the same as those in the CLI usage parameters, except that the scripts are executed through the package manager such as `npm run`. +#### [1]. lk -> Note: The only difference between the scripts in the project and the scaffolding is that the `-d` parameter is specified by default, pointing to the `src` directory at the root of the project, so all commands are executed by default in `src`. +| Short Parameter | Full Parameter | Explanation | +| --------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| No parameter / `-t` | `--today` | Check today's daily question | +| Question number / `-i <identity>` | `--identity <identity>` | Check the question corresponding to the specified number, and check if the question with the specified ID exists in the current working directory | +| `-r` | `--random` | Check the question created using the random mode last time | +| `-e` | `--easy` | Interactive check of the corresponding question based on prompts | -#### [1]. Create Solution [`lc`] +> Note: When checking, please pay attention to what mode to use for checking, and make sure that you have performed the corresponding mode creation operation. +> The specified ID mode is an exception because it will check whether the specified ID exists in the current working directory. -Refer to the `lc` part of the CLI for parameters: [lc](#1-creating-solutions---lc) +#### [2]. lf -Simple usage example: +| Short Parameter | Full Parameter | Explanation | +| --------------- | -------------- | ------------------------------------------------------------------------- | +| No parameter | None | Enter interactive search, and search or filter questions based on prompts | -```shell -# Execute using yarn -yarn lc 1314 -``` +#### [3]. lc -Execution result: +| Short Parameter | Full Parameter | Explanation | +| --------------------------------- | ----------------------- | --------------------------------------------------------------------------------------- | +| No parameter / `-t` | `--today` | Create today's daily question | +| Question number / `-i <identity>` | `--identity <identity>` | Create the question corresponding to the specified number | +| `-r` | `--random` | Create a random question that has not appeared in the current directory | +| `-e` | `--easy` | Interactive creation of questions | +| `-a` | `--all` | Fetch all questions from server and store them locally, prepare database for lf command | -```shell -# Generated in the src directory -> yarn lc 1314 -yarn run v1.22.19 -$ node bin/lc.js -d src 1314 -MODE: identity -Successfully obtained problem [1314.Matrix Block Sum]! -Problem file address is:/Users/mac-106/wh131462/workspace/leetcode-practice/src/1314.matrix-block-sum/index.js -✨ Done in 1.06s. -``` +#### [4]. General Parameters -#### [2]. Check Solution [`lk`] +| Short Parameter | Full Parameter | Explanation | +| ---------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `-d <directory>` | `--directory <directory>` | Specify the working directory (a relative address of the current execution directory), which will affect the creation and checking | +| `-V` | `--version` | Check the version number | +| `-v` | `--ver` | Check the version info and some extra info about leetcode-practice | +| `-h` | `--help` | Get help information | +| `-l [language]` | `--language [language]` | Without specifying a parameter, get the current language environment (default is JavaScript). Specifying a parameter can set the language environment to the corresponding language (e.g., `-l java` sets the language environment to Java) | +| `-u` | `--update` | Update the current script or dependency | -Refer to the `lk` part of the CLI for parameters: [lk](#2-checking-solutions---lk) +> Note: General parameters refer to parameters supported by all three scripts `lk`, `lf`, and `lc`. The semantics of usage are generally the same, but there may be differences in the meanings of behaviors in some commands (for example, specifying the `-d` parameter in the `lc` command means `creating questions in the specified directory`, while in the `lk` command, specifying the `-d` parameter means `creating questions in the specified directory`). -Simple usage example: +## III. Additional Information -```shell -# Execute using yarn -yarn lk 1314 -``` +### 1. Contributors -Execution result: +The development and improvement of the project would not be possible without the hard work of these contributors. Sincere thanks to all of them! -```shell -# Checked in the src directory -> yarn lk 1314 -yarn run v1.22.19 -$ node bin/lk.js -d src 1314 -MODE: identity -Check result for problem [1314.Matrix Block Sum]: -``` - -| index | Test Result | Expected Result | Execution Result | Execution Time | Memory Usage | -| ----- | ----------- | ------------------------------------ | ---------------- | -------------- | ------------ | -| 0 | 'Failed' | '[[12,21,16],[27,45,33],[24,39,28]]' | undefined | 0.1487ms | 2.47 KB | -| 1 | 'Failed' | '[[45,45,45],[45,45,45],[45,45,45]]' | undefined | 0.0278ms | 2.61 KB | - -> Click to jump to problem submission: <https://leetcode.com/problems/matrix-block-sum/> -> ✨ Done in 1.13s. - -#### [3]. Look Up Solutions [`lf`] - -Refer to the `lf` part of the CLI for parameters: [lf](#3-problem-lookup---lf) - -To be developed... - -#### [4]. Update [`update`] - -This is a special script to update the local project, which updates all non-src directories to synchronize with the latest features of the project. - -> Note: If you have your own optimized code changes, be cautious about this step! Please refer to our [upgrade plan under special circumstances](./update.md)! - -### Plugin Usage +<a href="https://github.com/EternalHeartTeam/leetcode-practice/graphs/contributors" target="_blank"><img src="https://raw.githubusercontent.com/EternalHeartTeam/leetcode-practice/svg/images/contributors.png" /></a> -To be developed... +### 2. How to Contribute -## Contributors +If you share a passion for open source and would like to contribute to our open source initiative, please refer to our [contribution guidelines](./.github/CONTRIBUTING.md). -<a href="https://github.com/EternalHeartTeam/leetcode-practice/graphs/contributors" target="_blank"><img src="https://raw.githubusercontent.com/EternalHeartTeam/leetcode-practice/svg/images/contributors.png" /></a> +### 3. Feedback -## Feedback +If you have any questions about usage or would like to offer some suggestions, feel free to join our feedback group! -If you encounter any `issues` or have some `great suggestions`, feel free to join our `Feedback Group` for providing `feedback`! We will address them promptly! +Engage in face-to-face discussions with developers in the group, hoping to resonate with each other and spark new ideas! - + -## Star History +### 4. Star Trend Chart [](https://star-history.com/#EternalHeartTeam/leetcode-practice&Date) diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000..e235900 --- /dev/null +++ b/README_CN.md @@ -0,0 +1,301 @@ +# Leetcode practice [](https://www.npmjs.com/package/leetcode-practice) [](https://github.com/EternalHeartTeam/leetcode-practice/actions/workflows/ci.yml) + +**中文** · [English](./README.md) · [日本語](./README_JP.md) + +## I.项目信息 + +### 1.简介 + +一句话介绍:“在编辑器中开始练习你的`leetcode`每日一题!” + +如果,你想要在编辑器中编写你的题解... + +如果,你想要简单快速的获取每日一题... + +如果,你想要创建你自己的题解仓库... + +那么,`leetcode-practice`将满足你的一切想要! + +### 2.预览 + + + +## II.使用须知 + +### 0. 预备条件 + +| 工具 | 备注 | +| -------- | :------------------: | +| nodejs | lts | +| git | lts | +| patience | 一颗能够坚持刷题的心 | + +### 1. 我可以怎么用? (三种方案供你选择) + +#### 方案A.脚手架 CLI (推荐) + +此方案是最为推荐的使用方案,通过脚手架指令`lc`、`lk`、`lf`自由灵活的在任意的目录中创建并检查你的题解。 + +> 使用预览 + +#### 方案B.模板项目 Template project (支持) + +如果你想要快速的创建一个自己的题解库,可以使用我们的模板项目进行快速的创建github项目,并且获得完善的初始化内容。 + +> 使用预览 + +#### 方案C.插件 Plugin (支持,待开发) + +如果你想在编辑器中通过点击操作按钮来创建题解,可以使用我们的编辑器插件(计划支持`WebStorm`和`VSCode`)在你的编辑器中创建题解。 + +> 使用预览 + +### 2. 我应该怎么用?(三种方案的详细的安装和使用教程) + +#### 方案A.脚手架 CLI + +##### 1.安装 + +你可以使用任意一款npm包管理软件(例如`npm`,`yarn`,`pnpm`等)的在`项目`中或者`全局`进行安装。 + +```shell +# 示例:全局安装 +# 使用npm进行全局安装 +npm install -g leetcode-practice +# 使用pnpm进行安装 +pnpm install -g leetcode-practice +# 使用yarn进行安装 +yarn global install leetcode-practice + +# 示例:在项目中安装 +yarn add --dev leetcode-practice +``` + +> 提示: 在项目中安装和全局安装的区别在于脚手架的作用范围不同。如果在项目中安装,那么指令只能在该项目内使用,而在其他项目中(未安装leetcode-practice包的情况下)则无法使用指令。而全局安装则允许在任何目录下使用指令。 + +##### 2.使用 + +在这里给大家简单介绍一下每日一题的`创建`和`检查`,还有关键词搜索的使用方式,最为详细具体的指令和参数请参照[KFC及其关键参数说明 ](#3-kfc及其关键参数说明-三种方案通用的参考手册) + +###### 2.1 创建题目 + +在指令作用范围中,执行指令`lc`来进行创建今天的每日一题: + +```shell +# 移动到我的工作目录中 +cd my-workspace +# 创建每日一题 +lc +``` + +当看到提示: + +```shell +MODE: today +题目[299.猜数字游戏]获取成功! +题目文件地址为:/my-workspace/299.bulls-and-cows/question.js +``` + +你的题目就已经创建完成了!可以在编辑器中愉快的解题了! + +###### 2.2 检查题目 + +当你完成解题代码的编写,可以通过`lk`指令进行简单的检查题解! + +```shell +# lk指令和lc指令的模式是对应的,不带参数的时候意为检查今日题目 +lk +``` + +你会得到如下提示信息: + +```shell +MODE: today +题目[299.猜数字游戏]检测结果: +┌────────────┬──────────────────────────────────────────┬──────────────────────────────────────────┬────────────┬────────────┐ +│ 测试结果 │ 预期结果 │ 执行结果 │ 执行用时 │ 内存占用 │ +├────────────┼──────────────────────────────────────────┼──────────────────────────────────────────┼────────────┼────────────┤ +│ 通过 │ "1A3B" │ "1A3B" │ 0.1361ms │ 2.79 KB │ +│ 通过 │ "1A1B" │ "1A1B" │ 0.0623ms │ 2.93 KB │ +└────────────┴──────────────────────────────────────────┴──────────────────────────────────────────┴────────────┴────────────┘ +点击跳转到题目提交: https://leetcode.cn/problems/bulls-and-cows/ +``` + +你可以看到`测试结果`、`预期结果`、`执行结果`、`执行用时`以及`内存占用`信息。 + +###### 2.3 搜索题目 + +关键词搜索是核心指令`lf`的一项基本功能,可以通过关键词的形式获取题目信息,并快速的选择创建。 + +```shell +# lf指令是一个完全交互式的指令 按其中的提示进行输入操作即可获取自己想要的信息 +lf +``` + +以下演示获取`两数之和`这个题目如何通过关键词搜索创建: + +```shell +# 在输入关键词 两数 之后 按下回车 会出现所有和两数相关的题目 按键盘的上下键进行选择 回车进行确认 +? 请选择查找的模式? 关键词搜索 +? 请输入关键词 两数 +? 请选择题目 +LCR 025.两数相加 II +2.两数相加 +29.两数相除 +❯ 1.两数之和 +LCR 006.两数之和 II - 输入有序数组 +445.两数相加 II +LCR 056.两数之和 IV - 输入二叉搜索树 +(Use arrow keys to reveal more choices) + +# 确认后的会进行题目创建,返回成功信息 +? 请选择查找的模式? 关键词搜索 +? 请输入关键词 两数 +? 请选择题目 1.两数之和 +1 +MODE: identity +题目[1.两数之和]获取成功! +题目文件地址为:fill:///my-workspace/1.two-sum/question.js:36 +``` + +> 提示: 在创建完成的时候会输出一个可以点击跳转的文件地址,如果在编辑器的控制台中点击,会直接打开对应的文件的函数开始位置。 + +#### 方案B.模板项目 Template project + +##### 1.创建模板项目 + +1. 在`github`中打开我们的模板项目[leetcodePracticeTemplate](https://github.com/EternalHeartTeam/LeetcodePracticeTemplate)。 +2. `点击`右上角的`Use this template`,选择[`Create a new repository`](https://github.com/new?template_name=LeetcodePracticeTemplate&template_owner=EternalHeartTeam)。 +3. 就像创建一个正常的仓库一样去填写信息即可。 +4. 等待...然后完成,从此你就有了一个自己的`leetcode题解仓库`,并且长期受`leetcode-practice`官方支持! + +> 填充创建过程图 + +##### 2. 使用模板项目 + +###### 1. 拉取项目,并进行初始化依赖。 + +e.g. 以我个人的项目为例 + +```shell +# 这里只是示例,请拉取自己的项目(在你看到这进行尝试的时候,此项目可能已经被清理,正常现象请勿疑惑) +git clone git@github.com:wh131462/my-leetcode-practice.git +# 移动进项目目录 +cd my-leetcode-practice +# 初始化 +npm i +``` + +###### 2. 在项目中的使用 + +在模板项目中使用`leetcode-practice`的方式有两种,一种是`项目内指令`的形式,一种是`npm脚本`的形式。接下来演示创建的过程,其他的指令用法和参数与脚手架一致,请参考[KFC及其关键参数说明](#3-kfc及其关键参数说明-三种方案通用的参考手册)部分。 + +```shell +# 在项目的根目录下 执行npm run lc 创建今日一题,因为默认配置了 -d src 所以 会在 src 目录下进行创建 +npm run lc +# 也可以使用 yarn :任意一种你喜欢的包管理工具 +yarn lc +``` + +你也可以使用指令`lc`来创建,当然,你只能在项目中使用我们的脚本(如果你没有全局安装`leetcode-practice`的话)。 + +```shell +# 使用lc 会在当前工作目录创建 如果 需要和脚本的表现保持一致(指在src目录下创建),请使用 -d src 参数 +lc +``` + +> 注意:在这里进行一下强调,项目内指令的说法是指指令的作用范围限制是当前的项目目录,也就是说在其他的目录,你尝试使用lc指令会发现不起作用。 +> +> 同样的,你也会发现在第一次安装好的时候,在项目内使用lc指令,也是不起作用的,这个时候需要关闭终端(terminal)再打开进行手动的刷新缓存。 +> +> npm脚本指在 package.json 中的 scripts 字段下封装的脚本指令。 + +###### 3. 更新依赖 + +当你想要进行更新的时候,可以执行封装好的npm指令:`update`,可以帮你安装`最新版本(latest)`的`leetcode-practice`。 + +```shell +# 使用任意一种包管理工具执行即可 +npm run update +# 当然你也可以自己执行指令 +npm i -D leetcode-practice +``` + +#### 方案C.插件 Plugin (待开发) + +### 3. KFC及其关键参数说明 (三种方案通用的参考手册) + +#### [0].什么是KFC? + +`KFC`是一个简便记法,可以快速记忆我们的三个核心指令:`lk`,`lf`,`lc`。 + +| 指令 | 说明 | +| ---- | ------------------------------------------------------------------------------------------------------ | +| lk | 核心检查指令,支持三种模式对应的题目检测 | +| lf | 核心查找指令,可以快捷的搜索你想要的题目,支持Hot100,关键词搜索,条件筛选等模式进行搜索题目并支持创建 | +| lc | 核心创建指令,支持三种创建模式 ( 每日一题、指定题目、随机题目 ) 进行题目的创建 | + +#### [1].lk + +| 简单参数 | 完整参数 | 说明 | +| ------------------------ | ----------------------- | ---------------------------------------------------------------------- | +| 无参数/`-t` | `--today` | 检查今日的每日一题 | +| 题目编号/`-i <identity>` | `--identity <identity>` | 检查指定编号对应的题目,会检查当前工作目录下的是否存在指定id对应的题目 | +| `-r` | `--random` | 检查上一次使用随机模式创建的题目 | +| `-e` | `--easy` | 交互式的根据提示去检查对应的题目 | + +> 注意: 当你检测的时候需要注意,使用什么模式去检查,请确保你已经执行过对应模式的创建操作。 +> 指定编号模式除外,因为会优先检查指定的id是否在当前工作目录存在。 + +#### [2].lf + +| 简单参数 | 完整参数 | 说明 | +| -------- | -------- | -------------------------------------------------- | +| 无参数 | 无 | 进入交互式查询,可根据提示搜索或筛选题目并创建题目 | + +#### [3].lc + +| 简单参数 | 完整参数 | 说明 | +| ------------------------ | ----------------------- | -------------------------------- | +| 无参数/`-t` | `--today` | 创建今日的每日一题 | +| 题目编号/`-i <identity>` | `--identity <identity>` | 创建指定编号对应的题目 | +| `-r` | `--random` | 创建当前目录下未出现过的随机题目 | +| `-e` | `--easy` | 交互式创建题目 | +| `-a` | `--all` | 获取全部题目缓存,用于lf指令 | + +#### [4].通用参数 + +| 简单参数 | 完整参数 | 说明 | +| ---------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| `-d <directory>` | `--directory <directory>` | 指定工作目录(是一个当前执行目录的相对地址),会影响创建和检查 | +| `-V` | `--version` | 检查版本号 | +| `-v` | `--ver` | 检查版本号信息并且输出一些额外的信息 | +| `-h` | `--help` | 获取帮助信息 | +| `-l [language]` | `--language [language]` | 不指定参数为获取当前的语言环境(默认为javascript),指定参数可以设置语言环境为对应语言(如`-l java`可以指定语言环境为java) | +| `-u` | `--update` | 更新当前脚本或者依赖 | + +> 注意:通用参数指三个脚本`lk`,`lf`,`lc`都支持的参数,使用上的语义一般来说是相同的,但是可能有些指令上的行为含义会有所不同(比如`lc`指令指定`-d`参数是指`在指定目录中创建题目`,而`lk`指令指定`-d`参数就是指`在指定目录创建题目`)。 + +## III.其他信息 + +### 1. 贡献者们 + +项目的开发和完善离不开这些贡献者的辛勤付出,在此真诚感谢各位大佬的付出! + +<a href="https://github.com/EternalHeartTeam/leetcode-practice/graphs/contributors" target="_blank"><img src="https://raw.githubusercontent.com/EternalHeartTeam/leetcode-practice/svg/images/contributors.png" /></a> + +### 2.如何贡献 + +如果你也有一颗热爱开源的心,想要为我们的开源事业贡献一份力量,那么请参考我们的[贡献手册](./.github/CONTRIBUTING.md)。 + +### 3.使用反馈 + +如果你有使用上的问题需要解惑,或者一些好的建议想要提出,可以加我们的使用反馈群进行反馈! + +在群里和开发者面对面的交流,希望我们能产生共鸣,迸发出新的火花! + + + +### 4.Star趋势图 + +[](https://star-history.com/#EternalHeartTeam/leetcode-practice&Date) diff --git a/README_JP.md b/README_JP.md new file mode 100644 index 0000000..72ebcca --- /dev/null +++ b/README_JP.md @@ -0,0 +1,291 @@ +# Leetcode practice [](https://www.npmjs.com/package/leetcode-practice) [](https://github.com/EternalHeartTeam/leetcode-practice/actions/workflows/ci.yml) + +[中文](./README_CN.md) · [English](./README.md) · **日本語** + +## I.プロジェクト情報 + +### 1.概要 + +一文で述べると、「エディタで毎日の`leetcode`問題を練習し始めましょう!」 + +もし、エディタで問題を解きたい場合... + +もし、簡単で迅速に毎日の問題を取得したい場合... + +もし、自分の解答リポジトリを作成したい場合... + +そのすべてができるのが`leetcode-practice`です! + +### 2.プレビュー + + + +## II.使用上の注意 + +### 0.前提条件 + +| ツール | 備考 | +| ------ | :----------------------: | +| nodejs | lts | +| git | lts | +| 我慢 | 問題を解き続けるための心 | + +### 1. どう使えるのか? (3つの選択肢) + +#### オプションA.スクリプトCLI (おすすめ) + +この方法は、自由自在に`lc`、`lk`、`lf`のスクリプトコマンドを使用して、任意のディレクトリで問題を作成およびチェックするためにお勧めされています。 + +> 使用例 + +#### オプションB.テンプレートプロジェクト (サポート) + +自分の解答リポジトリを素早く作成したい場合は、当社のテンプレートプロジェクトを使用して、GitHubプロジェクトを素早く作成し、初期化されたコンテンツを取得できます。 + +> 使用例 + +#### オプションC.プラグイン (サポート、開発中) + +エディタで問題を作成するためにクリック操作を使用したい場合は、当社のエディタプラグイン(予定では`WebStorm`および`VSCode`をサポート)を使用して、エディタで問題を作成できます。 + +> 使用例 + +### 2. どうすればいいですか?(3つの選択肢の詳細なインストールおよび使用手順) + +#### オプションA.スクリプトCLI + +##### 1.インストール + +`lc`、`lk`、`lf`のスクリプトを使用して、任意のnpmパッケージ管理ソフトウェア(たとえば*`npm`*、_`yarn`_、*`pnpm`*など)で`プロジェクト`または`グローバル`にインストールできます。 + +```shell +# 例:グローバルインストール +# npmを使用してグローバルにインストール +npm install -g leetcode-practice +# pnpmを使用してインストール +pnpm install -g leetcode-practice +# yarnを使用してインストール +yarn global install leetcode-practice + +# 例:プロジェクト内のインストール +yarn add --dev leetcode-practice +``` + +> ヒント: プロジェクト内およびグローバルインストールの違いは、スクリプトの範囲が異なることです。プロジェクト内でインストールすると、スクリプトはそのプロジェクト内でのみ使用できますが、他のプロジェクトでは(leetcode-practiceパッケージがインストールされていない場合)スクリプトを使用できません。一方、グローバルインストールでは、どのディレクトリでもスクリプトを使用できます。 + +##### 2.使用 + +ここでは、毎日の`作成`および`チェック`、およびキーワード検索の方法を簡単に説明します。詳細なスクリプトとパラメータについては、[KFCとその重要なパラメータの説明](#3-kfcとその重要なパラメータの説明-3つのオプション共通のリファレンスガイド)を参照してください。 + +###### 2.1 問題の作成 + +スクリプトの範囲内で、指定の日の毎日の問題を作成するには、`lc`を実行します。 + +```shell +# 私の作業ディレクトリに移動する +cd my-workspace +# 毎日の問題を作成する +lc +``` + +次のプロンプトが表示されると: + +```shell +MODE: today +問題[299.猜数字游戏]を取得しました! +問題ファイルの場所:/my-workspace/299.bulls-and-cows/question.js +``` + +問題は作成されました!エディタで問題を解く準備ができました! + +###### 2.2 問題のチェック + +問題の解答コードを書き終えたら、`lk`スクリプトを使用して問題の簡単なチェックを行うことができます! + +```shell +# lkスクリプトはlcスクリプトと対応しています。パラメータなし + +の場合、今日の問題をチェックすることを意味します +lk +``` + +以下のようなメッセージが表示されます: + +```shell +MODE: today +問題[299.猜数字游戏]のテスト結果: +┌────────────┬──────────────────────────────────────────┬──────────────────────────────────────────┬────────────┬────────────┐ +│ テスト結果 │ 期待結果 │ 実行結果 │ 実行時間 │ メモリ使用量 │ +├────────────┼──────────────────────────────────────────┼──────────────────────────────────────────┼────────────┼────────────┤ +│ パス │ "1A3B" │ "1A3B" │ 0.1361ms │ 2.79 KB │ +│ パス │ "1A1B" │ "1A1B" │ 0.0623ms │ 2.93 KB │ +└────────────┴──────────────────────────────────────────┴──────────────────────────────────────────┴────────────┴────────────┘ +問題提出へのリンクをクリックしてください: https://leetcode.cn/problems/bulls-and-cows/ +``` + +`テスト結果`、`期待結果`、`実行結果`、`実行時間`、`メモリ使用量`の情報が表示されます。 + +###### 2.3 問題の検索 + +キーワード検索は、`lf`スクリプトの主要な機能の1つです。キーワードの形式で問題情報を取得し、簡単に作成できます。 + +```shell +# lfスクリプトは完全なインタラクティブなスクリプトで、プロンプトに従って入力操作を行うことで、希望する情報を簡単に取得できます +lf +``` + +以下は、`two-sum`問題をキーワードで検索して作成する方法の例です。 + +```shell +# キーワード "two sum" を入力し、Enterキーを押すと、すべての"two sum"に関連する問題が表示されます。キーボードの上下キーを使用して選択し、Enterキーを押して確認します。 +? 検索モードを選択してください? キーワード検索 +? キーワードを入力してください 二つの数 +? 問題を選んでください 1.两数之和 +1 +MODE: identity +問題[1.两数之和]を取得しました! +問題ファイルの場所:fill:///my-workspace/1.two-sum/question.js:36 +``` + +> 注意: 作成時に、クリック可能なファイルパスが表示され、エディタのコンソールでクリックすると、対応するファイルの関数の開始位置が直接開きます。 + +#### オプションB.テンプレートプロジェクト + +##### 1.テンプレートプロジェクトの作成 + +1. GitHubでテンプレートプロジェクト[leetcodePracticeTemplate](https://github.com/EternalHeartTeam/LeetcodePracticeTemplate)を開きます。 +2. 右上隅の`Use this template`をクリックし、[`Create a new repository`](https://github.com/new?template_name=LeetcodePracticeTemplate&template_owner=EternalHeartTeam)を選択します。 +3. 通常のリポジトリの作成と同様に情報を入力します。 +4. しばらく待ちます...そして完了です。これで、自分の`leetcode解答リポジトリ`ができました! + +> 作成プロセスの準備画像 + +##### 2. テンプレートプロジェクトの使用 + +###### 1. プロジェクトをクローンし、依存関係を初期化します。 + +例: 個人的なプロジェクトを使用します。 + +```shell +# これは例です。自分のプロジェクトをクローンしてください。(あなたがこれを試している時点で、このプロジェクトはもうクリアされているかもしれませんが、正常な現象なので疑わないでください) +git clone git@github.com:wh131462/my-leetcode-practice.git +# プロジェクトディレクトリに移動 +cd my-leetcode-practice +# 初期化 +npm i +``` + +###### 2. プロジェクト内での使用 + +テンプレートプロジェクトでは、`leetcode-practice`を使用する方法は2つあります。1つは`プロジェクト内コマンド`の形式、もう1つは`npmスクリプト`の形式です。詳細な使い方とパラメータについては、[KFCとその重要なパラメータの説明](#3-kfcとその重要なパラメータの説明-3つのオプション共通のリファレンスガイド)を参照してください。 + +```shell +# ルートディレクトリで実行するnpm run lc コマンドを使用して、今日の問題を作成します。デフォルトで -d src を設定しているため、src ディレクトリ内で作成されます +npm run lc +# または yarn: 好きなどちらかのパッケージ管理ツールを使用できます +yarn lc +``` + +あなたはまた、`lc`コマンドを使用して作成することもできますが、あなたはプ + +ロジェクト内でしかスクリプトを使用できません(あなたが`leetcode-practice`をグローバルにインストールしていない場合)。 + +```shell +# ここでの注意点として、プロジェクト内コマンドとは、コマンドの作用範囲が現在のプロジェクトディレクトリに限定されることを意味します。つまり、他のディレクトリで lc コマンドを試しても効果はありません。 +# 同様に、最初にインストールしたときに、プロジェクト内で lc コマンドを使用しても、そのコマンドが機能しない場合があります。この場合は、ターミナル(terminal)を閉じて再度開いて、キャッシュを手動で更新する必要があります。 +# npmスクリプトは、package.jsonのscriptsフィールドにエンベロープされたスクリプトコマンドのことです。 + +# lcコマンドを使用して作成することもできますが、その場合はプロジェクト内でしか使用できません(あなたが"leetcode-practice"をグローバルにインストールしていない場合)。 +lc +``` + +> 注意: ここで強調すると、プロジェクト内コマンドは、コマンドの作用範囲が現在のプロジェクトディレクトリに限定されることを意味します。つまり、他のディレクトリで `lc` コマンドを試しても効果はありません。同様に、最初にインストールしたときに、プロジェクト内で `lc` コマンドを使用しても、そのコマンドが機能しない場合があります。この場合は、ターミナル(terminal)を閉じてから再度開き、キャッシュを手動で更新する必要があります。npmスクリプトは、package.jsonのscriptsフィールドにエンベロープされたスクリプトコマンドのことです。 + +###### 3. 依存関係の更新 + +更新したい場合は、`update`という名前の封印されたnpmコマンドを使用して、`最新バージョン(latest)`の`leetcode-practice`をインストールできます。 + +```shell +# どちらかのパッケージ管理ツールを使用して実行できます +npm run update +# もちろん、コマンドを手動で実行することもできます +npm i -D leetcode-practice +``` + +#### オプションC.プラグイン(開発中) + +### 3. KFCとその重要なパラメータの説明 (3つのオプション共通のリファレンスガイド) + +#### [0].KFCとは? + +`KFC`は、当社の3つの主要コマンド`lk`、`lf`、`lc`を素早く覚えるための簡単な記憶法です。 + +| コマンド | 説明 | +| -------- | ------------------------------------------------------------------------------------------------------------------------- | +| lk | 主要なチェックコマンドであり、3つのモードに対応する問題のチェックを行います | +| lf | 主要な検索コマンドであり、Hot100、キーワード検索、条件検索などのモードで問題を検索し、問題を作成します | +| lc | 主要な作成コマンドであり、3つの作成モード(毎日の問題、指定された問題、ランダムな問題)をサポートし、問題の作成を行います | + +#### [1]. lk (問題のチェック) + +| 簡易パラメータ | 完全パラメータ | 説明 | +| ------------------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------ | +| 無し/`-t` | `--today` | 今日の毎日の問題をチェックします。 | +| 問題番号/`-i <identity>` | `--identity <identity>` | 指定された番号に対応する問題をチェックします。指定されたIDが現在の作業ディレクトリに存在するかどうかも確認します。 | +| `-r` | `--random` | 最後に使用されたランダムモードで作成された問題をチェックします。 | +| `-e` | `--easy` | インタラクティブにプロンプトに従って問題をチェックします。 | + +> 注意: チェックする際は、どのモードを使用するかに注意してください。対応するモードの作成操作をすでに実行したことを確認してください。 +> 指定番号モードは例外であり、作成されていない問題をチェックすることもできます。 + +#### [2]. lf (問題の検索) + +| 簡易パラメータ | 完全パラメータ | 説明 | +| -------------- | -------------- | -------------------------------------------------------------------------------------------------------- | +| 無し | 無し | インタラクティブにクエリに入り、ヒントに従って問題を検索したりフィルタリングしたりして問題を作成します。 | + +#### [3]. lc (問題の作成) + +| 簡易パラメータ | 完全パラメータ | 説明 | +| ------------------------ | ----------------------- | -------------------------------------------- | +| 無し/`-t` | `--today` | 今日の毎日の問題を作成します。 | +| 問題番号/`-i <identity>` | `--identity <identity>` | 指定された番号に対応する問題を作成します。 | +| `-r` | `--random` | まだ現れていないランダムな問題を作成します。 | +| `-e` | `--easy` | インタラクティブに問題を作成します。 | + +#### [4]. 汎用パラメータ + +| 簡易パラメータ | 完全パラメータ | 説明 | +| ---------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `-d <directory>` | `--directory <directory>` | 作業ディレクトリを指定します(現在の実行ディレクトリの相対パス)。これは作成とチェックの両方に影響を与えます。 | +| `-V` | `--version` | バージョン番号を確認します。 | +| `-v` | `--ver` | Leetcode-practice のバージョン情報と追加情報をチェックする | +| `-h` | `--help` | ヘルプ情報を取得します。 | +| `-l [language]` | `--language [language]` | パラメータなしで現在の言語環境を取得します(デフォルトはJavaScript)。言語を指定すると、その言語の環境が設定されます(たとえば、`-l java`でJavaの環境が設定されます)。 | +| `-u` | `--update` | 現在のスクリプトまたは依存関係を更新します。 | + +> 注意: 汎用パラメータは`lk`,`lf`,`lc`の3つのスクリプトでサポートされていますが、その使用法の意味論は一般的には同じですが、いくつかの指示には異なる挙動が含まれる場合があります(たとえば、`lc`コマンドで`-d`パラメータを指定した場合は、`指定したディレクトリ内で問題を作成`するのに対し、`lk`コマンドで`-d`パラメータを指定すると`指定したディレクトリに問題をチェック`します)。 + +## III. その他の情報 + +### 1. 貢献者たち + +このプロジェクトの開発と改善には、これらの貢献者のご努力が不可欠です。ここに、すべての方々に心から感謝いたします! + +<a href="https://github.com/EternalHeartTeam/leetcode-practice/graphs/contributors" target="_blank"><img src="https://raw.githubusercontent.com/EternalHeartTeam/leetcode-practice/svg/images/contributors.png" /></a> + +### 2. 貢献方法 + +もしオープンソースに対する情熱を持ち、私たちのオープンソースイニシアチブに貢献したいとお考えでしたら、[貢献ガイドライン](./.github/CONTRIBUTING.md) を参照してください。 + +### 3. 使用フィードバック + +使用上の問題がある場合や、提案がある場合は、使用フィードバックグループにご参加ください! + +グループで開発者と対面してコミュニケーションを取り、新たなアイデアを生み出すことを願っています! + + + +### 4. Starのトレンドチャート + +[](https://star-history.com/#EternalHeartTeam/leetcode-practice&Date) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..a8fff38 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,18 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| -------- | ------------------ | +| v1.0.9-x | :white_check_mark: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. diff --git a/TO-DO.md b/TO-DO.md index 8fd63b2..266360d 100644 --- a/TO-DO.md +++ b/TO-DO.md @@ -4,53 +4,53 @@ ### 优先级高 -- [ ] finder完成 - 1. 主要功能:可以对题目进行不同的筛选或者关键词搜索 - 1. 关键词搜索 - 通过关键词进行模糊搜索,通过选择列表项进行创建题目 - 2. 热门列表查看 - 查询hot100题目列表,可以通过左右按键分页查看 - 3. 筛选 - 1. 标签筛选 - 2. 难度筛选 - 3. 通过率 -- [ ] 登陆和提交到leetcode -- [ ] 提供一个类似vue-cli-serve的脚手架配置项 -- [ ] 国际化 -- [ ] 插件制作-WS/VS code -- [ ] fork脚本的编写 +- [ ] finder完成 + 1. 主要功能:可以对题目进行不同的筛选或者关键词搜索 + 1. 关键词搜索 - 通过关键词进行模糊搜索,通过选择列表项进行创建题目 + 2. 热门列表查看 - 查询hot100题目列表,可以通过左右按键分页查看 + 3. 筛选 + 1. 标签筛选 + 2. 难度筛选 + 3. 通过率 +- [ ] 登陆和提交到leetcode +- [ ] 提供一个类似vue-cli-serve的脚手架配置项 +- [ ] 国际化 +- [ ] 插件制作-WS/VS code +- [ ] fork脚本的编写 ### 优先级中 -- [ ] 获取题解和代码 -- [ ] 获取更完备的测试用例,增强用户体验 +- [ ] 获取题解和代码 +- [ ] 获取更完备的测试用例,增强用户体验 ### 优先级低 ### 代码优化及基础建设 -- [ ] e2e测试集成和仿真环境搭建 +- [ ] e2e测试集成和仿真环境搭建 ## 已完归档 -- [x] 1.模板:获取js的函数体并替换生成文件中的@function -- [x] 2.模板:从detail中获取输入用例的数据填充@Testcase -- [x] 3.模板:获取跳转每日一题的链接替换@url -- [x] 4.函数:优化时间和资源统计函数 -- [x] 5.优化创建时的体验,添加重复时候的确认覆盖或者添加额外符号 -- [x] 6.特殊数据结构的处理(链表ListNode,树TreeNode,无向连通图Node)的处理 -- [x] 7.创建某一特定编号的题目脚本,以及实现随机题目【随机题目汇集本地题目,然后排除自己本地存在的题目进行随机】 -- [x] 8.加入eslint -- [x] 9.私人项目部署的实现方案 -- [x] 10.commonJS -> ES6 Module -- [x] 11.实现在编辑器中预览图片(markdown中可以查看) -- [x] 12.使用realm进行持久化,替换store.json -- [x] 13.实现lk/lf/lc指令的封装 -- [x] 14.重构工具代码,对UI和logic进行解耦 -- [x] 15.封装npm包,方便后续做成编辑器插件 -- [x] 16.文档的编写 -- [x] 17.项目的升级检测以及升级脚本 -- [x] 18.指定编程语言代码获取 -- [x] 19.基础参数设置与缓存 -- [x] 20.添加语言的设定 -- [x] 21.store文件升级冲突引起的报错无感修复 -- [x] 22.优化随机题目的随机方式,减少请求 -- [x] 23.真随机一题实现 +- [x] 1.模板:获取js的函数体并替换生成文件中的@function +- [x] 2.模板:从detail中获取输入用例的数据填充@Testcase +- [x] 3.模板:获取跳转每日一题的链接替换@url +- [x] 4.函数:优化时间和资源统计函数 +- [x] 5.优化创建时的体验,添加重复时候的确认覆盖或者添加额外符号 +- [x] 6.特殊数据结构的处理(链表ListNode,树TreeNode,无向连通图Node)的处理 +- [x] 7.创建某一特定编号的题目脚本,以及实现随机题目【随机题目汇集本地题目,然后排除自己本地存在的题目进行随机】 +- [x] 8.加入eslint +- [x] 9.私人项目部署的实现方案 +- [x] 10.commonJS -> ES6 Module +- [x] 11.实现在编辑器中预览图片(markdown中可以查看) +- [x] 12.使用realm进行持久化,替换store.json +- [x] 13.实现lk/lf/lc指令的封装 +- [x] 14.重构工具代码,对UI和logic进行解耦 +- [x] 15.封装npm包,方便后续做成编辑器插件 +- [x] 16.文档的编写 +- [x] 17.项目的升级检测以及升级脚本 +- [x] 18.指定编程语言代码获取 +- [x] 19.基础参数设置与缓存 +- [x] 20.添加语言的设定 +- [x] 21.store文件升级冲突引起的报错无感修复 +- [x] 22.优化随机题目的随机方式,减少请求 +- [x] 23.真随机一题实现 diff --git a/bin/lc.js b/bin/lc.js index 0f8567e..0b7af6b 100755 --- a/bin/lc.js +++ b/bin/lc.js @@ -1,26 +1,22 @@ #! /usr/bin/env node -import path from 'node:path' -import { program } from 'commander' -import { artFontLogo } from '#resources/text/art-font-logo.js' -import { lcExamples } from '#resources/text/examples.js' -import { love } from '#resources/text/love.js' -import { aim } from '#resources/text/aim.js' -import { referMode } from '#common/utils/create-check/refer-mode.js' -import { getArgs } from '#common/utils/create-check/get-args.js' -import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' - -import { getQuestionRandom } from '#common/utils/question-getter/getQuestionRandom.js' - -import { easyCreateView } from '#common/view/create.view.js' -import { description } from '#resources/text/description.js' -import { easyUpdateView } from '#common/view/update.view.js' -import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' -import { easyLanguageView } from '#common/view/language.view.js' -import { DefaultVer } from '#common/constants/question.const.js' -import { - create, - createQuestionById -} from '#common/utils/create-check/createUtil.js' +import { DefaultVer } from '#common/constants/question.const.js'; +import { commonMode } from '#common/utils/cli-utils/commonMode.js'; +import { create } from '#common/utils/cli-utils/create.js'; +import { createQuestionById } from '#common/utils/cli-utils/createQuestion.js'; +import { getArgs } from '#common/utils/cli-utils/getArgs.js'; +import { referMode } from '#common/utils/cli-utils/referMode.js'; +import { logger } from '#common/utils/logger/logger.js'; +import { getAllQuestionList } from '#common/utils/question-getter/getAllQuestionList.js'; +import { getQuestionRandom } from '#common/utils/question-getter/getQuestionRandom.js'; +import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js'; +import { setAllQuestion } from '#common/utils/store/controller/allQuestion.js'; +import { easyCreateView } from '#common/view/create.view.js'; +import { aim } from '#resources/text/aim.js'; +import { artFontLogo } from '#resources/text/art-font-logo.js'; +import { description } from '#resources/text/description.js'; +import { lcExamples } from '#resources/text/examples.js'; +import { love } from '#resources/text/love.js'; +import { program } from 'commander'; const version = process.env.VERSION ?? DefaultVer program @@ -34,69 +30,41 @@ program .option('-e, --easy', 'Use easy mode.') .option('-d, --directory <directory>', 'Set the question directory.') .option('-l, --language [language]', 'Set/Get the code language of question.') - .option( - '-u, --update', - 'Check the version to determine whether to update to the latest one.' - ) + .option('-a, --all', 'Get all questions.') + .option('-v, --ver', 'Check the version info and some extra info about leetcode-practice.') + .option('-u, --update', 'Check the version to determine whether to update to the latest one.') .parse(process.argv) const cmdArgs = program.args const cmdOpts = program.opts() -/** - * 执行逻辑: - * 目录检测 - 设置基础目录 - * 模式检测 - 检测是不是easy mode - * [参数检测 - 执行对应参数] - */ -/** - * 语言设置 - * -带参设置语言 - * -无参获取语言 - */ -if (cmdOpts.language) { - if (cmdOpts.language !== true) { - await easyLanguageView(cmdOpts.language) - } else { - const lang = await getQuestionLanguage() - console.log(`当前CLI语言环境为:${lang}`) - } - process.exit(0) -} -// 根据dir 参数来设置基本目录 -const baseDir = cmdOpts.directory - ? path.join(process.cwd(), cmdOpts.directory) - : process.cwd() -if (cmdOpts.easy) { - await easyCreateView() - process.exit(0) -} -// 检测更新 -if (cmdOpts.update) { - await easyUpdateView() - process.exit(0) -} -// 创建 - +// 通用参数执行 +const baseDir = await commonMode(cmdOpts, easyCreateView) // 模式对应的action export const callModeAction = { today: () => { getQuestionToday().then((question) => { create('today', question, baseDir).then(() => { process.exit(0) - }) + }); }) - }, + }, random: () => { getQuestionRandom().then((question) => { create('random', question, baseDir).then(() => { process.exit(0) - }) + }); }) - }, + }, identity: async (id) => { await createQuestionById(id, baseDir) - process.exit(0) - } + process.exit(0) + }, + all: async () => { + const allQuestionData = await getAllQuestionList() + await setAllQuestion(allQuestionData) + logger.info('拉取全部题目成功!') + process.exit(0) + } } // 获取模式和参数 const mode = referMode(cmdArgs, cmdOpts) diff --git a/bin/lf.js b/bin/lf.js index 4828527..9de6949 100755 --- a/bin/lf.js +++ b/bin/lf.js @@ -1,56 +1,31 @@ #! /usr/bin/env node -import path from 'node:path' -import { program } from 'commander' -import { description } from '#resources/text/description.js' -import { artFontLogo } from '#resources/text/art-font-logo.js' -import { aim } from '#resources/text/aim.js' -import { lfExamples } from '#resources/text/examples.js' -import { love } from '#resources/text/love.js' -import { easyUpdateView } from '#common/view/update.view.js' -import { easyLanguageView } from '#common/view/language.view.js' -import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' -import { DefaultVer } from '#common/constants/question.const.js' -import { easyFinderView } from '#common/view/finder.view.js' +import { DefaultVer } from '#common/constants/question.const.js'; +import { commonMode } from '#common/utils/cli-utils/commonMode.js'; +import { willUse } from '#common/utils/etc/willUse.js'; +import { easyFinderView } from '#common/view/finder.view.js'; +import { aim } from '#resources/text/aim.js'; +import { artFontLogo } from '#resources/text/art-font-logo.js'; +import { description } from '#resources/text/description.js'; +import { lfExamples } from '#resources/text/examples.js'; +import { love } from '#resources/text/love.js'; +import { program } from 'commander'; const version = process.env.VERSION ?? DefaultVer program .version(version) .description(`${description}\n${artFontLogo}\n${aim}`) .addHelpText('after', lfExamples + love) - .option('-l, --language [language]', 'Set/Get the code language of question.') + .option('-e, --easy', 'Use easy mode.') .option('-d, --directory <directory>', 'Set the question directory.') - .option( - '-u, --update', - 'Check the version to determine whether to update to the latest one.' - ) + .option('-l, --language [language]', 'Set/Get the code language of question.') + .option('-v, --ver', 'Check the version info and some extra info about leetcode-practice.') + .option('-u, --update', 'Check the version to determine whether to update to the latest one.') .parse(process.argv) -// const cmdArgs = program.args +const cmdArgs = program.args const cmdOpts = program.opts() - -/** - * 语言设置 - * -带参设置语言 - * -无参获取语言 - */ -if (cmdOpts.language) { - if (cmdOpts.language !== true) { - await easyLanguageView(cmdOpts.language) - } else { - const lang = await getQuestionLanguage() - console.log(`当前CLI语言环境为:${lang}`) - } - process.exit(0) -} -// 根据dir 参数来设置基本目录 -const baseDir = cmdOpts.directory - ? path.join(process.cwd(), cmdOpts.directory) - : process.cwd() -// 检测更新 -if (cmdOpts.update) { - await easyUpdateView() - process.exit(0) -} -// 进入视图操作 +// 通用参数执行 +const baseDir = await commonMode(cmdOpts, easyFinderView) await easyFinderView(baseDir) +willUse(cmdArgs, baseDir) process.exit(0) diff --git a/bin/lk.js b/bin/lk.js index 8df5aa6..0a1a7ad 100755 --- a/bin/lk.js +++ b/bin/lk.js @@ -1,23 +1,26 @@ #! /usr/bin/env node import fs from 'node:fs' import path from 'node:path' -import { program } from 'commander' -import { artFontLogo } from '#resources/text/art-font-logo.js' -import { lkExamples } from '#resources/text/examples.js' -import { love } from '#resources/text/love.js' -import { aim } from '#resources/text/aim.js' -import { referMode } from '#common/utils/create-check/refer-mode.js' -import { getArgs } from '#common/utils/create-check/get-args.js' -import { checkQuestion } from '#common/utils/question-handler/checkQuestion.js' -import { getQuestionByMode } from '#common/utils/store/controller/question.js' -import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' -import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' +import { DefaultLang, DefaultVer } from '#common/constants/question.const.js' +import { commonMode } from '#common/utils/cli-utils/commonMode.js' +import { getArgs } from '#common/utils/cli-utils/getArgs.js' +import { referMode } from '#common/utils/cli-utils/referMode.js' +import { getFilePathById } from '#common/utils/file/getFilePathById.js' +import { getQuestionFileInDir } from '#common/utils/file/getQuestionInDir.js' +import { logger } from '#common/utils/logger/logger.js' +import { checkQuestionByPath } from '#common/utils/question-handler/checkQuestionByPath.js' import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js' +import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' +import { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.js' +import { getQuestionByMode } from '#common/utils/store/controller/question.js' import { easyCheckView } from '#common/view/check.view.js' +import { aim } from '#resources/text/aim.js' +import { artFontLogo } from '#resources/text/art-font-logo.js' import { description } from '#resources/text/description.js' -import { easyUpdateView } from '#common/view/update.view.js' -import { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.js' -import { DefaultVer } from '#common/constants/question.const.js' +import { lkExamples } from '#resources/text/examples.js' +import { love } from '#resources/text/love.js' +import select from '@inquirer/select' +import { program } from 'commander' const version = process.env.VERSION ?? DefaultVer program @@ -26,78 +29,35 @@ program .addHelpText('after', lkExamples + love) .arguments('[identity]') .option('-t, --today', 'Check the question today.') - .option( - '-i, --identity <identity>', - 'Check the specified question by identity.' - ) + .option('-i, --identity <identity>', 'Check the specified question by identity.') .option('-r, --random', 'Check the last random question.') .option('-e, --easy', 'Use easy mode.') .option('-d, --directory <directory>', 'Set the question directory.') .option('-l, --language [language]', 'Set/Get the code language of question.') - .option( - '-u, --update', - 'Check the version to determine whether to update to the latest one.' - ) + .option('-v, --ver', 'Check the version info and some extra info about leetcode-practice.') + .option('-u, --update', 'Check the version to determine whether to update to the latest one.') .parse(process.argv) const cmdArgs = program.args const cmdOpts = program.opts() // 获取模式和参数 - const mode = referMode(cmdArgs, cmdOpts) const args = getArgs(mode, cmdArgs, cmdOpts) - -/** - * 执行逻辑: - * 目录检测 - 设置基础目录 - * 模式检测 - 检测是不是easy mode - * [参数检测 - 执行对应参数] - */ -/** - * 语言设置 - * -带参设置语言 - * -无参获取语言 - */ -if (cmdOpts.language) { - if (cmdOpts.language !== true) { - await easyLanguageView(cmdOpts.language) - } else { - const lang = await getQuestionLanguage() - console.log(`当前CLI语言环境为:${lang}`) - } - process.exit(0) -} -// 根据dir 参数来设置基本目录 -const baseDir = cmdOpts.directory - ? path.join(process.cwd(), cmdOpts.directory) - : process.cwd() -if (cmdOpts.easy) { - await easyCheckView() - process.exit(0) -} -// 检测更新 -if (cmdOpts.update) { - await easyUpdateView() - process.exit(0) -} +// 通用参数执行 +const baseDir = await commonMode(cmdOpts, easyCheckView) // 检测函数 async function check(mode, question) { if (!question) { - console.log('题目信息不存在,请使用lc指令进行创建~') + logger.info('题目信息不存在,请使用lc指令进行创建~') return false } - const filePath = path.join( - baseDir, - getQuestionFileName(question), - `question${getQuestionFileExtension(question?.lang)}` - ) + const filePath = path.join(baseDir, getQuestionFileName(question), `question${getQuestionFileExtension(question?.lang)}`) if (!fs.existsSync(filePath)) { - console.log(`文件[${filePath}]不存在,请确保已经创建!`) - } else { - console.log( - `MODE: ${mode}\n题目[${getQuestionChineseName(question)}]检测结果:` - ) - await checkQuestion(filePath) + logger.info(`文件[${filePath}]不存在,请确保已经创建!`) + } + else { + logger.info(`MODE: ${mode}\n题目[${getQuestionChineseName(question)}]检查结果:`) + await checkQuestionByPath(filePath) } return true } @@ -114,13 +74,75 @@ const callModeAction = { process.exit(0) }, identity: async (id) => { - const question = !id - ? await getQuestionByMode(mode) - : await getQuestionById(id) - await check('identity', question) + let question + if (!id) { + // 如果未指定id说明是要检测模式创建的题目 + question = await getQuestionByMode(mode) + await check('identity', question) + } + else { + question = await getFilePathById(id, baseDir) + const needToSelect = { + type: 'list', + name: 'need', + message: `在当前目录下存在id为[${id}]的题目副本,请选择你要检查的副本:`, + choices: [], + } + /** + * 只检查一个题目 + * @param fileOrFiles + * @returns {Promise<void>} + */ + const checkOne = async (fileOrFiles) => { + const needToCheck = { + type: 'list', + name: 'check', + message: '当前题目目录中存在多个题目文件副本,请选择一个进行检查:', + choices: [], + default: null, + } + let filePath + switch (typeof fileOrFiles) { + case 'undefined': + logger.warn(`虽然在题目目录中,但当前目录下不存在[${id}]的题目文件!`) + process.exit(0) + break + case 'string': + filePath = fileOrFiles + break + case 'object': + needToCheck.choices = fileOrFiles.map((o) => { + return { name: o, value: o } + }) + needToCheck.default = fileOrFiles?.find(o => o.endsWith(getQuestionFileExtension(DefaultLang))) + filePath = await select(needToCheck) + break + } + return await checkQuestionByPath(filePath) + } + + let files + let which + switch (typeof question) { + case 'undefined': + logger.warn(`当前目录下未找到题目id为[${id}]的题目!`) + process.exit(0) + break + case 'string': + files = getQuestionFileInDir(path.resolve(baseDir, question)) + break + case 'object': + needToSelect.choices = question.map((o) => { + return { name: o, value: o } + }) + which = await select(needToSelect) + files = getQuestionFileInDir(path.resolve(baseDir, which)) + break + } + await checkOne(files) + } process.exit(0) - } + }, } - // 执行指令分发 callModeAction[mode](args) diff --git a/common/constants/date.const.js b/common/constants/date.const.js new file mode 100644 index 0000000..c13a6d8 --- /dev/null +++ b/common/constants/date.const.js @@ -0,0 +1,7 @@ +// 以毫秒计算的时间单位 +export const Second = 1000 +export const Minute = 60 * Second +export const Hour = 60 * Minute +export const Day = 24 * Hour +export const Week = 7 * Day +export const Year = 365 * Day diff --git a/common/constants/manager.const.js b/common/constants/manager.const.js new file mode 100644 index 0000000..8a6ace3 --- /dev/null +++ b/common/constants/manager.const.js @@ -0,0 +1,35 @@ +/** + * npm 的安装指令 + * @param packageName + * @param isUpdate + * @param isGlobal + * @returns {string} + * @constructor + */ +export function NpmInstall(packageName, isUpdate, isGlobal) { + return `npm ${isUpdate ? 'update' : 'install'} ${isGlobal ? '-g' : ''} ${packageName}` +} + +/** + * @description yarn 的安装指令 + * @param packageName + * @param isUpdate + * @param isGlobal + * @returns {string} + * @constructor + */ +export function YarnInstall(packageName, isUpdate, isGlobal) { + return `yarn ${isGlobal ? 'global' : ''} ${isUpdate ? 'upgrade' : 'add'} ${packageName}` +} + +/** + * @description pnpm 的安装指令 + * @param packageName + * @param isUpdate + * @param isGlobal + * @returns {string} + * @constructor + */ +export function PnpmInstall(packageName, isUpdate, isGlobal) { + return `pnpm ${isGlobal ? 'global' : ''} ${isUpdate ? 'update' : 'install'} ${packageName}` +} diff --git a/common/constants/question.const.js b/common/constants/question.const.js index c630e5a..5a07681 100644 --- a/common/constants/question.const.js +++ b/common/constants/question.const.js @@ -10,7 +10,10 @@ export const GITHUB_HOST = 'EternalHeartTeam' // endregion // region 域名列表 // npm 主域名 -export const NPM_URL = 'https://registry.npmjs.org/' +export const NPM_URL = 'https://npmjs.org/' +// npm 仓库域名 +export const NPM_REGISTRY_URL = 'https://registry.npmjs.org/' + // github raw 主域名 export const GITHUB_RAW = 'https://raw.githubusercontent.com/' // github diff --git a/common/origin/checkUpdate.js b/common/origin/checkUpdate.js new file mode 100644 index 0000000..16cb7ad --- /dev/null +++ b/common/origin/checkUpdate.js @@ -0,0 +1,22 @@ +import { Day } from '#common/constants/date.const.js' +import { NpmInstall, PnpmInstall, YarnInstall } from '#common/constants/manager.const.js' +import { PackageName } from '#common/constants/question.const.js' +import { logger } from '#common/utils/logger/logger.js' +import { getStore, setStore } from '#common/utils/store/controller/store.js' +import { checkUpdate } from '#common/utils/update/update.js' + +const { timestamp = 0, hasShow = false } = (await getStore('checkResult')) ?? {} +if (Date.now() - timestamp <= Day || hasShow) + process.exit(0) + +const { localVersion, npmVersion, isCliUpdate } = await checkUpdate() +const needShow = false +if (isCliUpdate) { + const installInfo = [NpmInstall, YarnInstall, PnpmInstall] + .map(fun => fun(PackageName, true, true)) // 暂时先默认为全局 + .join('\n') + logger.warn(`[leetcode-practice] 检测到新版本[ ${npmVersion} ]已经发布! 您当前的版本为[ ${localVersion} ]! 您可以执行对应的指令进行手动更新~`) + logger.info(`${installInfo}`) +} +await setStore('checkResult', { timestamp: Date.now(), hasShow: needShow }) +process.exit(0) diff --git a/common/origin/readme.md b/common/origin/readme.md new file mode 100644 index 0000000..78ea2bf --- /dev/null +++ b/common/origin/readme.md @@ -0,0 +1,5 @@ +# Origin + +> 吮指原味鸡~ +> +> 在这个目录中的都会按目录输出. diff --git a/common/structures/ListNode.js b/common/structures/ListNode.js index bd57e2d..0d236d0 100644 --- a/common/structures/ListNode.js +++ b/common/structures/ListNode.js @@ -12,7 +12,8 @@ export class ListNode { } static parse(arr) { - if (arr.length === 0) return null // Return null for an empty array + if (arr.length === 0) + return null // Return null for an empty array const head = new ListNode(arr.shift(), null) let current = head @@ -24,7 +25,8 @@ export class ListNode { } static toArray(listNodes, arr = []) { - if (listNodes === undefined || listNodes === null) return arr + if (listNodes === undefined || listNodes === null) + return arr arr.push(listNodes.val) return ListNode.toArray(listNodes.next, arr) diff --git a/common/structures/Node.js b/common/structures/Node.js index 071020c..f453afa 100644 --- a/common/structures/Node.js +++ b/common/structures/Node.js @@ -30,13 +30,15 @@ export class Node { } static toArray(node) { - if (!node) return [] + if (!node) + return [] const visited = new Set() const result = [] const dfs = (currentNode) => { - if (visited.has(currentNode.val)) return + if (visited.has(currentNode.val)) + return const { neighbors, val } = currentNode visited.add(val) diff --git a/common/structures/TreeNode.js b/common/structures/TreeNode.js index 90c4146..11be2f1 100644 --- a/common/structures/TreeNode.js +++ b/common/structures/TreeNode.js @@ -7,7 +7,8 @@ export class TreeNode { } static parse(arr) { - if (arr.length === 0) return null + if (arr.length === 0) + return null const root = new TreeNode(arr[0]) const queue = [root] for (let i = 1; i < arr.length; i += 2) { @@ -26,7 +27,8 @@ export class TreeNode { static toArray(treeNode) { const result = [] - if (!treeNode) return result + if (!treeNode) + return result const queue = [treeNode] @@ -36,7 +38,8 @@ export class TreeNode { result.push(node.val) queue.push(node.left) queue.push(node.right) - } else { + } + else { result.push(null) } } diff --git a/common/utils/cli-utils/commonMode.js b/common/utils/cli-utils/commonMode.js new file mode 100644 index 0000000..a6fa158 --- /dev/null +++ b/common/utils/cli-utils/commonMode.js @@ -0,0 +1,65 @@ +import { fork } from 'node:child_process' +import path from 'node:path' +import { currentEnv } from '#common/utils/etc/checkEnv.js' +import { checkVisionInfo } from '#common/utils/etc/checkVisionInfo.js' +import { rootPath } from '#common/utils/file/getRootPath.js' +import { logger } from '#common/utils/logger/logger.js' +import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' +import { easyLanguageView } from '#common/view/language.view.js' +import { easyUpdateView } from '#common/view/update.view.js' + +/** + * 执行逻辑: + * 目录检测 - 设置基础目录 + * 模式检测 - 检测是不是easy mode + * [参数检测 - 执行对应参数] + */ +/** + * 通用参数的执行逻辑 + * @param cmdOpts {{directory:string,language:string|boolean,easy:boolean,update:boolean,[key:string]:*}} + * @param easyCallback {(baseDir:string)=>Promise<any>} + * @returns {Promise<string>} + */ +export async function commonMode(cmdOpts, easyCallback) { + // 启动一个额外的线程,并执行 worker.js 文件 + // const workerProcess = + const jsPath = path.resolve(rootPath, currentEnv() === 'cli' ? 'origin/checkUpdate.js' : 'common/origin/checkUpdate.js') + fork(jsPath) + // todo 监听额外线程的消息 + // workerProcess.on('message', (message) => {}) + // todo 监听额外线程的退出事件 + // workerProcess.on('exit', (code, signal) => {}) + + // 根据dir 参数来设置基本目录 + const baseDir = cmdOpts.directory ? path.join(process.cwd(), cmdOpts.directory) : process.cwd() + /** + * 语言设置 + * -带参设置语言 + * -无参获取语言 + */ + if (cmdOpts.language) { + if (cmdOpts.language !== true) { + await easyLanguageView(cmdOpts.language) + } + else { + const lang = await getQuestionLanguage() + logger.info(`当前CLI语言环境为:${lang}`) + } + process.exit(0) + } + // 简单模式 + if (cmdOpts.easy) { + await easyCallback(baseDir) + process.exit(0) + } + if (cmdOpts.ver) { + await checkVisionInfo() + process.exit(0) + } + // 检测更新 + if (cmdOpts.update) { + await easyUpdateView() + process.exit(0) + } + return baseDir +} diff --git a/common/utils/create-check/createUtil.js b/common/utils/cli-utils/create.js similarity index 51% rename from common/utils/create-check/createUtil.js rename to common/utils/cli-utils/create.js index 3322dd6..2677f37 100644 --- a/common/utils/create-check/createUtil.js +++ b/common/utils/cli-utils/create.js @@ -1,39 +1,30 @@ import path from 'node:path' +import { getLineNumberByContent } from '#common/utils/file/getLineNumberByContent.js' +import { logger } from '#common/utils/logger/logger.js' import { createQuestion } from '#common/utils/question-handler/createQuestion.js' -import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' import { createQuestionCopy } from '#common/utils/question-handler/createQuestionCopy.js' -import { setQuestion } from '#common/utils/store/controller/question.js' import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js' -import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' -import { getQuestionIdBySlug } from '#common/utils/question-handler/getQuestionIdBySlug.js' -import { getLineNumberByContent } from '#common/utils/file/getLineNumberByContent.js' +import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' +import { setQuestion } from '#common/utils/store/controller/question.js' +/** + * 创建函数 + * @param mode + * @param question + * @param baseDir + * @returns {Promise<unknown>} + */ export function create(mode, question, baseDir) { - console.log(`MODE: ${mode}`) + logger.info(`MODE: ${mode}`) return new Promise((resolve) => { setQuestion(mode, question) const questionDir = path.join(baseDir, getQuestionFileName(question)) createQuestion(question, questionDir).then(async (path) => { - if (!path) path = await createQuestionCopy(question, questionDir) + if (!path) + path = await createQuestionCopy(question, questionDir) const line = (await getLineNumberByContent(path, '@QUESTION_START')) + 1 - console.log( - `题目[${getQuestionChineseName(question)}]获取成功!\n题目文件地址为:file://${path}:${line}` - ) + logger.info(`题目[${getQuestionChineseName(question)}]获取成功!\n题目文件地址为:file://${path}:${line}`) resolve(true) }) }) } - -export async function createQuestionByTitleSlug( - titleSlug, - baseDir = process.cwd() -) { - const { question } = await getQuestionIdBySlug(titleSlug) - - await createQuestionById(question.questionId, baseDir) -} -export async function createQuestionById(id, baseDir = process.cwd()) { - const question = await getQuestionById(id) - if (!question?.id) console.log(`指定编号: [ ${id} ] 题目不存在.`) - await create('identity', question, baseDir) -} diff --git a/common/utils/cli-utils/createQuestion.js b/common/utils/cli-utils/createQuestion.js new file mode 100644 index 0000000..f94c8f5 --- /dev/null +++ b/common/utils/cli-utils/createQuestion.js @@ -0,0 +1,28 @@ +import { create } from '#common/utils/cli-utils/create.js' +import { logger } from '#common/utils/logger/logger.js' +import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' +import { getQuestionIdBySlug } from '#common/utils/question-handler/getQuestionIdBySlug.js' + +/** + * 通过指定的titleSlug创建题目 + * @param titleSlug + * @param baseDir + * @returns {Promise<void>} + */ +export async function createQuestionByTitleSlug(titleSlug, baseDir = process.cwd()) { + const { question } = await getQuestionIdBySlug(titleSlug) + await createQuestionById(question.questionId, baseDir) +} + +/** + * 通过id创建题目 + * @param id + * @param baseDir + * @returns {Promise<void>} + */ +export async function createQuestionById(id, baseDir = process.cwd()) { + const question = await getQuestionById(id) + if (!question?.id) + logger.warn(`指定编号: [ ${id} ] 题目不存在.`) + await create('identity', question, baseDir) +} diff --git a/common/utils/create-check/get-args.js b/common/utils/cli-utils/getArgs.js similarity index 100% rename from common/utils/create-check/get-args.js rename to common/utils/cli-utils/getArgs.js diff --git a/common/utils/cli-utils/referMode.js b/common/utils/cli-utils/referMode.js new file mode 100644 index 0000000..50fcbe7 --- /dev/null +++ b/common/utils/cli-utils/referMode.js @@ -0,0 +1,13 @@ +// 推测模式 +export function referMode(args, opts) { + if (args.length > 0 || opts.identity) + return 'identity' + + if (opts.random) + return 'random' + + if (opts.all) + return 'all' + + return 'today' +} diff --git a/common/utils/create-check/refer-mode.js b/common/utils/create-check/refer-mode.js deleted file mode 100644 index 42ff1f8..0000000 --- a/common/utils/create-check/refer-mode.js +++ /dev/null @@ -1,8 +0,0 @@ -// 推测模式 -export function referMode(args, opts) { - if (args.length > 0 || opts.identity) return 'identity' - - if (opts.random) return 'random' - - return 'today' -} diff --git a/common/utils/etc/checkEnv.js b/common/utils/etc/checkEnv.js index f5740f7..fce4e63 100644 --- a/common/utils/etc/checkEnv.js +++ b/common/utils/etc/checkEnv.js @@ -9,3 +9,10 @@ export function currentEnv() { const projectReg = /etc\/checkEnv.js$/im return projectReg.test(url) ? 'project' : 'cli' } + +/** + * 检查npm安装时的位置 + */ +export function npmEnv() { + return true ? 'global' : 'module' +} diff --git a/common/utils/etc/checkVisionInfo.js b/common/utils/etc/checkVisionInfo.js new file mode 100644 index 0000000..1261348 --- /dev/null +++ b/common/utils/etc/checkVisionInfo.js @@ -0,0 +1,16 @@ +import { DefaultVer, GITHUB_HOST, GITHUB_URL, NPM_URL, PackageName } from '#common/constants/question.const.js' +import { rootPath } from '#common/utils/file/getRootPath.js' +import { url_join } from '#common/utils/http/urlJoin.js' +import { logger } from '#common/utils/logger/logger.js' +import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' +import { aim } from '#resources/text/aim.js' + +/** + * 检查版本信息 加一些额外输出 + */ +export async function checkVisionInfo() { + const version = process.env.VERSION ?? DefaultVer + const location = rootPath + const lang = await getQuestionLanguage() + logger.info(`version: ${version}\nlanguage: ${lang}\nlocation: file://${location}\ngithub: ${url_join(GITHUB_URL, GITHUB_HOST, PackageName)}\nnpm: ${url_join(NPM_URL, 'package', PackageName)}\n\n${aim}`) +} diff --git a/common/utils/etc/createColorFont.js b/common/utils/etc/createColorFont.js index cd5eb60..751ca34 100644 --- a/common/utils/etc/createColorFont.js +++ b/common/utils/etc/createColorFont.js @@ -7,11 +7,9 @@ export function createColorFont(font) { const code = gradient_string([ { color: '#ff0000', pos: 0 }, { color: '#ffc600', pos: 0.5 }, - { color: '#003dff', pos: 1 } + { color: '#003dff', pos: 1 }, ])(font) writeFileSync(path.resolve(process.cwd(), 'colorFont.js'), code) - console.log( - `[ColorFont]Create color font: ${font}\ncode location:${path.resolve(process.cwd(), 'colorFont.js')}` - ) + console.log(`[ColorFont]Create color font: ${font}\ncode location:${path.resolve(process.cwd(), 'colorFont.js')}`) console.log(code) } diff --git a/common/utils/etc/open.js b/common/utils/etc/open.js index 8c0e991..6350a92 100644 --- a/common/utils/etc/open.js +++ b/common/utils/etc/open.js @@ -1,5 +1,6 @@ -import os from 'node:os' import { exec } from 'node:child_process' +import os from 'node:os' +import { logger } from '#common/utils/logger/logger.js' const platform = os.platform() @@ -19,7 +20,7 @@ export function open(url) { exec(`xdg-open "${url}"`) break default: - console.log(`Unsupported platform: ${platform}`) + logger.info(`Unsupported platform: ${platform}`) break } } diff --git a/common/utils/etc/typeof_.js b/common/utils/etc/typeof_.js index 8d8458a..914278b 100644 --- a/common/utils/etc/typeof_.js +++ b/common/utils/etc/typeof_.js @@ -5,6 +5,7 @@ * @private */ export function typeof_(data) { - if (data === null) return 'null' + if (data === null) + return 'null' else return typeof data } diff --git a/common/utils/etc/willUse.js b/common/utils/etc/willUse.js new file mode 100644 index 0000000..21d4ddb --- /dev/null +++ b/common/utils/etc/willUse.js @@ -0,0 +1,8 @@ +/** + * 无用之用:标记可能会用的变量 + * @returns {*} + * @param args + */ +export function willUse(...args) { + return args +} diff --git a/common/utils/file/getCountBySameName.js b/common/utils/file/getCountBySameName.js index 7966377..71d94e9 100644 --- a/common/utils/file/getCountBySameName.js +++ b/common/utils/file/getCountBySameName.js @@ -7,5 +7,5 @@ import { readdirSync } from 'node:fs' * @returns {number} */ export function getCountBySameName(dir, name) { - return readdirSync(dir).filter((filename) => filename.includes(name)).length + return readdirSync(dir).filter(filename => filename.includes(name)).length } diff --git a/common/utils/file/getDirname.js b/common/utils/file/getDirname.js index 22ec495..b12de7d 100644 --- a/common/utils/file/getDirname.js +++ b/common/utils/file/getDirname.js @@ -1,5 +1,5 @@ -import { fileURLToPath } from 'node:url' import { dirname } from 'node:path' +import { fileURLToPath } from 'node:url' const __filename = fileURLToPath(import.meta.url) export const __dirname = dirname(__filename) diff --git a/common/utils/file/getFileListBySameName.js b/common/utils/file/getFileListBySameName.js index e0cbcb0..b8c66b1 100644 --- a/common/utils/file/getFileListBySameName.js +++ b/common/utils/file/getFileListBySameName.js @@ -1,5 +1,5 @@ import { readdirSync } from 'node:fs' export function getFileListBySameName(dir, name) { - return readdirSync(dir).filter((filename) => filename.includes(name)) + return readdirSync(dir).filter(filename => filename.includes(name)) } diff --git a/common/utils/file/getFilePathById.js b/common/utils/file/getFilePathById.js index a54e68a..dbaa569 100644 --- a/common/utils/file/getFilePathById.js +++ b/common/utils/file/getFilePathById.js @@ -8,7 +8,8 @@ import fs from 'node:fs' */ export function getFilePathById(id, baseDir = process.cwd()) { const dir = fs.readdirSync(baseDir) - const files = dir.filter((o) => o.startsWith(`${id}.`)) - if (files.length > 1) return files + const files = dir.filter(o => o.startsWith(`${id}.`)) + if (files.length > 1) + return files return files?.[0] } diff --git a/common/utils/file/getLineNumberByContent.js b/common/utils/file/getLineNumberByContent.js index 06ea9ce..8565fd8 100644 --- a/common/utils/file/getLineNumberByContent.js +++ b/common/utils/file/getLineNumberByContent.js @@ -1,4 +1,5 @@ import fs from 'node:fs' +import { logger } from '#common/utils/logger/logger.js' /** * 通过给入的文件地址和内容 给出对应的行号 @@ -24,12 +25,12 @@ export function getLineNumberByContent(filePath, searchString) { }) readStream.on('end', () => { - console.warn(`"${searchString}" not found in file: ${filePath}`) + logger.warn(`[WARN] "${searchString}" not found in file: ${filePath}`) resolve(0) }) readStream.on('error', () => { - console.warn(`"${searchString}" not found in file: ${filePath}`) + logger.warn(`[WARN] "${searchString}" not found in file: ${filePath}`) resolve(0) }) }) diff --git a/common/utils/file/getQuestionInDir.js b/common/utils/file/getQuestionInDir.js new file mode 100644 index 0000000..f22db49 --- /dev/null +++ b/common/utils/file/getQuestionInDir.js @@ -0,0 +1,13 @@ +import fs from 'node:fs' +import path from 'node:path' + +/** + * 在目录中查找题目文件 + * @param dir + * @returns {string|string[]} + */ +export function getQuestionFileInDir(dir) { + const list = fs.readdirSync(dir) + const questionLikes = list.filter(name => name.startsWith('question')).map(file => path.resolve(dir, file)) + return questionLikes?.length === 1 ? questionLikes[0] : questionLikes +} diff --git a/common/utils/file/getRootPath.js b/common/utils/file/getRootPath.js index 0971a80..9c2a535 100644 --- a/common/utils/file/getRootPath.js +++ b/common/utils/file/getRootPath.js @@ -1,9 +1,6 @@ import path from 'node:path' -import { __dirname } from '#common/utils/file/getDirname.js' import { currentEnv } from '#common/utils/etc/checkEnv.js' +import { __dirname } from '#common/utils/file/getDirname.js' // 在cli环境下 执行目录为 bin 目录 根目录就是上一层目录 -export const rootPath = - currentEnv() === 'project' - ? path.dirname(path.dirname(path.dirname(__dirname))) - : path.dirname(__dirname) +export const rootPath = currentEnv() === 'project' ? path.dirname(path.dirname(path.dirname(__dirname))) : path.dirname(__dirname) diff --git a/common/utils/functions/isSameData.js b/common/utils/functions/isSameData.js index b313fc6..ae2b78d 100644 --- a/common/utils/functions/isSameData.js +++ b/common/utils/functions/isSameData.js @@ -7,7 +7,8 @@ export function isSameData(a, b) { const typeA = typeof a const typeB = typeof b - if (typeA !== typeB) return false + if (typeA !== typeB) + return false switch (typeA) { case 'bigint': case 'boolean': @@ -19,12 +20,14 @@ export function isSameData(a, b) { case 'function': return a.toString() === b.toString() case 'object': { - if (a === null || a === undefined) return a === b + if (a === null || a === undefined) + return a === b const keysA = Object.keys(a) const keysB = Object.keys(b) - if (keysA.length !== keysB.length) return false - return keysA.every((key) => isSameData(a[key], b[key])) + if (keysA.length !== keysB.length) + return false + return keysA.every(key => isSameData(a[key], b[key])) } } } diff --git a/common/utils/functions/removeDomTags.js b/common/utils/functions/removeDomTags.js index 0f38b86..1668109 100644 --- a/common/utils/functions/removeDomTags.js +++ b/common/utils/functions/removeDomTags.js @@ -5,7 +5,7 @@ */ export function removeDomTags(input) { return input - .replace(/<[^>]*>/g, '') + ?.replace(/<[^>]*>/g, '') .replaceAll(' ', ' ') .replaceAll(' ', ' ') .replaceAll('<', '<') diff --git a/common/utils/functions/sizeUtil.js b/common/utils/functions/sizeUtil.js index 72de534..b7867a8 100644 --- a/common/utils/functions/sizeUtil.js +++ b/common/utils/functions/sizeUtil.js @@ -15,11 +15,16 @@ export const PB = 1024 * GB * @return {size: number, label: string} */ export function getFileSizeUnit(size) { - if (size < KB) return { size: 1, label: 'B' } - if (size < MB) return { size: KB, label: 'KB' } - if (size < GB) return { size: MB, label: 'MB' } - if (size < TB) return { size: GB, label: 'GB' } - if (size < PB) return { size: TB, label: 'TB' } + if (size < KB) + return { size: 1, label: 'B' } + if (size < MB) + return { size: KB, label: 'KB' } + if (size < GB) + return { size: MB, label: 'MB' } + if (size < TB) + return { size: GB, label: 'GB' } + if (size < PB) + return { size: TB, label: 'TB' } return { size: PB, label: 'PB' } } diff --git a/common/utils/http/fetch_.js b/common/utils/http/fetch_.js index 0e6f65b..a80d377 100644 --- a/common/utils/http/fetch_.js +++ b/common/utils/http/fetch_.js @@ -1,10 +1,15 @@ +import ora from 'ora' + /** * 基础请求-直接返回JSON格式的值 * @param url - * @param options + * @param options {RequestInit&{loadText?:string}} * @returns {Promise<any>} * @private */ export async function fetch_(url, options) { - return await fetch(url, options).then((res) => res.json()) + const loader = ora(options.loadText ?? 'loading...').start() + const resp = await fetch(url, options).then(res => res.json()) + loader.stop() + return resp } diff --git a/common/utils/http/urlJoin.js b/common/utils/http/urlJoin.js index 0d7ca09..ac0f170 100644 --- a/common/utils/http/urlJoin.js +++ b/common/utils/http/urlJoin.js @@ -8,7 +8,7 @@ export function url_join(host, ...rest) { const host_base = host.replace(/\/$/, '') const path = rest .join('/') - .replace(/(\/){1,3}/gim, '/') + .replace(/(\/){1,3}/g, '/') .replace(/^\//, '') return [host_base, path].join('/') } diff --git a/common/utils/loading/loading.js b/common/utils/loading/loading.js new file mode 100644 index 0000000..6cca644 --- /dev/null +++ b/common/utils/loading/loading.js @@ -0,0 +1,36 @@ +import chalk from 'chalk' + +export class Loading { + text = 'loading...' + constructor(text) { + this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] + this.currentFrame = 0 + this.interval = null + this.text = text + } + + start() { + if (this.interval) + clearInterval(this.interval) + this.interval = setInterval(() => { + process.stdout.write(chalk.blueBright(`\r${this.frames[this.currentFrame]} ${this.text}`)) + + this.currentFrame++ + if (this.currentFrame === this.frames.length) + this.currentFrame = 0 + }, 80) + return this + } + + stop() { + clearInterval(this.interval) + process.stdout.write('\r') // 清除动画最后一帧 + return this + } + + // 在发生异常时调用此方法清除动画 + handleException() { + this.stop() + return this + } +} diff --git a/common/utils/logger/logger.js b/common/utils/logger/logger.js new file mode 100644 index 0000000..94bfd86 --- /dev/null +++ b/common/utils/logger/logger.js @@ -0,0 +1,64 @@ +import { getStore } from '#common/utils/store/controller/store.js' +import chalk from 'chalk' + +class LOGGER { + isOn = true + constructor(_env) { + // console.log( + // chalk.bgGray(`[logger init] The current env is ${env ?? 'not plugin'}.`) + // ) + } + + /** + * 开启 + */ + on() { + this.isOn = true + } + + /** + * 关闭 + */ + off() { + this.isOn = false + } + + get forbidden() { + return !this.isOn + } + + /** + * 普通消息 + * @param message{*} + * @param args{*[]} + */ + info(message, ...args) { + if (this.forbidden) + return + console.log(chalk.whiteBright(message, ...args)) + } + + /** + * 警告 + * @param message{*} + * @param args{*[]} + */ + warn(message, ...args) { + if (this.forbidden) + return + console.log(chalk.yellowBright(message, ...args)) + } + + /** + * 错误信息 + * @param message{*} + * @param args{*[]} + */ + error(message, ...args) { + if (this.forbidden) + return + console.log(chalk.redBright(message, ...args)) + } +} +const { env = null } = (await getStore('config')) ?? {} +export const logger = new LOGGER(env) diff --git a/common/utils/question-getter/getAllQuestionList.js b/common/utils/question-getter/getAllQuestionList.js new file mode 100644 index 0000000..ad7beff --- /dev/null +++ b/common/utils/question-getter/getAllQuestionList.js @@ -0,0 +1,22 @@ +import { graphql } from '#common/utils/http/graphql.js' +import { getAllQuestionRequestUrlJson } from '#resources/headers/allQuestionRequestUrlJson.js' +import ora from 'ora' + +export async function getAllQuestionUrl() { + const { data } = await graphql(getAllQuestionRequestUrlJson()) + const { allQuestionUrls } = data + const { questionUrl } = allQuestionUrls + return questionUrl +} + +export async function getAllQuestionList() { + const url = await getAllQuestionUrl() + const loader = ora('loading...').start() + const allQuestionData = await fetch(url, { + headers: { 'content-type': 'application/json' }, + body: null, + method: 'GET', + }) + loader.stop() + return allQuestionData.json() +} diff --git a/common/utils/question-getter/getPlanQuestionList.js b/common/utils/question-getter/getPlanQuestionList.js new file mode 100644 index 0000000..784183d --- /dev/null +++ b/common/utils/question-getter/getPlanQuestionList.js @@ -0,0 +1,10 @@ +import { graphql } from '#common/utils/http/graphql.js' +import { getPlanQuestionListJson } from '#resources/headers/planQuestionListJson.js' + +export async function getPlanQuestionList(slug) { + const res = await graphql(getPlanQuestionListJson(slug)) + const { + data: { studyPlanV2Detail }, + } = res + return studyPlanV2Detail +} diff --git a/common/utils/question-getter/getQuestionById.js b/common/utils/question-getter/getQuestionById.js index 4331553..faa82c6 100644 --- a/common/utils/question-getter/getQuestionById.js +++ b/common/utils/question-getter/getQuestionById.js @@ -1,15 +1,13 @@ -import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' -import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js' import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js' +import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' export async function getQuestionById(id) { const base = await graphql(getQuestionSearchJson(id.toString())) - const questionContent = base?.data?.problemsetQuestionList?.questions?.find( - (o) => o?.frontendQuestionId === id.toString() - ) + const questionContent = base?.data?.problemsetQuestionList?.questions?.find(o => o?.frontendQuestionId === id.toString()) if (!questionContent) { return { - id: null + id: null, } } const slug = questionContent.titleSlug diff --git a/common/utils/question-getter/getQuestionList.js b/common/utils/question-getter/getQuestionList.js index 66df191..55cbd35 100644 --- a/common/utils/question-getter/getQuestionList.js +++ b/common/utils/question-getter/getQuestionList.js @@ -1,5 +1,5 @@ -import { getQuestionListJson } from '#resources/headers/questionListJson.js' import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionListJson } from '#resources/headers/questionListJson.js' export async function getQuestionList() { const base = await graphql(getQuestionListJson()) diff --git a/common/utils/question-getter/getQuestionListHot100.js b/common/utils/question-getter/getQuestionListHot100.js deleted file mode 100644 index 2c1f32b..0000000 --- a/common/utils/question-getter/getQuestionListHot100.js +++ /dev/null @@ -1,10 +0,0 @@ -import { graphql } from '#common/utils/http/graphql.js' -import { getQuestionListHot100Json } from '#resources/headers/questionListHot100Json.js' - -export async function getQuestionListHot100() { - const res = await graphql(getQuestionListHot100Json()) - const { - data: { studyPlanV2Detail } - } = res - return studyPlanV2Detail -} diff --git a/common/utils/question-getter/getQuestionRandom.js b/common/utils/question-getter/getQuestionRandom.js index a06154c..7c18c9f 100644 --- a/common/utils/question-getter/getQuestionRandom.js +++ b/common/utils/question-getter/getQuestionRandom.js @@ -1,14 +1,12 @@ -import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' -import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js' -import { getRandomId } from '#common/utils/question-handler/getRandomId.js' import { graphql } from '#common/utils/http/graphql.js' +import { getRandomId } from '#common/utils/question-handler/getRandomId.js' +import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js' +import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' export async function getQuestionRandom() { const id = await getRandomId() const base = await graphql(getQuestionSearchJson(id.toString())) - const slug = base.data.problemsetQuestionList.questions.find( - (o) => o.frontendQuestionId === id.toString() - ).titleSlug + const slug = base.data.problemsetQuestionList.questions.find(o => o.frontendQuestionId === id.toString()).titleSlug const question = await getQuestionDetail(slug) return question } diff --git a/common/utils/question-getter/getQuestionTagType.js b/common/utils/question-getter/getQuestionTagType.js new file mode 100644 index 0000000..55a6f88 --- /dev/null +++ b/common/utils/question-getter/getQuestionTagType.js @@ -0,0 +1,8 @@ +import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionTagTypeJson } from '#resources/headers/questionTagTypeJson.js' + +export async function getQuestionTagType() { + const { data } = await graphql(getQuestionTagTypeJson()) + const { questionTagTypeWithTags } = data + return questionTagTypeWithTags +} diff --git a/common/utils/question-getter/getQuestionToday.js b/common/utils/question-getter/getQuestionToday.js index 10dfcfb..442815f 100644 --- a/common/utils/question-getter/getQuestionToday.js +++ b/common/utils/question-getter/getQuestionToday.js @@ -1,6 +1,6 @@ -import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' -import { getQuestionTodayJson } from '#resources/headers/questionTodayJson.js' import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionTodayJson } from '#resources/headers/questionTodayJson.js' +import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' export async function getQuestionToday() { const question = await graphql(getQuestionTodayJson()) diff --git a/common/utils/question-getter/getQuestionTypes.js b/common/utils/question-getter/getQuestionTypes.js index 8db5e3a..4ba90e5 100644 --- a/common/utils/question-getter/getQuestionTypes.js +++ b/common/utils/question-getter/getQuestionTypes.js @@ -1,5 +1,5 @@ -import { getQuestionTypesJson } from '#resources/headers/questionTypeJson.js' import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionTypesJson } from '#resources/headers/questionTypeJson.js' /** * 获取问题的类型 @@ -25,6 +25,6 @@ import { graphql } from '#common/utils/http/graphql.js' export async function getQuestionTypes() { const res = await graphql(getQuestionTypesJson()) const tags = res.data?.questionTagTypeWithTags - // console.log(JSON.stringify(tags)) + // logger.info(JSON.stringify(tags)) return tags } diff --git a/common/utils/question-getter/getStudyPlanList.js b/common/utils/question-getter/getStudyPlanList.js new file mode 100644 index 0000000..c7de5aa --- /dev/null +++ b/common/utils/question-getter/getStudyPlanList.js @@ -0,0 +1,12 @@ +import { graphql } from '#common/utils/http/graphql.js' +import { getStudyPlanListJson } from '#resources/headers/studyPlanListJson.js' + +export async function getStudyPlanList(type) { + const res = await graphql(getStudyPlanListJson(type)) + const { + data: { + studyPlansV2ByCatalog: { studyPlans }, + }, + } = res + return studyPlans +} diff --git a/common/utils/question-handler/checkQuestion.js b/common/utils/question-handler/checkQuestionByPath.js similarity index 88% rename from common/utils/question-handler/checkQuestion.js rename to common/utils/question-handler/checkQuestionByPath.js index 43f5393..cc27a49 100644 --- a/common/utils/question-handler/checkQuestion.js +++ b/common/utils/question-handler/checkQuestionByPath.js @@ -18,12 +18,12 @@ export function executeScript(filePath, context) { * 执行问题检测进程 * @param path */ -export async function checkQuestion(path) { +export async function checkQuestionByPath(path) { return await executeScript( path, vm.createContext({ showLogs, - console - }) + console, + }), ) } diff --git a/common/utils/question-handler/code.js b/common/utils/question-handler/code.js index 04469a8..2ee3ad4 100644 --- a/common/utils/question-handler/code.js +++ b/common/utils/question-handler/code.js @@ -1,10 +1,7 @@ import fs from 'node:fs' -import { getQuestionCodeList } from '#common/utils/question-getter/getQuestionCodeList.js' -import { - getLangByExtension, - setLineComment -} from '#common/utils/question-handler/questionLanguage.js' import { DefaultLang } from '#common/constants/question.const.js' +import { getQuestionCodeList } from '#common/utils/question-getter/getQuestionCodeList.js' +import { getLangByExtension, setLineComment } from '#common/utils/question-handler/questionLanguage.js' /** * 获取代码 @@ -14,7 +11,7 @@ import { DefaultLang } from '#common/constants/question.const.js' */ export async function getCodeBySlug(slug, lang) { const list = await getQuestionCodeList(slug) - return list.find((o) => o.langSlug === lang)?.code + return list?.find(o => o.langSlug === lang)?.code } /** * 获取支持的代码语言 @@ -22,8 +19,8 @@ export async function getCodeBySlug(slug, lang) { * @returns {Promise<string[]>} */ export async function getSupportCode(slug) { - const list = await getQuestionCodeList(slug) - return list.map((code) => code?.langSlug) + const list = (await getQuestionCodeList(slug)) ?? [] + return list?.map(code => code?.langSlug) } /** @@ -33,16 +30,9 @@ export async function getSupportCode(slug) { * @returns {*|string} */ export function getCodeRange(lang, code) { - if (!code) { - return setLineComment( - lang, - `!important: 此题目没有当前语言[${lang}]的代码模板!` - ) - } - return `${setLineComment(lang, '@QUESTION_START') + code}\n${setLineComment( - lang, - '@QUESTION_END' - )}` + if (!code) + return setLineComment(lang, `!important: 此题目没有当前语言[${lang}]的代码模板!`) + return `${setLineComment(lang, '@QUESTION_START') + code}\n${setLineComment(lang, '@QUESTION_END')}` } /** * 获取文件中的代码部分 @@ -53,8 +43,9 @@ export function getCodeInFile(filePath) { const startTag = setLineComment(lang, '@QUESTION_START') const endTag = setLineComment(lang, '@QUESTION_END') const rangeReg = new RegExp(`${startTag}.*${endTag}`, 'ms') - const rangeTagReg = new RegExp(`(${startTag}|${endTag})+`, 'mg') + const rangeTagReg = new RegExp(`(${startTag}|${endTag})+`, 'gm') const match = data.match(rangeReg) - if (!match) return null + if (!match) + return null return match[0]?.replace(rangeTagReg, '') } diff --git a/common/utils/question-handler/createMarkdown.js b/common/utils/question-handler/createMarkdown.js index 754f9a4..1cf94d6 100644 --- a/common/utils/question-handler/createMarkdown.js +++ b/common/utils/question-handler/createMarkdown.js @@ -7,6 +7,8 @@ import path from 'node:path' * @param {*} questionPath */ export function createMarkdown(description, questionPath) { + if (!description) + return const dir = path.dirname(questionPath) const descriptionPath = path.join(dir, 'description.md') fs.writeFileSync(descriptionPath, description) diff --git a/common/utils/question-handler/createQuestion.js b/common/utils/question-handler/createQuestion.js index c8d7fb9..969b66e 100644 --- a/common/utils/question-handler/createQuestion.js +++ b/common/utils/question-handler/createQuestion.js @@ -1,8 +1,8 @@ import fs from 'node:fs' import path from 'node:path' +import { getSupportCode } from '#common/utils/question-handler/code.js' import { fulfillQuestion } from '#common/utils/question-handler/fulfillQuestion.js' import { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.js' -import { getSupportCode } from '#common/utils/question-handler/code.js' /** * 创建问题 @@ -12,17 +12,13 @@ import { getSupportCode } from '#common/utils/question-handler/code.js' */ export function createQuestion(question, questionDir) { return new Promise((resolve) => { - const filePath = path.normalize( - path.join( - questionDir, - `question${getQuestionFileExtension(question.lang)}` - ) - ) + const filePath = path.normalize(path.join(questionDir, `question${getQuestionFileExtension(question.lang)}`)) if (fs.existsSync(filePath)) { resolve(false) - } else { + } + else { createQuestionFile(questionDir, filePath, question) - .then((path) => resolve(path)) + .then(path => resolve(path)) .catch(() => resolve(false)) } }) @@ -36,13 +32,12 @@ export function createQuestionFile(questionDir, questionFilePath, question) { await fulfillQuestion(questionFilePath, question) if (!question.code) { const supports = await getSupportCode(question.slug) - console.warn( - `此题目不支持当前语言[${question.lang}]!受支持的语言有[${supports.join(',')}]!` - ) + console.warn(`此题目不支持当前语言[${question.lang}]!受支持的语言有[${supports.join(',')}]!`) } resolve(questionFilePath) }) - } catch (e) { + } + catch (e) { reject(e) } }) diff --git a/common/utils/question-handler/createQuestionCopy.js b/common/utils/question-handler/createQuestionCopy.js index 8720c9e..e5ebede 100644 --- a/common/utils/question-handler/createQuestionCopy.js +++ b/common/utils/question-handler/createQuestionCopy.js @@ -17,9 +17,6 @@ export function createQuestionCopy(question, questionDir) { const name = `${question.id}.${question.slug}` const affix = ` [${getCountBySameName(dir, name)}]` const copyFileDir = path.join(dir, `${name}${affix}`) - const copyFilePath = path.join( - copyFileDir, - `question${getQuestionFileExtension(question.lang)}` - ) + const copyFilePath = path.join(copyFileDir, `question${getQuestionFileExtension(question.lang)}`) return createQuestionFile(copyFileDir, copyFilePath, question) } diff --git a/common/utils/question-handler/fulfillQuestion.js b/common/utils/question-handler/fulfillQuestion.js index 830890b..b06d023 100644 --- a/common/utils/question-handler/fulfillQuestion.js +++ b/common/utils/question-handler/fulfillQuestion.js @@ -1,12 +1,12 @@ import fs from 'node:fs' -import { removeDomTags } from '../functions/removeDomTags.js' -import { getTestCase } from './getTestCase.js' -import { createMarkdown } from './createMarkdown.js' -import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js' +import { getCodeRange } from '#common/utils/question-handler/code.js' import { getConsoleText } from '#common/utils/question-handler/getConsoleText.js' -import { template } from '#resources/template/template.js' +import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js' import { setBlockComment } from '#common/utils/question-handler/questionLanguage.js' -import { getCodeRange } from '#common/utils/question-handler/code.js' +import { template } from '#resources/template/template.js' +import { removeDomTags } from '../functions/removeDomTags.js' +import { createMarkdown } from './createMarkdown.js' +import { getTestCase } from './getTestCase.js' /** * @typedef {object} Question @@ -29,7 +29,7 @@ import { getCodeRange } from '#common/utils/question-handler/code.js' */ export function generateTemplateContent(question) { const title = `${getQuestionChineseName(question)} ${question.date ? `[${question.date}]` : ''}\n` - const describe = removeDomTags(question.detail).replace(/\n+/g, '\n') + const describe = removeDomTags(question.detail)?.replace(/\n+/g, '\n') ?? '' const lang = question.lang const code = question.code return template @@ -52,7 +52,8 @@ export function fulfillQuestion(questionPath, question) { const newData = generateTemplateContent(question) // 创建文件 fs.writeFile(questionPath, newData, (err) => { - if (err) throw err + if (err) + throw err resolve() }) }) diff --git a/common/utils/question-handler/getHot100QuestionListCode.js b/common/utils/question-handler/getHot100QuestionListCode.js deleted file mode 100644 index 752f88b..0000000 --- a/common/utils/question-handler/getHot100QuestionListCode.js +++ /dev/null @@ -1,26 +0,0 @@ -import path from 'node:path' -import { createQuestionByTitleSlug } from '../create-check/createUtil.js' -import { getQuestionListHot100 } from '#common/utils/question-getter/getQuestionListHot100.js' - -// 获取题目列表 -export async function getTitleSlugList() { - const res = await getQuestionListHot100() - const { planSubGroups } = res - return planSubGroups.reduce((acc, cur) => { - acc.push(...cur.questions.map((res) => res.titleSlug)) - return acc - }, []) -} -// 获取创建promise列表 -async function getPromiseList() { - const titleSlugList = await getTitleSlugList() - const dir = path.join(process.cwd(), 'hot100') - return titleSlugList.map((titleSlug) => - createQuestionByTitleSlug(titleSlug, dir) - ) -} - -export async function getHot100QuestionListCode() { - const promiseList = await getPromiseList() - return await Promise.all(promiseList) -} diff --git a/common/utils/question-handler/getQuestionDetail.js b/common/utils/question-handler/getQuestionDetail.js index 4a4883e..b70aefb 100644 --- a/common/utils/question-handler/getQuestionDetail.js +++ b/common/utils/question-handler/getQuestionDetail.js @@ -1,13 +1,13 @@ -import { getQuestionDetailJson } from '#resources/headers/questionDetailJson.js' -import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' import { graphql } from '#common/utils/http/graphql.js' import { getCodeBySlug } from '#common/utils/question-handler/code.js' +import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' +import { getQuestionDetailJson } from '#resources/headers/questionDetailJson.js' /** * 获取代码详情 * @param slug * @param extra - * @returns {Promise<*&{code: *, detail: *, title: *, slug}>} + * @returns {Promise<*&{id:*,slug:*, title: *,detail: *, lang:*,code: *,jsonExampleTestcases:*,exampleTestcases:*}>} */ export async function getQuestionDetail(slug, extra = {}) { // 标题的英文字符串 @@ -22,6 +22,8 @@ export async function getQuestionDetail(slug, extra = {}) { detail: detail?.translatedContent, lang: curLang, code, - ...extra + jsonExampleTestcases: detail?.jsonExampleTestcases, + exampleTestcases: detail?.exampleTestcases, + ...extra, } } diff --git a/common/utils/question-handler/getQuestionFileName.js b/common/utils/question-handler/getQuestionFileName.js index 882ae44..4ccffbc 100644 --- a/common/utils/question-handler/getQuestionFileName.js +++ b/common/utils/question-handler/getQuestionFileName.js @@ -4,6 +4,7 @@ * @returns {string} */ export function getQuestionFileName(question) { - if (!question || !question?.id) return '' + if (!question || !question?.id) + return '' return `${question.id}.${question.slug}` } diff --git a/common/utils/question-handler/getQuestionIdBySlug.js b/common/utils/question-handler/getQuestionIdBySlug.js index d61f0da..c6ed176 100644 --- a/common/utils/question-handler/getQuestionIdBySlug.js +++ b/common/utils/question-handler/getQuestionIdBySlug.js @@ -1,22 +1,21 @@ import { graphql } from '#common/utils/http/graphql.js' const headers = { - 'content-type': 'application/json' + 'content-type': 'application/json', } export async function getQuestionIdBySlug(titleSlug) { const body = { - query: - '\n query questionTitle($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n title\n titleSlug\n isPaidOnly\n difficulty\n likes\n dislikes\n categoryTitle\n }\n}\n ', + query: '\n query questionTitle($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n title\n titleSlug\n isPaidOnly\n difficulty\n likes\n dislikes\n categoryTitle\n }\n}\n ', variables: { - titleSlug + titleSlug, }, - operationName: 'questionTitle' + operationName: 'questionTitle', } const initJson = { headers, body: JSON.stringify(body), - method: 'POST' + method: 'POST', } const res = await graphql(initJson) const { data: question } = res diff --git a/common/utils/question-handler/getQuestionListCodeBy.js b/common/utils/question-handler/getQuestionListCodeBy.js new file mode 100644 index 0000000..160b320 --- /dev/null +++ b/common/utils/question-handler/getQuestionListCodeBy.js @@ -0,0 +1,41 @@ +import { createQuestionById, createQuestionByTitleSlug } from '#common/utils/cli-utils/createQuestion.js' +import { getPlanQuestionList } from '#common/utils/question-getter/getPlanQuestionList.js' + +// 根据 slug 获取创建promise列表 +async function createSlugPromiseList(slugList, baseDir = process.cwd()) { + return slugList.map((titleSlug) => { + return createQuestionByTitleSlug(titleSlug, baseDir) + }) +} + +// 根据 id 获取创建promise列表 +async function createIdPromiseList(questionList, baseDir = process.cwd()) { + return questionList.map((question) => { + return createQuestionById(question.questionId, baseDir) + }) +} + +/** + * 創建題目列表通過plan slug + * @param slug + * @param baseDir + */ +export async function getQuestionListCodeBySlug(slug, baseDir) { + const { planSubGroups } = await getPlanQuestionList(slug) + const questionTitleList = planSubGroups.reduce((acc, cur) => { + acc.push(...cur.questions.map(res => res.titleSlug)) + return acc + }, []) + const promiseList = await createSlugPromiseList(questionTitleList, baseDir) + return await Promise.allSettled(promiseList) +} + +/** + * 創建題目列表通過tag + * @param tagQuestionList + * @param baseDir + */ +export async function getQuestionListCodeByTag(tagQuestionList, baseDir) { + const promiseList = await createIdPromiseList(tagQuestionList, baseDir) + return await Promise.allSettled(promiseList) +} diff --git a/common/utils/question-handler/getRandomId.js b/common/utils/question-handler/getRandomId.js index 0c6b3f1..e2639ee 100644 --- a/common/utils/question-handler/getRandomId.js +++ b/common/utils/question-handler/getRandomId.js @@ -1,43 +1,42 @@ import { readdirSync } from 'node:fs' -import { getQuestionListJson } from '#resources/headers/questionListJson.js' -import { graphql } from '#common/utils/http/graphql.js' import { DefaultLimit } from '#common/constants/question.const.js' +import { graphql } from '#common/utils/http/graphql.js' +import { logger } from '#common/utils/logger/logger.js' +import { getQuestionListJson } from '#resources/headers/questionListJson.js' /** * 获取指定页数的ids */ export async function getIds(index, limit = DefaultLimit) { const res = await graphql(getQuestionListJson(index, limit)) - return res?.data?.problemsetQuestionList?.questions?.map( - (q) => q.frontendQuestionId - ) + return res?.data?.problemsetQuestionList?.questions?.map(q => q.frontendQuestionId) } /** * 获取总数 * @returns {Promise<any>} */ export function getCount() { - return graphql(getQuestionListJson(0)).then( - (res) => res?.data?.problemsetQuestionList?.total - ) + return graphql(getQuestionListJson(0)).then(res => res?.data?.problemsetQuestionList?.total) } /** * 获取随机的一个id 只要保证没有存在过就可以 */ export async function getRandomId() { // 去除所有的标题 剩下的就是id - const parse = (name) => name.replace(/\.[a-zA-Z0-9-]+$/i, '') + const parse = name => name.replace(/\.[a-z0-9-]+$/i, '') // 获取一个 递归的获取 总会有一个 直到数量到达最大值 const getOne = async (waitIndexList, localIds) => { const randomIndex = waitIndexList[random(waitIndexList.length)] const ids = await getIds(randomIndex) // 过滤后的结果 - const filtered = ids.filter((o) => !localIds.includes(o)) - if (randomIndex === undefined) return null + const filtered = ids.filter(o => !localIds.includes(o)) + if (randomIndex === undefined) + return null if (filtered.length) { return filtered[random(filtered.length)] - } else { - waitIndexList.splice(waitIndexList.findIndex((i) => i === randomIndex)) + } + else { + waitIndexList.splice(waitIndexList.findIndex(i => i === randomIndex)) return await getOne(waitIndexList, localIds) } } @@ -46,10 +45,11 @@ export async function getRandomId() { // 最大的数量 const maxLength = await getCount() const waitIndexList = Array.from({ - length: Math.ceil(maxLength / DefaultLimit) + length: Math.ceil(maxLength / DefaultLimit), }).map((_, i) => i) const one = await getOne(waitIndexList, allLocalIds) - if (one === null) console.log('恭喜!你已经刷完了所有的题目!') + if (one === null) + logger.info('恭喜!你已经刷完了所有的题目!') else return one } /** diff --git a/common/utils/question-handler/getTestCase.js b/common/utils/question-handler/getTestCase.js index 2862f73..13ffb0a 100644 --- a/common/utils/question-handler/getTestCase.js +++ b/common/utils/question-handler/getTestCase.js @@ -1,7 +1,7 @@ -import { removeDomTags } from '../functions/removeDomTags.js' -import { getDataStructure } from './parseStructure.js' import { DefaultLang } from '#common/constants/question.const.js' import { setBlockComment } from '#common/utils/question-handler/questionLanguage.js' +import { removeDomTags } from '../functions/removeDomTags.js' +import { getDataStructure } from './parseStructure.js' /** * 输出的日志 @@ -44,53 +44,48 @@ function logsTemplate(question, functionName, cases, expires) { */ export function getTestCase(question) { // 完整的一条语句的reg - const inputReg = /(<[a-zA-Z]+>)?输入[:|:](<\/[a-zA-Z]+>)?.+\n/g - const inputStartReg = /(<[a-zA-Z]+>)?输入[:|:]/gm + const inputReg = /(<[a-z]+>)?输入[:|:](<\/[a-z]+>)?.+\n/gi + const inputStartReg = /(<[a-z]+>)?输入[:|:]/gi // 输出的reg - const outputReg = /(<[a-zA-Z]+>)?输出[:|:](<\/[a-zA-Z]+>)?.+\n/g - const outputStartReg = /(<[a-zA-Z]+>)?输出[:|:]/gm + const outputReg = /(<[a-z]+>)?输出[:|:](<\/[a-z]+>)?.+\n/gi + const outputStartReg = /(<[a-z]+>)?输出[:|:]/gi // 结尾 - const endReg = /(<\/[a-zA-Z]+>)?/gm + const endReg = /(<\/[a-z]+>)?/gi - const detail = question.detail.replaceAll('`', '') - const cases = detail.match(inputReg)?.map( - (str) => + const detail = question.detail?.replaceAll('`', '') + const cases = detail?.match(inputReg)?.map( + str => `[${removeDomTags( str ?.replace(inputStartReg, '') ?.replace(endReg, '') ?.replace('\n', '') - .replace(/[a-zA-Z]+ =/g, '') - )}]` + .replace(/[a-z]+ =/gi, ''), + )}]`, ) - const expires = detail.match(outputReg)?.map((str) => + const expires = detail?.match(outputReg)?.map(str => removeDomTags( str ?.replace(outputStartReg, '') ?.replace(endReg, '') ?.replace('\n', '') - .replace(/[a-zA-Z]+ =/g, '') - ) + .replace(/[a-z]+ =/gi, ''), + ), ) if (question.lang === DefaultLang) { const functionName = question.code ?.match(/(var|let|const).+=/g)?.[0] - ?.replace(/((var|let|const)|=)\s?/gm, '') + ?.replace(/((var|let|const)|=)\s?/g, '') .trim() - if (!functionName) return '' - return ( - setBlockComment(question.lang, 'Test Cases') + - logsTemplate(question, functionName, cases, expires) - ) - } else { + if (!functionName) + return '' + return setBlockComment(question.lang, 'Test Cases') + logsTemplate(question, functionName, cases, expires) + } + else { // 其他语言无法支持测试 只能提供测试数据 // 生成注释语句 let showText = `暂无法支持除JS外的语言测试,提取的一些入参和返回值供自行测试,每一个case中的第一行为入参,第二行为返回值\n` - for ( - let i = 0; - i < Math.max(cases?.length ?? 0, expires?.length ?? 0); - i++ - ) { + for (let i = 0; i < Math.max(cases?.length ?? 0, expires?.length ?? 0); i++) { showText += `case ${i + 1}:\n` showText += `${cases?.[i]}\n` ?? '[参数获取错误]\n' showText += `${expires?.[i]}\n` ?? '[返回值获取错误]\n' diff --git a/common/utils/question-handler/parseStructure.js b/common/utils/question-handler/parseStructure.js index 1ed941a..65be67a 100644 --- a/common/utils/question-handler/parseStructure.js +++ b/common/utils/question-handler/parseStructure.js @@ -1,24 +1,24 @@ +import { ListNode } from '#common/structures/ListNode.js' import { Node } from '../../structures/Node.js' import { TreeNode } from '../../structures/TreeNode.js' -import { ListNode } from '#common/structures/ListNode.js' const paramMap = { // 入参map cases: { - ListNode: (_param) => ListNode.parse(_param), - 'ListNode[]': (param) => param.map((res) => ListNode.parse(res)), - TreeNode: (param) => TreeNode.parse(param), - Node: (param) => Node.parse(param), - default: (param) => param + 'ListNode': _param => ListNode.parse(_param), + 'ListNode[]': param => param.map(res => ListNode.parse(res)), + 'TreeNode': param => TreeNode.parse(param), + 'Node': param => Node.parse(param), + 'default': param => param, }, // 返回值map return: { - ListNode: (param) => ListNode.toArray(param), - 'ListNode[]': (param) => param.map((res) => ListNode.toArray(res)), - TreeNode: (param) => TreeNode.toArray(param), - Node: (param) => Node.toArray(param), - default: (param) => param - } + 'ListNode': param => ListNode.toArray(param), + 'ListNode[]': param => param.map(res => ListNode.toArray(res)), + 'TreeNode': param => TreeNode.toArray(param), + 'Node': param => Node.toArray(param), + 'default': param => param, + }, } /** * @@ -42,8 +42,8 @@ export function setDataStructure(params, structs, type = 'cases') { */ export function getDataStructure(code, type = 'param') { const regexMap = { - param: /@param\s+{\s*([^}\s]+)\s*}/g, - return: /@return\s+{\s*([^}\s]+)\s*}/g + param: /@param\s+\{\s*([^}\s]+)\s*\}/g, + return: /@return\s+\{\s*([^}\s]+)\s*\}/g, } const regex = regexMap[type] const paramTypes = [] diff --git a/common/utils/question-handler/questionLanguage.js b/common/utils/question-handler/questionLanguage.js index ca4bc22..ccc1371 100644 --- a/common/utils/question-handler/questionLanguage.js +++ b/common/utils/question-handler/questionLanguage.js @@ -1,5 +1,5 @@ -import { getStore, setStore } from '#common/utils/store/controller/store.js' import { DefaultLang } from '#common/constants/question.const.js' +import { getStore, setStore } from '#common/utils/store/controller/store.js' /** * 语言 @@ -11,204 +11,204 @@ export const LANGUAGES = [ name: 'cpp', extension: '.cpp', blockComment: '/*\n*\n*/', // 块级注释 使用换行符来分割 - lineComment: '//' // 行级注释 不需要分割 + lineComment: '//', // 行级注释 不需要分割 }, { id: 1, name: 'java', extension: '.java', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 2, name: 'python', extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' + blockComment: '\'\'\'\n\n\'\'\'', + lineComment: '#', }, { id: 11, name: 'python3', extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' + blockComment: '\'\'\'\n\n\'\'\'', + lineComment: '#', }, { id: 3, name: 'mysql', extension: '.sql', blockComment: '/*\n*\n*/', - lineComment: '--' + lineComment: '--', }, { id: 14, name: 'mssql', extension: '.sql', blockComment: '/*\n*\n*/', - lineComment: '--' + lineComment: '--', }, { id: 15, name: 'oraclesql', extension: '.sql', blockComment: '/*\n*\n*/', - lineComment: '--' + lineComment: '--', }, { id: 4, name: 'c', extension: '.c', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 5, name: 'csharp', extension: '.cs', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 6, name: 'javascript', extension: '.js', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 20, name: 'typescript', extension: '.ts', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 8, name: 'bash', extension: '.sh', - blockComment: "'''\n\n'''", - lineComment: '#' + blockComment: '\'\'\'\n\n\'\'\'', + lineComment: '#', }, { id: 19, name: 'php', extension: '.php', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 9, name: 'swift', extension: '.swift', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 13, name: 'kotlin', extension: '.kt', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 24, name: 'dart', extension: '.dart', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 10, name: 'golang', extension: '.go', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 7, name: 'ruby', extension: '.rb', blockComment: '=begin\n\n=end', - lineComment: '#' + lineComment: '#', }, { id: 12, name: 'scala', extension: '.scala', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 16, name: 'html', extension: '.html', blockComment: '<!--\n\n-->', - lineComment: '' + lineComment: '', }, { id: 17, name: 'pythonml', extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' + blockComment: '\'\'\'\n\n\'\'\'', + lineComment: '#', }, { id: 18, name: 'rust', extension: '.rs', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 21, name: 'racket', extension: '.rkt', blockComment: ';;\n\n;;', - lineComment: '' + lineComment: '', }, { id: 22, name: 'erlang', extension: '.erl', blockComment: '%%\n\n%%', - lineComment: '' + lineComment: '', }, { id: 23, name: 'elixir', extension: '.ex', blockComment: '#\n#\n#', - lineComment: '' + lineComment: '', }, { id: 25, name: 'pythondata', extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' + blockComment: '\'\'\'\n\n\'\'\'', + lineComment: '#', }, { id: 26, name: 'react', extension: '.jsx', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 27, name: 'vanillajs', extension: '.js', blockComment: '/*\n*\n*/', - lineComment: '//' + lineComment: '//', }, { id: 28, name: 'postgresql', extension: '.sql', blockComment: '/*\n*\n*/', - lineComment: '--' - } + lineComment: '--', + }, ] /** @@ -231,7 +231,7 @@ export async function getQuestionLanguage() { * @returns {*} */ export function getLang(lang) { - return LANGUAGES.find((o) => o.name.toLowerCase() === lang.toLowerCase()) + return LANGUAGES.find(o => o.name.toLowerCase() === lang.toLowerCase()) } /** * 获取文件后缀 @@ -248,10 +248,10 @@ export function getQuestionFileExtension(lang = DefaultLang) { * @returns {*} */ export function getLangByExtension(extensionLike) { - const reg = /\.[0-9a-zA-Z_]+$/im + const reg = /\.\w+$/m const match = extensionLike.match(reg) const extension = match === null ? `.${extensionLike}` : match[0] - return LANGUAGES?.find((o) => o.extension === extension) + return LANGUAGES?.find(o => o.extension === extension) } /** * 获取行注释 @@ -262,7 +262,8 @@ export function getLineComment(lang = DefaultLang) { const langObj = getLang(lang) if (langObj.lineComment !== '') { return langObj.lineComment - } else { + } + else { // 因为保底是都有块级注释的 return null } @@ -289,7 +290,8 @@ export function setLineComment(lang = DefaultLang, comment = '') { if (lineComment !== null) { const lines = comment.split('\n') return lines.reduce((p, line) => (p += `${lineComment} ${line}\n`), '') - } else { + } + else { return setBlockComment(lang, comment) } } @@ -309,10 +311,7 @@ export function setBlockComment(lang = DefaultLang, comment = '') { const start = splitter[0] const end = splitter[2] const startTag = splitter[1] - const content = lines.reduce( - (p, line) => (p += `${startTag} ${line}\n`), - '' - ) + const content = lines.reduce((p, line) => (p += `${startTag} ${line}\n`), '') return `${start}\n${content}${end}\n` } default: diff --git a/common/utils/question-handler/showLogs.js b/common/utils/question-handler/showLogs.js index 3c98ffb..fc7b46d 100644 --- a/common/utils/question-handler/showLogs.js +++ b/common/utils/question-handler/showLogs.js @@ -1,7 +1,7 @@ import v8 from 'node:v8' import { Table } from 'console-table-printer' -import { getFileSize } from '../functions/sizeUtil.js' import { isSameData } from '../functions/isSameData.js' +import { getFileSize } from '../functions/sizeUtil.js' import { setDataStructure } from './parseStructure.js' /** @@ -18,30 +18,20 @@ export function parseLog(fnName, param, compare, compareStruct) { // 获取函数执行前的内存使用情况 const startHeapStatsArray = v8.getHeapSpaceStatistics() const callVal = fnName(...param) - const [parsedCompareArr] = setDataStructure( - [callVal], - compareStruct, - 'return' - ) + const [parsedCompareArr] = setDataStructure([callVal], compareStruct, 'return') // 获取函数执行后的内存使用情况 const endHeapStatsArray = v8.getHeapSpaceStatistics() // 记录结束时间 const endTime = performance.now() - const startHeapStats = startHeapStatsArray.reduce( - (prev, curr) => (prev += curr.space_used_size), - 0 - ) - const endHeapStats = endHeapStatsArray.reduce( - (prev, curr) => (prev += curr.space_used_size), - 0 - ) + const startHeapStats = startHeapStatsArray.reduce((prev, curr) => (prev += curr.space_used_size), 0) + const endHeapStats = endHeapStatsArray.reduce((prev, curr) => (prev += curr.space_used_size), 0) return { 测试结果: isSameData(parsedCompareArr, compare) ? '通过' : '未通过', 预期结果: JSON.stringify(compare), 执行结果: JSON.stringify(parsedCompareArr), 执行用时: `${Number(endTime - startTime).toFixed(4)}ms`, - 内存占用: getFileSize(endHeapStats - startHeapStats) + 内存占用: getFileSize(endHeapStats - startHeapStats), } } @@ -52,12 +42,7 @@ export function showLogs(fnName, paramMap, compareMap) { paramArr.forEach((param, index) => { const parsedParma = setDataStructure(param, paramStruct) - const logItem = parseLog( - fnName, - parsedParma, - compareArr[index], - compareStruct - ) + const logItem = parseLog(fnName, parsedParma, compareArr[index], compareStruct) logsItems.push(logItem) }) @@ -67,18 +52,17 @@ export function showLogs(fnName, paramMap, compareMap) { { name: '预期结果', title: '预期结果', alignment: 'center', maxLen: 40 }, { name: '执行结果', title: '执行结果', alignment: 'center', maxLen: 40 }, { name: '执行用时', title: '执行用时', alignment: 'center', maxLen: 10 }, - { name: '内存占用', title: '内存占用', alignment: 'center', maxLen: 10 } - ] + { name: '内存占用', title: '内存占用', alignment: 'center', maxLen: 10 }, + ], }) logsItems.forEach((item) => { for (const key in item) { - if (key === '预期结果' || key === '执行结果') { - item[key] = - item[key]?.length >= 40 ? `${item[key].slice(0, 37)}...` : item[key] - } + if (key === '预期结果' || key === '执行结果') + item[key] = item[key]?.length >= 40 ? `${item[key].slice(0, 37)}...` : item[key] } + logTable.addRow(item, { - color: item['测试结果'] === '通过' ? 'green' : 'red' + color: item['测试结果'] === '通过' ? 'green' : 'red', }) }) logTable.printTable() diff --git a/common/utils/store/controller/allQuestion.js b/common/utils/store/controller/allQuestion.js new file mode 100644 index 0000000..eecf21e --- /dev/null +++ b/common/utils/store/controller/allQuestion.js @@ -0,0 +1,97 @@ +import { exeOnce } from '#common/utils/store/store-realm.js' + +const oSign = '$object$' +/** + * 读取的时候:从对象的字符串转化到对象的对象 + * @param obj + */ +function parseQuestion(obj) { + if (!obj) + return null + return Object.entries(obj).reduce((pre, [k, v]) => { + pre[k] = typeof v == 'string' && v.startsWith(oSign) ? JSON.parse(v.replace(oSign, '')) : v + return pre + }, {}) +} +/** + * 存入的时候:从对象的对象属性转化到字符串 + */ +function stringifyQuestion(obj) { + if (!obj) + return null + return ( + Object.entries(obj)?.reduce((pre, [key, value]) => { + pre[key] = value != null && typeof value === 'object' ? oSign + JSON.stringify(value) : value + return pre + }, {}) ?? {} + ) +} + +/** + * 获取一个问题对象 + * @param id + * @returns {Promise<void>} + */ +export function getOneQuestion(id) { + return exeOnce((realm) => { + const question = realm.objectForPrimaryKey('AllQuestion', id) + return parseQuestion(question?.toJSON()) + }) +} + +/** + * 存一个问题对象 + * @param question + * @returns {*} + */ +export function setOneQuestion(question) { + return exeOnce((realm) => { + let newQuestion + realm.write(() => { + newQuestion = realm.create('AllQuestion', stringifyQuestion(question), true) + }) + return newQuestion?.toJSON() + }) +} + +/** + * 根据模式读取对象 + * @returns {unknown} + */ +export function getAllQuestion() { + return exeOnce((realm) => { + const all = realm.objects('AllQuestion') + return all?.toJSON()?.map(parseQuestion) + }) +} + +/** + * 存对象 + * @param questions + * @returns {*} + */ +export function setAllQuestion(questions) { + return exeOnce((realm) => { + const newQuestions = [] + realm.write(() => { + for (const question of questions) { + const data = stringifyQuestion(question) + if (!data?.questionId) + continue + newQuestions.push(realm.create('AllQuestion', data, true)) + } + }) + return newQuestions + }) +} + +/** + * 删除全部 + */ +export function deleteAllQuestion() { + return exeOnce((realm) => { + realm.write(() => { + realm.delete(realm.objects('AllQuestion')) + }) + }) +} diff --git a/common/utils/store/controller/store.js b/common/utils/store/controller/store.js index 5da932b..3b595e7 100644 --- a/common/utils/store/controller/store.js +++ b/common/utils/store/controller/store.js @@ -1,5 +1,5 @@ -import { exeOnce } from '#common/utils/store/store-realm.js' import { typeof_ } from '#common/utils/etc/typeof_.js' +import { exeOnce } from '#common/utils/store/store-realm.js' /** * 转化数据到特殊格式字符串 @@ -18,8 +18,9 @@ function convData(data) { * @returns {any} */ function parseData(dataStr) { - const prefixReg = /^\$<.+>\$/im - if (!prefixReg.test(dataStr)) return null + const prefixReg = /^\$<.+>\$/m + if (!prefixReg.test(dataStr)) + return null const type = dataStr.match(prefixReg)[0].replace(/[$<>]+/g, '') const remainStr = dataStr.replace(prefixReg, '') diff --git a/common/utils/store/schemas/allQuestion.js b/common/utils/store/schemas/allQuestion.js new file mode 100644 index 0000000..591b226 --- /dev/null +++ b/common/utils/store/schemas/allQuestion.js @@ -0,0 +1,26 @@ +import Realm from 'realm' + +export class AllQuestion extends Realm.Object { + static schema = { + name: 'AllQuestion', + properties: { + questionId: 'string', + questionFrontendId: 'string?', + questionType: 'string?', + categoryTitle: 'string?', + title: 'string?', + titleSlug: 'string?', + difficulty: 'string?', + isPaidOnly: 'bool?', + codeSnippets: 'string?', + topicTags: 'string?', + relatedTags: 'string?', + translatedTitle: 'string?', + stats: 'string?', + extra: 'string?', + isNewQuestion: 'bool?', + frequency: 'string?', + }, + primaryKey: 'questionId', + } +} diff --git a/common/utils/store/schemas/question.js b/common/utils/store/schemas/question.js index 1d3b20d..57db7a6 100644 --- a/common/utils/store/schemas/question.js +++ b/common/utils/store/schemas/question.js @@ -7,15 +7,17 @@ export class Question extends Realm.Object { _id: { type: 'objectId', default: () => new Realm.BSON.ObjectId() }, id: 'string', mode: 'string', - slug: 'string', - title: 'string', - detail: 'string', + slug: 'string?', + title: 'string?', + detail: 'string?', + jsonExampleTestcases: 'string?', + exampleTestcases: 'string?', lang: 'string', code: 'string?', url: 'string?', date: 'string?', - timestamp: { type: 'date', default: () => new Date() } + timestamp: { type: 'date', default: () => new Date() }, }, - primaryKey: '_id' + primaryKey: '_id', } } diff --git a/common/utils/store/schemas/store.js b/common/utils/store/schemas/store.js index 9ee3f6f..4f7a696 100644 --- a/common/utils/store/schemas/store.js +++ b/common/utils/store/schemas/store.js @@ -6,8 +6,8 @@ export class Store extends Realm.Object { properties: { key: 'string', value: 'string', - timestamp: { type: 'date', default: () => new Date() } + timestamp: { type: 'date', default: () => new Date() }, }, - primaryKey: 'key' + primaryKey: 'key', } } diff --git a/common/utils/store/store-realm.js b/common/utils/store/store-realm.js index 7392047..8475b50 100644 --- a/common/utils/store/store-realm.js +++ b/common/utils/store/store-realm.js @@ -1,9 +1,10 @@ -import path from 'node:path' import { readdirSync, rmSync } from 'node:fs' -import Realm from 'realm' -import { Question } from '#common/utils/store/schemas/question.js' +import path from 'node:path' import { rootPath } from '#common/utils/file/getRootPath.js' +import { AllQuestion } from '#common/utils/store/schemas/allQuestion.js' +import { Question } from '#common/utils/store/schemas/question.js' import { Store } from '#common/utils/store/schemas/store.js' +import Realm from 'realm' const localPath = path.resolve(rootPath, 'resources/stores/store.realm') /** @@ -14,15 +15,17 @@ export async function open() { let realm try { realm = await Realm.open({ - schema: [Question, Store], - path: localPath + schema: [Question, AllQuestion, Store], + path: localPath, }) - } catch (e) { - if (e?.message?.includes('Migration')) await cleanStore() + } + catch (e) { + if (e?.message?.includes('Migration')) + await cleanStore() realm = await Realm.open({ - schema: [Question, Store], - path: localPath + schema: [Question, AllQuestion, Store], + path: localPath, }) } return realm diff --git a/common/utils/update/update.js b/common/utils/update/update.js index bef2cb4..7ee30ad 100644 --- a/common/utils/update/update.js +++ b/common/utils/update/update.js @@ -1,31 +1,14 @@ import fs from 'node:fs' import path from 'node:path' +import { GITEE_URL, GITHUB_HOST, GITHUB_RAW, NPM_REGISTRY_URL, PackageName } from '#common/constants/question.const.js' import { rootPath } from '#common/utils/file/getRootPath.js' -import { - GITEE_URL, - GITHUB_HOST, - GITHUB_RAW, - NPM_URL, - PackageName -} from '#common/constants/question.const.js' -import { url_join } from '#common/utils/http/urlJoin.js' import { fetch_ } from '#common/utils/http/fetch_.js' +import { url_join } from '#common/utils/http/urlJoin.js' // npm 中的 包地址 -const npmUrl = url_join(NPM_URL, PackageName) -const githubUrl = url_join( - GITHUB_RAW, - GITHUB_HOST, - PackageName, - 'master/package.json' -) -const giteeUrl = url_join( - GITEE_URL, - GITHUB_HOST, - PackageName, - 'raw', - 'master/package.json' -) +const npmUrl = url_join(NPM_REGISTRY_URL, PackageName) +const githubUrl = url_join(GITHUB_RAW, GITHUB_HOST, PackageName, 'master/package.json') +const giteeUrl = url_join(GITEE_URL, GITHUB_HOST, PackageName, 'raw', 'master/package.json') /** * 获取远端npm库中的版本号 @@ -33,57 +16,66 @@ const giteeUrl = url_join( export async function getNpmVersion() { try { const res = await fetch_(npmUrl, { method: 'GET' }) - console.log('获取NPM版本成功!======', res['dist-tags']?.latest) - return res['dist-tags']?.latest - } catch (e) { - console.log('获取NPM版本失败!') - throw new Error(e) + return res['dist-tags']?.latest || null + } + catch (e) { + console.error('Error fetching npm version:', e) + return null } } + /** * 获取github的最新提交sha - * @returns {Promise<unknown>} + * @returns {Promise<string|null>} */ export async function getGithubVersion() { try { - const [{ reason: _1, value: github }, { reason: _2, value: gitee }] = - await Promise.allSettled([ - fetch_(githubUrl, { method: 'GET' }), - fetch_(giteeUrl, { method: 'GET' }) - ]) - const ver = github?.version ?? gitee?.version - console.log('获取Github版本成功!======', ver) - return ver - } catch (e) { - console.log('获取Github版本失败!', e) - throw new Error(e) + const results = await Promise.allSettled([ + fetch_(githubUrl, { method: 'GET' }), + fetch_(giteeUrl, { method: 'GET' }), + ]) + + for (const result of results) { + if (result.status === 'fulfilled' && result.value?.version) { + return result.value.version + } + } + return null + } + catch (e) { + console.error('Error fetching GitHub version:', e) + return null } } + export function getLocalVersion() { try { - const { version } = JSON.parse( - fs.readFileSync(path.resolve(rootPath, 'package.json'), 'utf-8') - ) - console.log('本地版本号获取成功!======', version) + const packageJsonPath = path.resolve(rootPath, 'package.json') + const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) return version - } catch (e) { - console.log('本地版本号获取失败!') - return false + } + catch (e) { + console.error('Error reading local version:', e) + return null } } + /** * 检测整体的更新状况 - * @returns {Promise<{localVersion: (any|boolean), githubVersion: *, isCliUpdate: boolean, remoteVersion: unknown, isGithubUpdate: boolean}>} + * @returns {Promise<{localVersion: string|null, npmVersion: string|null, githubVersion: string|null, isCliUpdate: boolean, isGithubUpdate: boolean}>} */ export async function checkUpdate() { - const remote = await getNpmVersion() - const github = await getGithubVersion() - const local = getLocalVersion() + const [remote, github, local] = await Promise.all([ + getNpmVersion(), + getGithubVersion(), + Promise.resolve(getLocalVersion()), + ]) + return { localVersion: local, npmVersion: remote, githubVersion: github, - isCliUpdate: remote !== local, - isGithubUpdate: github !== local + isCliUpdate: remote !== null && remote !== local, + isGithubUpdate: github !== null && github !== local, } } diff --git a/common/utils/update/updateByEnv.js b/common/utils/update/updateByEnv.js index b2409e4..7a4f060 100644 --- a/common/utils/update/updateByEnv.js +++ b/common/utils/update/updateByEnv.js @@ -1,25 +1,5 @@ import { exec } from 'node:child_process' -import https from 'node:https' -import fs from 'node:fs' -import inquirer from 'inquirer' -import { getGithubVersion } from '#common/utils/update/update.js' -/** - * 根据环境进行更新 - * @param {"cli"|"project"} env - */ -export async function updateByEnv(env) { - switch (env) { - case 'cli': - // 执行CLI更新逻辑 - return await updateCli() - case 'project': - // 执行项目更新逻辑 - return await updateProject() - default: - throw new Error(`Unsupported environment: ${env}`) - } -} /** * 更新CLI * @returns {Promise<void>} @@ -27,94 +7,9 @@ export async function updateByEnv(env) { export function updateCli() { return new Promise((resolve, reject) => { exec(`npm install -g leetcode-practice`, (err) => { - if (err) reject(err) + if (err) + reject(err) else resolve() }) }) } -/** - * 更新项目 - * @returns {Promise<void>} - */ -export async function updateProject() { - console.log('脚本升级中,请等待后续版本更新...') - return - // todo 更新项目 - // 0. 询问是否存在自己修改过的内容 - // 0.1 如果有过更改,终止更新脚本,并给出提示建议 - // 0.2 如果没有更改,进行更新操作 - // 1. 检测当前的git工作区 - // 1.1 如果有内容,提示提交,终止更新 - // 1.2 如果空,可以进行更新 - // 2. 通过raw.github.com下载所有的文件并对应更新文件(除package.json) - // 2.0 所有的文件在更新后都进行git add [file-path] - // 2.1 如果文件不存在,则创建文件 - // 2.2 如果文件存在,则覆盖文件 - // 2.3 更新package.json文件中的版本号为最新的版本号. - // 3. 创建一个git的commit update:Version [版本号] - // 4. 完成更新 - async function execCommand(command) { - return new Promise((resolve, reject) => { - exec(command, (error, stdout) => { - if (error) reject(error) - else resolve(stdout.trim()) - }) - }) - } - - try { - const ltsVersion = await getGithubVersion() - // 0. 询问是否存在自己修改过的内容 - const { hasChanges } = await inquirer.prompt([ - { - type: 'confirm', - name: 'hasChanges', - message: '是否存在自己修改过的内容?', - default: false - } - ]) - - // 0.1 如果有过更改,终止更新脚本,并给出提示建议 - if (hasChanges) { - console.log('您有未提交的更改,请先处理后再更新。') - return - } - - // 1. 检测当前的git工作区 - const gitStatus = await execCommand('git status --porcelain') - - // 1.1 如果有内容,提示提交,终止更新 - if (gitStatus) { - console.log('您有未提交的更改,请先提交后再更新。') - return - } - - // 2. 下载所有的文件并对应更新文件(除package.json) - const response = await https.get( - 'https://raw.githubusercontent.com/wh131462/leetcode-practice' - ) - const filesToUpdate = response.data - - // 2.0 所有的文件在更新后都进行git add [file-path] - for (const filePath in filesToUpdate) { - fs.writeFileSync(filePath, filesToUpdate[filePath]) - - // 2.1 如果文件不存在,则创建文件 - // 2.2 如果文件存在,则覆盖文件 - await execCommand(`git add ${filePath}`) - } - - // 2.3 更新package.json文件中的版本号为最新的版本号 - const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8')) - packageJson.version = `${ltsVersion}` // 这里替换为实际的最新版本号 - fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2)) - - // 3. 创建一个git的commit update:Version [版本号] - await execCommand(`git commit -m "update:${ltsVersion}"`) // 这里替换为实际的最新版本号 - - // 4. 完成更新 - console.log('项目更新完成。') - } catch (error) { - console.error('更新过程中出现错误:', error) - } -} diff --git a/common/view/check.view.js b/common/view/check.view.js index 8172651..506c1ad 100644 --- a/common/view/check.view.js +++ b/common/view/check.view.js @@ -1,11 +1,12 @@ import path from 'node:path' -import inquirer from 'inquirer' -import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' -import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' -import { getQuestionByMode } from '#common/utils/store/controller/question.js' -import { checkQuestion } from '#common/utils/question-handler/checkQuestion.js' import { getCountBySameName } from '#common/utils/file/getCountBySameName.js' import { getFileListBySameName } from '#common/utils/file/getFileListBySameName.js' +import { logger } from '#common/utils/logger/logger.js' +import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' +import { checkQuestionByPath } from '#common/utils/question-handler/checkQuestionByPath.js' +import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' +import { getQuestionByMode } from '#common/utils/store/controller/question.js' +import inquirer from 'inquirer' export async function easyCheckView() { const modeQuestion = [ @@ -13,8 +14,8 @@ export async function easyCheckView() { type: 'list', name: 'mode', message: '请选择检查问题的模式:', - choices: ['today', 'identity', 'random'] - } + choices: ['today', 'identity', 'random'], + }, ] // 第一个问题 选择的模式 const { mode } = await inquirer.prompt(modeQuestion, null) @@ -22,16 +23,14 @@ export async function easyCheckView() { { type: 'input', name: 'identity', - message: '请输入题目编号:' - } + message: '请输入题目编号:', + }, ] let question switch (mode) { case 'identity': { const { identity } = await inquirer.prompt(identityQuestion, null) - question = !identity - ? await getQuestionByMode(mode) - : await getQuestionById(identity) + question = !identity ? await getQuestionByMode(mode) : await getQuestionById(identity) break } case 'random': @@ -51,8 +50,8 @@ export async function easyCheckView() { { type: 'confirm', name: 'dirRight', - message: `是否检测当前目录[ ${currentDir} ]下的题目[ ${questionFileName} ]?` - } + message: `是否检测当前目录[ ${currentDir} ]下的题目[ ${questionFileName} ]?`, + }, ] const { dirRight } = await inquirer.prompt(pathRightQuestion, null) if (!dirRight) { @@ -60,18 +59,15 @@ export async function easyCheckView() { { type: 'input', name: 'newDir', - message: `请选择新目录(基础地址为${currentDir})[按回车[Enter]终止操作]:` - } + message: `请选择新目录(基础地址为${currentDir})[按回车[Enter]终止操作]:`, + }, ] const { newDir } = await inquirer.prompt(newDirQuestion, null) if (!newDir) { - console.log('[LK-LOG]用户终止操作~') + logger.info('[LK-logger]用户终止操作~') process.exit(0) } - questionDir = path.join( - path.join(process.cwd(), newDir), - `${questionFileName}` - ) + questionDir = path.join(path.join(process.cwd(), newDir), `${questionFileName}`) } const questionParentDir = path.dirname(questionDir) // 先检测有几个副本 @@ -81,21 +77,16 @@ export async function easyCheckView() { type: 'list', name: 'selectQuestion', message: `题目[ ${questionFileName} ]有多个副本,请选择要检测的副本:`, - choices: getFileListBySameName(questionParentDir, questionFileName) - } + choices: getFileListBySameName(questionParentDir, questionFileName), + }, ] // 选择其中一个副本进行检查 - const { selectQuestion } = await inquirer.prompt( - selectQuestionQuestion, - null - ) + const { selectQuestion } = await inquirer.prompt(selectQuestionQuestion, null) questionDir = path.join(questionParentDir, selectQuestion) - console.log( - `用户选择题目[ ${questionFileName}]的副本[ ${selectQuestion}]进行检测` - ) + logger.info(`用户选择题目[ ${questionFileName}]的副本[ ${selectQuestion}]进行检测`) } const filePath = path.join(questionDir, `question${question.lang}`) - await checkQuestion(filePath) - console.log(`题目[${questionFileName}]检查完成!\n文件地址为: ${filePath}`) + await checkQuestionByPath(filePath) + logger.info(`题目[${questionFileName}]检查完成!\n文件地址为: ${filePath}`) process.exit(0) } diff --git a/common/view/create.view.js b/common/view/create.view.js index ecdb06c..379d261 100644 --- a/common/view/create.view.js +++ b/common/view/create.view.js @@ -1,21 +1,22 @@ import path from 'node:path' -import inquirer from 'inquirer' -import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' +import { logger } from '#common/utils/logger/logger.js' import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' -import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' import { getQuestionRandom } from '#common/utils/question-getter/getQuestionRandom.js' +import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' import { createQuestion } from '#common/utils/question-handler/createQuestion.js' import { createQuestionCopy } from '#common/utils/question-handler/createQuestionCopy.js' +import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js' import { setQuestion } from '#common/utils/store/controller/question.js' +import inquirer from 'inquirer' -export async function easyCreateView() { +export async function easyCreateView(baseDir = process.cwd()) { const modeQuestion = [ { type: 'list', name: 'mode', message: '请选择创建问题的模式:', - choices: ['today', 'identity', 'random'] - } + choices: ['today', 'identity', 'random'], + }, ] // 第一个问题 选择的模式 const { mode } = await inquirer.prompt(modeQuestion, null) @@ -23,14 +24,14 @@ export async function easyCreateView() { { type: 'input', name: 'identity', - message: '请输入题目编号:' - } + message: '请输入题目编号:', + }, ] let question switch (mode) { case 'identity': { const { identity } = await inquirer.prompt(identityQuestion, null) - console.log(identity) + logger.info(identity) question = await getQuestionById(identity) break } @@ -43,18 +44,18 @@ export async function easyCreateView() { break } const store = await setQuestion(mode, question) - if (!store) console.warn(`[create][${mode}]问题[${question.title}]未成功缓存`) - // 创建题目 + if (!store) + console.warn(`[create][${mode}]问题[${question.title}]未成功缓存`) + // 创建题目 const questionFileName = getQuestionFileName(question) - const currentDir = process.cwd() - let questionDir = path.join(currentDir, questionFileName) + let questionDir = path.join(baseDir, questionFileName) // 创建路径确认 const pathRightQuestion = [ { type: 'confirm', name: 'dirRight', - message: `是否在目录[ ${currentDir} ]下创建题目[ ${questionFileName} ]?` - } + message: `是否在目录[ ${baseDir} ]下创建题目[ ${questionFileName} ]?`, + }, ] const { dirRight } = await inquirer.prompt(pathRightQuestion, null) if (!dirRight) { @@ -62,22 +63,20 @@ export async function easyCreateView() { { type: 'input', name: 'newDir', - message: `请选择新目录(基础地址为${process.cwd()})[按回车[Enter]终止操作]:` - } + message: `请选择新目录(基础地址为${baseDir})[按回车[Enter]终止操作]:`, + }, ] const { newDir } = await inquirer.prompt(newDirQuestion, null) if (!newDir) { - console.log('[LC-LOG]用户终止操作~') + logger.info('[LC-logger]用户终止操作~') process.exit(0) } - questionDir = path.join( - path.join(process.cwd(), newDir), - `${questionFileName}` - ) + questionDir = path.join(path.join(baseDir, newDir), `${questionFileName}`) } let filePath = await createQuestion(question, questionDir) - if (!filePath) filePath = await createQuestionCopy(question, questionDir) + if (!filePath) + filePath = await createQuestionCopy(question, questionDir) - console.log(`题目[${questionFileName}]创建完成!\n文件地址为: ${filePath}`) + logger.info(`题目[${questionFileName}]创建完成!\n文件地址为: ${filePath}`) process.exit(0) } diff --git a/common/view/finder.view.js b/common/view/finder.view.js index b190155..834dc47 100644 --- a/common/view/finder.view.js +++ b/common/view/finder.view.js @@ -1,38 +1,87 @@ -import select from '@inquirer/select' +import path from 'node:path' +import { createQuestionById, createQuestionByTitleSlug } from '#common/utils/cli-utils/createQuestion.js' +import { logger } from '#common/utils/logger/logger.js' +import { getAllQuestionList } from '#common/utils/question-getter/getAllQuestionList.js' +import { getPlanQuestionList } from '#common/utils/question-getter/getPlanQuestionList.js' +import { getQuestionByKeyword } from '#common/utils/question-getter/getQuestionByKeyword.js' +import { getQuestionTagType } from '#common/utils/question-getter/getQuestionTagType.js' +import { getStudyPlanList } from '#common/utils/question-getter/getStudyPlanList.js' +import { getQuestionListCodeBySlug, getQuestionListCodeByTag } from '#common/utils/question-handler/getQuestionListCodeBy.js' +import { getAllQuestion, setAllQuestion } from '#common/utils/store/controller/allQuestion.js' import input from '@inquirer/input' +import select, { Separator } from '@inquirer/select' -import { - getHot100QuestionListCode, - getTitleSlugList -} from '#common/utils/question-handler/getHot100QuestionListCode.js' -import { - createQuestionById, - createQuestionByTitleSlug -} from '#common/utils/create-check/createUtil.js' -import { getQuestionByKeyword } from '#common/utils/question-getter/getQuestionByKeyword.js' +function handleQuestionList(list) { + const questionList = [] + list.forEach((item) => { + if (!item.premiumOnly && item.name.indexOf('SQL') <= -1 && item.name.indexOf('Pandas') <= -1) { + questionList.push({ + name: `${item.name}(${item.questionNum}题)`, + value: item.slug, + }) + } + }) + return questionList +} -async function hotMode(baseDir = process.cwd()) { +async function studyMode(baseDir = process.cwd()) { + // const sprintInterviewCompanyList = await getStudyPlanList( + // 'sprint-interview-company' + // ) + const crackingCodingInterviewList = await getStudyPlanList('cracking-coding-interview') + const deepDiveTopicsList = await getStudyPlanList('deep-dive-topics') + const questionList = [ + // ...handleQuestionList(sprintInterviewCompanyList), + // new Separator(), + ...handleQuestionList(crackingCodingInterviewList), + new Separator(), + ...handleQuestionList(deepDiveTopicsList), + ] + const planListMode = { + message: '请选择学习计划', + choices: questionList, + pageSize: 30, + } + const planSlug = await select(planListMode) const createMode = await select({ message: '拉题模式', choices: [ { name: '单个选择', value: 'single' }, - { name: '全部拉取', value: 'all' } - ] + { name: '全部拉取(不穩定)', value: 'all' }, + ], }) if (createMode === 'single') { - const titleSlugList = await getTitleSlugList() + const { planSubGroups } = await getPlanQuestionList(planSlug) + const planList = planSubGroups.reduce((acc, cur) => { + acc.push( + ...cur.questions.map((res) => { + return { + cnTitle: res.translatedTitle, + enTitle: res.titleSlug, + } + }), + ) + return acc + }, []) const singleMode = { message: '请选择题目?', - choices: titleSlugList.map((res) => ({ - name: res, - value: res - })) + choices: planList.map(res => ({ + name: res.cnTitle, + value: res.enTitle, + })), + pageSize: 30, } const singleChoice = await select(singleMode) await createQuestionByTitleSlug(singleChoice, baseDir) } - if (createMode === 'all') await getHot100QuestionListCode() + if (createMode === 'all') { + const dir = path.resolve(baseDir, planSlug.toString()) + logger.off() + await getQuestionListCodeBySlug(planSlug, dir) + logger.on() + logger.info(`题目全部拉取完成: file://${dir}`) + } } async function keywordMode(baseDir = process.cwd()) { @@ -41,44 +90,113 @@ async function keywordMode(baseDir = process.cwd()) { const list = data?.map((q) => { return { name: `${q.frontendQuestionId}.${q.titleCn}`, - value: q.frontendQuestionId + value: q.frontendQuestionId, } }) const listQuestion = { type: 'list', name: 'chooseQuestion', message: '请选择题目', - choices: list + choices: list, + pageSize: 30, } const chooseQuestion = await select(listQuestion) - console.log(chooseQuestion) await createQuestionById(chooseQuestion, baseDir) } -async function selectMode(baseDir) { - console.log(baseDir) + +async function selectMode(baseDir = process.cwd()) { + const questionTagList = await getQuestionTagType() + const tagList = questionTagList.reduce((acc, cur) => { + acc.push( + ...cur.tagRelation.map((res) => { + return { + name: `${res.tag.nameTranslated ? res.tag.nameTranslated : res.tag.name}(${res.questionNum})`, + value: res.tag.slug, + } + }), + ) + return acc + }, []) + + const tagQuestion = { + type: 'list', + name: 'chooseTag', + message: '请选择标签', + choices: tagList, + pageSize: 30, + } + const chooseTag = await select(tagQuestion) + const allQuestion = await getAllQuestion() + // 未发现题目 所以先自动拉取题目 + if (!allQuestion?.length) { + logger.info('本地数据库未初始化,自动执行初始化流程,请稍等~') + try { + const allQuestionData = await getAllQuestionList() + await setAllQuestion(allQuestionData) + const newData = await getAllQuestion() + allQuestion.push(...newData) + } + catch (e) { + logger.error('初始化失败!终止.') + process.exit(0) + } + finally { + logger.info('本地数据库初始化完成.') + } + } + const tagQuestionList = allQuestion.filter(question => question.topicTags?.some(topic => topic.slug === chooseTag)) + if (!tagQuestionList?.length) { + logger.info('您选择的类型暂无可拉取题目~') + process.exit(0) + } + const createMode = await select({ + message: '拉题模式', + choices: [ + { name: '单个选择(不穩定)', value: 'single' }, + { name: '全部拉取(不穩定)', value: 'all' }, + ], + }) + if (createMode === 'single') { + const singleMode = { + type: 'list', + name: 'chooseTagQuestion', + message: '请选择题目', + choices: tagQuestionList.map(res => ({ + name: res.translatedTitle, + value: res.questionId, + })), + pageSize: 30, + } + + const singleChoice = await select(singleMode) + await createQuestionById(singleChoice, baseDir) + } + if (createMode === 'all') { + const dir = path.resolve(baseDir, chooseTag.toString()) + logger.off() + await getQuestionListCodeByTag(tagQuestionList, dir) + logger.on() + logger.info(`题目全部拉取完成: file://${dir}`) + } } export async function easyFinderView(baseDir = process.cwd()) { const choices = [ { name: '关键词搜索', value: 'keyword', description: '关键词描述' }, - { - name: 'hot 100列表查询', - value: 'hot', - description: '最受欢迎的100道题目' - } - // { name: '筛选模式', value: 'select', description: '筛选题目' } + { name: '学习计划', value: 'study', description: '企业和经典面试题目列表' }, + { name: '筛选模式', value: 'select', description: '筛选题目' }, ] const modeQuestion = { message: '请选择查找的模式?', - choices + choices, } const mode = await select(modeQuestion) const modeMap = { - hot: hotMode, + study: studyMode, keyword: keywordMode, - select: selectMode + select: selectMode, } await modeMap[mode](baseDir) } diff --git a/common/view/language.view.js b/common/view/language.view.js index 2828f1f..cbb4c3f 100644 --- a/common/view/language.view.js +++ b/common/view/language.view.js @@ -1,24 +1,21 @@ -import inquirer from 'inquirer' -import { - LANGUAGES, - setQuestionLanguage -} from '#common/utils/question-handler/questionLanguage.js' import { DefaultLang } from '#common/constants/question.const.js' +import { logger } from '#common/utils/logger/logger.js' +import { LANGUAGES, setQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js' +import inquirer from 'inquirer' export async function easyLanguageView(defaultLang = DefaultLang) { - const list = LANGUAGES.map((o) => o.name) + const list = LANGUAGES.map(o => o.name) const setQuestion = [ { type: 'list', name: 'newSet', - message: - '请确认你要设置CLI的语言环境(如果选项匹配成功,那么按下回车确认即可)', + message: '请确认你要设置CLI的语言环境(如果选项匹配成功,那么按下回车确认即可)', choices: list, - default: defaultLang - } + default: defaultLang, + }, ] const { newSet } = await inquirer.prompt(setQuestion, null) - console.log('设置语言环境为:', newSet) + logger.info('设置语言环境为:', newSet) await setQuestionLanguage(newSet) process.exit(0) } diff --git a/common/view/update.view.js b/common/view/update.view.js index 65cde1e..701e346 100644 --- a/common/view/update.view.js +++ b/common/view/update.view.js @@ -1,69 +1,33 @@ -import inquirer from 'inquirer' +import { logger } from '#common/utils/logger/logger.js' import { checkUpdate } from '#common/utils/update/update.js' -import { currentEnv } from '#common/utils/etc/checkEnv.js' -import { updateByEnv } from '#common/utils/update/updateByEnv.js' +import { updateCli } from '#common/utils/update/updateByEnv.js' +import inquirer from 'inquirer' export async function easyUpdateView() { - // 1. 询问当前的环境是啥 (自动检测一次) - // 检测到的当前环境 - const env = currentEnv() - const envQuestion = { - type: 'list', - name: 'choseEnv', - message: `自动检测到的环境为[ ${env} ],如果不是,请进行选择,如是,请按下回车确认.`, - choices: ['cli', 'project'], - default: env - } - const { choseEnv } = await inquirer.prompt(envQuestion, null) - // 2. 检测版本更新 - const { - localVersion, - npmVersion, - githubVersion, - isCliUpdate, - isGithubUpdate - } = await checkUpdate() - console.log( - `当前版本:[ ${localVersion} ] npm包最新版本:[ ${npmVersion} ] github版本:[ ${githubVersion} ]` - ) - let isUpdate = false - let version = '未知' - switch (choseEnv) { - case 'project': - isUpdate = isGithubUpdate - version = githubVersion - break - case 'cli': - isUpdate = isCliUpdate - version = npmVersion - break - default: - console.log('未知环境:', choseEnv) - process.exit(0) - break - } + const { localVersion = '未检出', npmVersion = '未检出', isCliUpdate } = await checkUpdate() + logger.info(`当前版本:[ ${localVersion} ] npm包最新版本:[ ${npmVersion} ]`) // 3. 询问是否更新 - if (isUpdate) { + if (isCliUpdate) { const checkQuestion = { type: 'confirm', name: 'willUpdate', - message: `检测到[ ${env} ]可更新版本[ ${version} ],是否进行更新?` + message: `检测到可更新版本[ ${npmVersion} ],是否进行更新?`, } const { willUpdate } = await inquirer.prompt(checkQuestion, null) if (willUpdate) { // 4.1 选择更新 - console.log('开始更新...') - await updateByEnv(env) - console.log('更新完成~祝你使用愉快~') - } else { + logger.info('开始更新...') + await updateCli() + logger.info('更新完成~祝你使用愉快~') + } + else { // 4.2 取消更新 - console.log( - '你选择跳过此次更新,如果想要进行更新,随时可以使用参数 -u 进行更新检测!祝你使用愉快~' - ) + logger.info('你选择跳过此次更新,如果想要进行更新,随时可以使用参数 -u 进行更新检测!祝你使用愉快~') } process.exit(0) - } else { - console.log('当前已是最新版本!祝你使用愉快~') + } + else { + logger.info('当前已是最新版本!祝你使用愉快~') process.exit(0) } } diff --git a/directory.md b/directory.md deleted file mode 100644 index 62acc61..0000000 --- a/directory.md +++ /dev/null @@ -1,16 +0,0 @@ -# 目录结构 - -```tree -. -├── bin # 指令入口目录 -├── common # 通用目录 -│ ├── resources # 通用资源目录 -│ ├── structures # 数据结构目录 -│ ├── utils # 通用工具目录 -│ └── view # 交互视图相关脚本 -├── coverage # 测试覆盖图目录 -├── resources # 资源目录(存放图片和一些静态内容) -├── scripts # 项目脚本存放目录 -├── src # 问题存放的默认目录 -└── test # 测试目录 -``` diff --git a/docs/README_CN.md b/docs/README_CN.md deleted file mode 100644 index 0958fbe..0000000 --- a/docs/README_CN.md +++ /dev/null @@ -1,499 +0,0 @@ -# Leetcode practice - -**中文文档**|[英文文档](../README.md)|[日文文档](./README_JP.md)|[韩文文档](./README_KR.md) - -## 简介 - -一句话介绍:“在编辑器中开始练习你的`leetcode`每日一题!” - -如果,你想要在编辑器中编写你的题解... - -如果,你想要简单快速的获取每日一题... - -如果,你想要创建你自己的题解仓库... - -那么,`leetcode-practice`将满足你的一切想要! - -## 预览 - - - -## 我应该怎么使用?(三种方案供你选择) - -### 方案 A : CLI (推荐使用) - -最好的也是最自由的使用方法是:在终端中使用我们的脚手架,通过三个核心指令:`lk`,`lf`,`lc`,来创建和检查你的题解。 - -[安装](<#一全局安装脚手架-(方案-A)>) · [使用](#CLI的使用) - -### 方案 B : fork (受支持的) - -你也可以使用`github`的`fork`功能来创建我们的项目副本,然后,直接使用项目内置指令进行题解的创建和检查。 - -[安装](<#二使用fork创建你自己的leetcode-practice仓库副本-(方案-B)>) · [使用](#fork项目的使用) - -### 方案 C : plugin (受支持的) - -你同样可以使用我们发布在插件市场的插件`leetcode-practice`来进行交互式的创建和检查题解。(支持两个主流编辑器:`WebStorm` 和 `VS Code`) - -[安装](<#三在编辑器的插件市场安装插件-(方案-C)>) · [使用](#插件的使用) - -## 预备条件 - -| 依赖包 | 版本 | -| ------ | ---- | -| nodejs | lts | -| git | lts | - -> note: nodejs:[nodejs安装向导](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs) -> -> git:[git下载地址](https://git-scm.com/downloads) - -## 安装 - -### 一.全局安装脚手架 (方案 A) - -你可以使用任意npm包管理软件(例如`npm`,`yarn`,`pnpm`等)的全局安装方法进行安装。 - -```shell -# 使用npm进行安装 -npm install -g leetcode-practice -# 使用pnpm进行安装 -pnpm install -g leetcode-practice -# 使用yarn进行安装 -yarn global install leetcode-practice -``` - -### 二.使用fork创建你自己的leetcode-practice仓库副本 (方案 B) - -#### 常规方法 - -1. 打开我们的项目地址:[leetcode-practice](https://github.com/wh131462/leetcode-practice) - - - -2. 点击`fork`按钮 - -你会看到这样的一个页面,然后修改仓库名和描述,确认勾选`Copy the master branch only` - - -3. 点击确认创建,等待创建 - - - -4. 创建完成,然后拉取这个仓库愉快地开始你的解题吧! - - - -#### 简便方法 - -1. 拉取我们的仓库到本地 - -```shell -git clone https://github.com/wh131462/leetcode-practice.git -``` - -2. 执行我们的部署脚本 - -```shell -# 使用你喜欢的包管理器进行执行脚本即可 -npm run easy-fork -``` - -3. 完成部署 - -### 三.在编辑器的插件市场安装插件 (方案 C) - -待开发... - -## 使用方法 - -### CLI的使用 - -#### 1.创建题解 - `lc` - -##### [1]. 获取今日题目 - [`-t`/`--today`] - -在终端中键入`lc`指令,即可默认在当前终端的工作区中获取今日的题目。 - -```shell -lc -# 完整指令 -lc -t -``` - -示例获取今日题目: - -```shell -# 例如当前执行目录为src目录 -➜ src git:(dev) ✗ lc -MODE: today -题目[2867.统计树中的合法路径数目]获取成功! -题目文件地址为:/home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js -``` - -##### [2]. 获取指定题目 - [`-i`/`--identity`] - -在终端中键入`lc`指令加上对应的题号,即可在当前工作区中获取指定题目。 - -```shell -lc 1314 -# 完整指令 -lc -i 1314 -# 使用双引号(")进行包裹 可以确保指定编号准确,对于带空格的题目编号尤其有用 -lc -i "LCP 50" -``` - -示例获取`LCP 50`: - -```shell -➜ src git:(dev) ✗ lc "LCP 50" -MODE: identity -题目[LCP 50.宝石补给]获取成功! -题目文件地址为:/home/wh131462/workspace/leetcode-practice/src/LCP 50.WHnhjV/index.js -``` - -##### [3]. 获取随机题目 - [`-r`/`--random`] - -在终端中键入`lc`指令加上参数`-r`,即可在当前工作区中获取随机题目,会优先获取不存在当前目录中的题目。 - -```shell -# 完整指令 -lc -r -``` - -示例获取随机题目: - -```shell -➜ src git:(dev) ✗ lc -r -MODE: random -题目[14.最长公共前缀]获取成功! -题目文件地址为:/home/wh131462/workspace/leetcode-practice/src/14.longest-common-prefix/index.js -``` - -##### [4]. 简单创建模式(交互式创建) - [`-e`/`--easy`] - -除了如上的使用精准的指令快速创建题目外,还可以使用简单创建模式来进行交互式创建。 - -```shell -lc -e -``` - -使用简单模式创建今日题目示例: - -```shell -➜ src git:(dev) ✗ lc -e -? 请选择创建问题的模式: today -? 是否在目录[ /home/wh131462/workspace/leetcode-practice/src ]下创建题目[ 2867.count-valid-paths-in-a-tree ]? Yes -题目[2867.count-valid-paths-in-a-tree]创建完成! -文件地址为: /home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js - -``` - -#### 2.检查题解 - `lk` - -##### [1]. 检查今日题解 [`-t`/`--today`] - -在终端中键入`lk`指令,即可在当前工作区中检查今日题解。 - -```shell -# 默认执行检查今日题解 -lk -# 完整指令 -lk -t -``` - -使用示例: - -```shell -# 指定了src目录为根目录 -workspace/leetcode-practice [dev●] » lk -d src -t -MODE: today -题目[2581.统计可能的树根数目]检测结果: -``` - -| index | 测量结果 | 预期结果 | 执行结果 | 执行用时 | 内存占用 | -| ----- | -------- | -------- | --------- | -------- | -------- | -| 0 | 未通过 | '3' | undefined | 0.0921ms | 2.52 KB | -| 1 | 通过 | '5' | undefined | 0.0119ms | 2.66 KB | - -> 点击跳转到题目提交:<https://leetcode.cn/problems/count-number-of-possible-root-nodes/> - -##### [2]. 检查指定题解 [`-i`/`--identity` + `<identity>`] - -在终端中键入`lk`指令,并输入题目编号,即可在当前工作区中检查指定题解。 - -```shell -# 检查指定题解 -lk 2581 -# 完整指令 -lk -i 2581 -# 带空格的编号 使用双引号包裹 -lk "LCP 50" -``` - -使用示例检查指定题解: - -```shell -workspace/leetcode-practice [dev●] » lk -d src 2581 -MODE: identity -题目[2581.统计可能的树根数目]检测结果: -``` - -| index | 测量结果 | 预期结果 | 执行结果 | 执行用时 | 内存占用 | -| ----- | -------- | -------- | -------- | -------- | -------- | -| 0 | 通过 | '3' | '3' | 0.1668ms | 2.52 KB | -| 1 | 通过 | '5' | '5' | 0.0234ms | 2.66 KB | - -> 点击跳转到题目提交:<https://leetcode.cn/problems/count-number-of-possible-root-nodes/> - -##### [3]. 检查随机获取的题解 [`-r`/`--random`] - -在终端中键入`lk`指令,使用参数`-r`,即可在当前工作区中检查上一个随机获取的题解。 - -```shell -# 完整指令 -lk -r -``` - -使用示例: - -```shell -workspace/leetcode-practice [dev●] » lk -r -MODE: random -题目[41.缺失的第一个正数]检测结果: -``` - -| index | 测量结果 | 预期结果 | 执行结果 | 执行用时 | 内存占用 | -| ----- | -------- | -------- | --------- | -------- | -------- | -| 0 | 未通过 | '3' | undefined | 0.0896ms | 2.42 KB | -| 1 | 未通过 | '2' | undefined | 0.0110ms | 2.56 KB | -| 2 | 未通过 | '1' | undefined | 0.0045ms | 2.56 KB | - -> 点击跳转到题目提交:<https://leetcode.cn/problems/first-missing-positive/> -> -> 注意:在执行此指令之前请务必先执行过,`lc -r`创建了随机题目。 - -##### [4]. 简单模式(交互式检查) [`-e`/`--easy`] - -在终端中键入`lk`指令,使用参数`-e`,即可使用交互式的进行题目检查。 - -```shell -# 完整指令 -lk -e -``` - -使用简单模式检测指定题目: - -```shell -workspace/leetcode-practice [dev●] » lk -e -? 请选择检查问题的模式: identity -? 请输入题目编号: 41 -? 是否检测当前目录[ /Users/mac-106/wh131462/workspace/leetcode-practice ]下的题目[ 41.first-missing-positive ]? Yes -``` - -| index | 测量结果 | 预期结果 | 执行结果 | 执行用时 | 内存占用 | -| ----- | -------- | -------- | --------- | -------- | -------- | -| 0 | 未通过 | '3' | undefined | 0.0969ms | 2.42 KB | -| 1 | 未通过 | '2' | undefined | 0.0139ms | 2.56 KB | -| 2 | 未通过 | '1' | undefined | 0.0051ms | 2.56 KB | - -> 点击跳转到题目提交:<https://leetcode.cn/problems/first-missing-positive/> -> 题目[41.first-missing-positive]检查完成! -> 文件地址为: /Users/mac-106/wh131462/workspace/leetcode-practice/41.first-missing-positive/index.js - -#### 3.题目查找 - `lf` - -待开发... - -##### [1]. 查看题目列表[待开发] - -#### 4.通用参数 - -##### [1]. 获取或指定当前编程语言 - [`-l`/`-language` [language]] - -可以通过`-l`不带参数来获取当前的编程语言设定,也可以通过指定语言参数将当前cli的语言环境设定为指定的语言。 - -```shell -# 此参数在 lc/lk/lf 中的表现一致 -lc -l -lk -l java -``` - -使用示例: - -```shell -# 获取语言环境 -➜ leetcode-practice git:(dev) ✗ lc -l -当前CLI语言环境为:javascript -# 更改语言环境 -➜ leetcode-practice git:(dev) ✗ lc -l java -? 请确认你要设置CLI的语言环境(如果选项匹配成功,那么按下回车确认即可) java -设置语言环境为: java - -``` - -> 注意: 在这个环境下无法执行检测测试用例。 - -##### [2]. 指定目录 - [`-d`/`-directory`] - -`创建`和`检查`指令还可以使用参数`-d`来指定基于当前工作目录的相对地址作为指定目录。 -当指定目录后会在指定目录中进行创建或者检查操作。 - -```shell -# 指定当前目录的子目录src作为生成目录 -lc -d src -t -# 指定当前目录的子目录src作为检查目录 -lk -d src -i -``` - -使用示例: - -```shell -➜ src git:(dev) ✗ lc -d src -t -MODE: today -题目[2867.统计树中的合法路径数目]获取成功! -题目文件地址为:/home/wh131462/workspace/leetcode-practice/src/src/2867.count-valid-paths-in-a-tree/index.js -``` - -> 注意: 如果指定的目录不存在,会自动生成一个空目录进行创建。 - -##### [3]. 检查版本号 [`-V`/`--version`] - -```shell -# 查看lc版本 -lc -V -# 查看lk版本 -lk -V -# 查看lf版本 -lf -V -``` - -查看lc版本示例: - -```shell -workspace/leetcode-practice [dev●] » lc -V -0.0.0 -``` - -##### [4]. 更新检测 [`-u`/`--update`] - -使用`-u`或者`--update`参数可以检测当前版本是否为最新版本,如果当前版本不是最新版本,会提示用户是否进行更新. - -```shell -lk -u -lf -u -lc -u -``` - -```shell -? 自动检测到的环境为[ project ],如果不是,请进行选择,如是,请按下回车确认. project -开始获取npm仓库中的版本号... -npm仓库中的版本号获取成功! -开始获取github仓库的版本号... -github仓库的版本号获取成功! -开始获取本地版本号... -本地版本号获取成功! -当前版本:[ 1.0.0 ] npm包最新版本:[ 1.0.1 ] github版本:[ 1.0.1 ] -? 检测到[ project ]可更新版本[ 1.0.1 ],是否进行更新? (Y/n) Yes -更新完成~祝你使用愉快~ -``` - -### fork项目的使用 - -#### [0]. 安装依赖 - -在使用之前,先使用包管理工具进行依赖的安装. - -```shell -# 安装依赖 -npm install -# 或者 使用yarn (你可以使用任意一种你喜欢的包管理工具) -yarn -``` - -fork项目中的指令,使用上和脚手架CLI的使用参数是一致的,只不过需要通过`npm run`类似的包管理工具执行命令来执行脚本. - -> 注意:在项目中的脚本,和脚手架的唯一区别就是默认指定了`-d`参数,指向了项目根目录的`src`目录,所以所有的指令都是在src中默认执行的. - -#### [1]. 创建题解 [`lc`] - -参数参考cli的`lc`部分: [lc](#1创建题解---lc) - -简单使用示例: - -```shell -# 使用yarn执行 -yarn lc 1314 -``` - -执行结果: - -```shell -# 会在src目录下进行生成 -> yarn lc 1314 -yarn run v1.22.19 -$ node bin/lc.js -d src 1314 -MODE: identity -题目[1314.矩阵区域和]获取成功! -题目文件地址为:/Users/mac-106/wh131462/workspace/leetcode-practice/src/1314.matrix-block-sum/index.js -✨ Done in 1.06s. -``` - -#### [2]. 检查题解 [`lk`] - -参数参考cli的`lk`部分: [lk](#2检查题解---lk) - -简单使用示例: - -```shell -# 使用yarn执行 -yarn lk 1314 -``` - -执行结果: - -```shell -# 会在src目录下进行检查 -> yarn lk 1314 -yarn run v1.22.19 -$ node bin/lk.js -d src 1314 -MODE: identity -题目[1314.矩阵区域和]检测结果: -``` - -| index | 测量结果 | 预期结果 | 执行结果 | 执行用时 | 内存占用 | -| ----- | -------- | ------------------------------------ | --------- | -------- | -------- | -| 0 | 未通过 | '[[12,21,16],[27,45,33],[24,39,28]]' | undefined | 0.1487ms | 2.47 KB | -| 1 | 未通过 | '[[45,45,45],[45,45,45],[45,45,45]]' | undefined | 0.0278ms | 2.61 KB | - -> 点击跳转到题目提交:<https://leetcode.cn/problems/matrix-block-sum/> -> ✨ Done in 1.13s. - -#### [3]. 查找题解 [`lf`] - -参数参考cli的`lf`部分: [lf](#3题目查找---lf) - -待开发... - -#### [4]. 更新 [`update`] - -特定更新本地项目的脚本,会更新所有的非src目录,用以同步项目最新特性. - -> 注意: 如果你有自己的优化更改代码,这一步请谨慎操作! 请参考我们的[特殊情况下的升级方案](./update.md)! - -### 插件的使用 - -待开发... - -## 贡献者 - -[<img src="https://avatars.githubusercontent.com/u/48346853" style="border-radius:50%;" width="30" height="30" alt="EternalHeart"/>](https://github.com/wh131462) -[<img src="https://avatars.githubusercontent.com/u/61453917" style="border-radius:50%;" width="30" height="30" alt="SmartTeddy"/>](https://github.com/SmallTeddy) -[<img src="https://avatars.githubusercontent.com/u/35305691" style="border-radius:50%;" width="30" height="30" alt="Hedwig-Fang"/>](https://github.com/Hedwig-Fang) - -## 使用反馈 - -如果有使用上的`问题`,或者一些`好的建议`,可以加我们的`使用反馈群`进行`反馈`!我们会及时处理! - - diff --git a/docs/README_JP.md b/docs/README_JP.md deleted file mode 100644 index e70d186..0000000 --- a/docs/README_JP.md +++ /dev/null @@ -1,509 +0,0 @@ -# Leetcode practice - -[中文文件](./README_CN.md)|[英文文件](../README.md)|**日本語ファイル**|[韓国語ファイル](./README_KR.md) - -## はじめに - -一言で言うと:"エディタで LeetCode のデイリー問題を練習しよう!" - -もし、あなたがエディタで問題を解きたい場合... - -もし、毎日の問題を簡単に取得したい場合... - -もし、独自の解決策リポジトリを作成したい場合... - -そうであれば、leetcode-practiceがあなたのすべての要望を叶えます! - -## プレビュー - - - -## どのように使うか?(3つの選択肢) - -### 選択肢 A: CLI(推奨) - -最も自由度が高く、使いやすい方法は、ターミナルで `lk`, `lf`, `lc` の3つの主要コマンドを使って問題を作成し、チェックすることです。 - -[インストール](<#一全局インストールスクリプト-(オプション-A)>) · [使用](#CLIの使用) - -### 選択肢 B: フォーク(サポートされています) - -GitHubのフォーク機能を使用して、プロジェクトのコピーを作成し、プロジェクト内の指示に従って問題を作成およびチェックします。 - -[インストール](<#二フォークを使用して独自のleetcode-practiceリポジトリのコピーを作成する-(オプション-B)>) · [使用](#プロジェクトのフォークの使用) - -### 選択肢 C: プラグイン(サポートされています) - -インタラクティブに問題を作成し、チェックするために、插件市場に公開されている`leetcode-practice`プラグインを使用することもできます。(主要な2つのエディタ `WebStorm` と `VS Code` に対応) - -[インストール](<#三エディタのプラグイン市場にプラグインをインストールする-(オプション-C)>) · [使用](#プラグインの使用) - -## 準備条件 - -| 必要なパッケージ | バージョン | -| ---------------- | ---------- | -| nodejs | lts | -| git | lts | - -> メモ:nodejs:[nodejsのインストールガイド](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs) -> -> git:[gitダウンロードリンク](https://git-scm.com/downloads) - -## インストール - -### 一.全局インストールスクリプト (オプション A) - -npm、yarn、pnpmなどの任意のnpmパッケージ管理ソフトウェアを使用して、グローバルインストールメソッドを使用してインストールできます。 - -```shell -# npmを使用してインストール -npm install -g leetcode-practice -# pnpmを使用してインストール -pnpm install -g leetcode-practice -# yarnを使用してインストール -yarn global install leetcode-practice -``` - -### 二.フォークを使用して独自のleetcode-practiceリポジトリのコピーを作成する (オプション B) - -#### 標準的な方法 - -1. 当社のプロジェクトのURLを開きます:[leetcode-practice](https://github.com/wh131462/leetcode-practice) - - - -2. `フォーク` ボタンをクリックします。 - -次のようなページが表示されます。そして、リポジトリ名と説明を変更し、「マスターブランチのみをコピーする」を選択してください。 - - -3. 作成を確認して待機してください。 - - - -4. 作成が完了したら、このリポジトリをクローンして、楽しい問題解決を開始できます! - - - -#### 簡単な方法 - -1. 当社のリポジトリをローカルにクローンします。 - -```shell -git clone https://github.com/wh131462/leetcode-practice.git -``` - -2. 当社のデプロイスクリプトを実行します。 - -```shell -# 使用するパッケージマネージャに従ってスクリプトを実行してください -npm run easy-fork -``` - -3. 完了したら、デプロイが完了します - -### 三.エディタのプラグイン市場にプラグインをインストールする (オプション C) - -まだ開発中... - -## 使い方 - -### CLIの使用 - -#### 1.問題の作成 - `lc` - -##### [1]. 今日の問題の取得 - [`-t`/`--today`] - -ターミナルに `lc` コマンドを入力すると、デフォルトで今日の問題を現在のターミナルの作業ディレクトリに取得します。 - -```shell -lc -# フルコマンド -lc -t -``` - -今日の問題の取得の例: - -```shell -# たとえば、現在の実行ディレクトリがsrcディレクトリの場合 -➜ src git:(dev) ✗ lc -MODE: - - today -問題[2867.統計ツリー内の有効なパスの数]が取得されました! -問題ファイルの場所は:/home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js -``` - -##### [2]. 特定の問題の取得 - [`-i`/`--identity`] - -ターミナルに `lc` コマンドに対応する問題番号を入力すると、指定された問題を現在の作業ディレクトリに取得します。 - -```shell -lc 1314 -# フルコマンド -lc -i 1314 -# ダブルクオーテーション(")で囲むと、指定された番号が正確に指定され、特にスペースが含まれる問題番号に特に便利です。 -lc -i "LCP 50" -``` - -`LCP 50` の取得の例: - -```shell -➜ src git:(dev) ✗ lc "LCP 50" -MODE: identity -問題[LCP 50.宝石の供給]が取得されました! -問題ファイルの場所は:/home/wh131462/workspace/leetcode-practice/src/LCP 50.WHnhjV/index.js -``` - -##### [3]. ランダムな問題の取得 - [`-r`/`--random`] - -ターミナルに `lc` コマンドに `-r` パラメータを追加すると、ランダムな問題を取得し、現在のディレクトリに優先的に存在しない問題を取得します。 - -```shell -# フルコマンド -lc -r -``` - -ランダムな問題の取得の例: - -```shell -➜ src git:(dev) ✗ lc -r -MODE: random -問題[14.最長共通接頭辞]が取得されました! -問題ファイルの場所は:/home/wh131462/workspace/leetcode-practice/src/14.longest-common-prefix/index.js -``` - -##### [4]. 簡易作成モード(対話形式で作成) - [`-e`/`--easy`] - -正確な指示を使用して問題を素早く作成するだけでなく、簡単な作成モードを使用して対話形式で作成することもできます。 - -```shell -lc -e -``` - -簡易モードで今日の問題を作成する例: - -```shell -➜ src git:(dev) ✗ lc -e -? 問題の作成モードを選択してください: today -? ディレクトリ[ /home/wh131462/workspace/leetcode-practice/src ]に問題[ 2867.count-valid-paths-in-a-tree ]を作成しますか? Yes -問題[2867.count-valid-paths-in-a-tree]の作成が完了しました! -ファイルの場所は: /home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js -``` - -#### 2.問題のチェック - `lk` - -##### [1]. 今日の解答をチェックする [`-t`/`--today`] - -`lk` コマンドをターミナルに入力すると、現在の作業ディレクトリで今日の解答をチェックします。 - -```shell -# デフォルトで今日の解答をチェック -lk -# フルコマンド -lk -t -``` - -使用例: - -```shell -# ディレクトリsrcをルートディレクトリとして指定している -workspace/leetcode-practice [dev●] » lk -d src -t -MODE: today -問題[2581.可能なツリールートの数を数える]のチェック結果: -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ テスト結果 │ 期待結果 │ 実行結果 │ 実行時間 │ メモリ使用量 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '不合格' │ '3' │ undefined │ '0.0921ms' │ '2.52 KB' │ -│ 1 │ '不合格' │ '5' │ undefined │ '0.0119ms' │ '2.66 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -問題の提出ページに移動するにはここをクリックしてください:https://leetcode-cn/problems/count-number-of-possible-root-nodes/ -``` - -##### [2]. 特定の解答をチェックする [`-i`/`--identity` + `<identity>`] - -上記のコマンドを使って、`lk`をターミナルに入力し、問題番号を入力すると、指定された問題の解答を現在の作業スペースで確認できます。 - -例えば: - -```shell -# 指定された問題の解答を確認する -lk 2581 -# 完全なコマンド -lk -i 2581 -# スペースが含まれる番号はダブルクォーテーションで囲む -lk "LCP 50" -``` - -解答を確認する例: - -```shell -workspace/leetcode-practice [dev●] » lk -d src 2581 -MODE: identity -問題[2581.可能な根の数を数える]の検査結果: -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ テスト結果 │ 期待結果 │ 実行結果 │ 実行時間 │ メモリ使用量 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '合格' │ '3' │ '3' │ '0.1668ms' │ '2.52 KB' │ -│ 1 │ '合格' │ '5' │ '5' │ '0.0234ms' │ '2.66 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -問題の提出にジャンプする:https://leetcode.cn/problems/count-number-of-possible-root-nodes/ -``` - -#### [3]. ランダムな解答を確認する [`-r`/`--random`] - -`lk`をターミナルに入力し、`-r`オプションを使用すると、直前にランダムに取得した解答を現在の作業スペースで確認できます。 - -例えば: - -```shell -# 完全なコマンド -lk -r -``` - -使用例: - -```shell -workspace/leetcode-practice [dev●] » lk -r -MODE: random -問題[41.最初の不足している正の数]の検査結果: -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ テスト結果 │ 期待結果 │ 実行結果 │ 実行時間 │ メモリ使用量 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '不合格' │ '3' │ undefined │ '0.0896ms' │ '2.42 KB' │ -│ 1 │ '不合格' │ '2' │ undefined │ '0.0110ms' │ '2.56 KB' │ -│ 2 │ '不合格' │ '1' │ undefined │ '0.0045ms' │ '2.56 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -問題の提出にジャンプする:https://leetcode.cn/problems/first-missing-positive/ -``` - -> 注意: このコマンドを実行する前に、`lc -r`を実行してランダムな問題を作成してください。 - -#### [4]. 簡易モード(対話式確認) [`-e`/`--easy`] - -`lk`をターミナルに入力し、`-e`オプションを使用すると、対話式で問題を確認できます。 - -例えば: - -```shell -# 完全なコマンド -lk -e -``` - -簡易モードで指定された問題を確認する例: - -```shell -workspace/leetcode-practice [dev●] » lk -e -? モードを選択してください: identity -? 問題番号を入力してください: 41 -? 現在のディレクトリ[ /Users/mac-106/wh131462/workspace/leetcode-practice ]で問題[ 41.first-missing-positive ]を確認しますか? Yes -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ テスト結果 │ 期待結果 │ 実行結果 │ 実行時間 │ メモリ使用量 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '不合格' │ '3' │ undefined │ '0.0969ms' │ '2.42 KB' │ -│ 1 │ '不合格' │ '2' │ undefined │ '0.0139ms' │ '2.56 KB' │ -│ 2 │ '不合格' │ '1' │ undefined │ '0.0051ms' │ '2.56 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -問題の提出にジャンプする:https://leetcode.cn/problems/first-missing-positive/ -問題[41.first-missing-positive]の確認が完了しました! -ファイルの場所: /Users/mac-106/wh131462/workspace/leetcode-practice/41.first-missing-positive/index.js -``` - -#### 3.問題検索 - `lf` - -開発中... - -#### 4.一般的なオプション - -##### [1]. 現在のプログラミング言語の取得または指定 - [`-l`/`-language` [language]] - -`-l`を引数なしで使用すると、現在のプログラミング言語の設定を取得できます。また、言語のパラメータを指定することで、現在のCLIの言語環境を指定の言語に設定することもできます。 - -```shell -# このパラメータは lc/lk/lf で同様の動作をします -lc -l -lk -l java -``` - -使用例: - -```shell -# 言語環境の取得 -➜ leetcode-practice git:(dev) ✗ lc -l -現在のCLIの言語環境は:javascript -# 言語環境の変更 -➜ leetcode-practice git:(dev) ✗ lc -l java -? CLIの言語環境を設定してください (オプションが一致した場合、Enterキーを押して確認してください) java -言語環境が設定されました: java - -``` - -> 注意: この環境ではテストケースの実行はできません。 - -##### [2]. ディレクトリを指定する - [`-d`/`-directory`] - -`-d`オプ - -ションを使用して、作業ディレクトリの相対パスを指定ディレクトリとして使用できます。指定ディレクトリ内での作成または確認操作が行われます。 - -例えば: - -```shell -# srcディレクトリを指定して生成 -lc -d src -t -# srcディレクトリを指定して確認 -lk -d src -i -``` - -使用例: - -```shell -➜ src git:(dev) ✗ lc -d src -t -MODE: today -問題[2867.木の有効なパスの数を数える]を取得しました! -問題のファイルの場所:/home/wh131462/workspace/leetcode-practice/src/src/2867.count-valid-paths-in-a-tree/index.js -``` - -> 注意: 指定したディレクトリが存在しない場合、空のディレクトリが作成されます。 - -##### [3]. バージョンを確認する [`-V`/`--version`] - -```shell -# lcのバージョンを確認する -lc -V -# lkのバージョンを確認する -lk -V -# lfのバージョンを確認する -lf -V -``` - -lcのバージョンを確認する例: - -```shell -workspace/leetcode-practice [dev●] » lc -V -0.0.0 -``` - -##### [4]. 更新をチェックする [`-u`/`--update`] - -`-u`または`--update`オプションを使用すると、現在のバージョンが最新バージョンでないかどうかをチェックできます。現在のバージョンが最新バージョンでない場合、更新を行うかどうかをユーザーに確認します。 - -```shell -lk -u -lf -u -lc -u -``` - -```shell -? 自動検出された環境は[ プロジェクト ]です。もしそうでない場合は選択してください。そうであれば、Enterを押して確認してください。 project -npmリポジトリのバージョン番号の取得を開始します... -npmリポジトリのバージョン番号の取得が完了しました! -githubリポジトリのバージョン番号の取得を開始します... -githubリポジトリのバージョン番号の取得が完了しました! -ローカルバージョン番号の取得を開始します... -ローカルバージョン番号の取得が完了しました! -現在のバージョン:[ 1.0.0 ] npmパッケージの最新バージョン:[ 1.0.1 ] GitHubのバージョン:[ 1.0.1 ] -? [ プロジェクト ]でアップデート可能なバージョン[ 1.0.1 ]が検出されました。アップデートしますか? (Y/n) Yes -更新が完了しました。お楽しみください! -``` - -### プロジェクトのフォークの使用 - -##### [0]. 依存関係のインストール - -使用する前に、依存関係のインストールを行います。 - -```shell -# 依存関係のインストール -npm install -# または、yarnを使用する(お好みのパッケージ管理ツールを使用できます) -yarn -``` - -プロジェクト内のコマンドは、CLIの使用と同じようにパラメータを指定して実行されますが、`npm run`などのパッケージ管理ツールを使用してスクリプトを実行する必要があります。 - -> 注意: プロジェクト内のスクリプトは、デフォルトで`-d`パラメータが設定されており、プロジェクトのルートディレクトリの`src`ディレクトリを指すようになっています。そのため、すべてのコマンドはデフォルトでsrc内で実行されます。 - -##### [1]. 解答を作成する [`lc`] - -パラメータはCLIの`lc`部分を参照してください: [lc](#1問題の作成---lc) - -例: - -```shell -# yarnで実行 -yarn lc 1314 -``` - -実行結果: - -```shell -# srcディレクトリ内で生成されます -> yarn lc 1314 -yarn run v1.22.19 -$ node bin/lc.js -d src 1314 -MODE: identity -問題[1314.マトリックスブロック和]を取得しました! -問題のファイルの場所:/Users/mac-106/wh131462/workspace/leetcode-practice/src/1314.matrix-block-sum/index.js -✨ Done in 1.06s. -``` - -##### [2]. 解答を確認する [`lk`] - -パラメータはCLIの`lk`部分を参照してください: [lk](#2問題のチェック---lk) - -例: - -```shell -# yarnで実行 -yarn lk 1314 -``` - -実行結果: - -```shell -# srcディレクトリ内で確認されます -> yarn lk 1314 -yarn run v1.22.19 -$ node bin/lk.js -d src 1314 -MODE: identity -問題[1314.マトリックスブロック和]の検査結果: -┌─────────┬──────────┬──────────────────────────────────────┬───────────┬────────────┬───────────┐ -│ (index) │ テスト結果 │ 期待結果 │ 実行結果 │ 実行時間 │ メモリ使用量 │ -├──────── - -─┼──────────┼──────────────────────────────────────┼───────────┼────────────┼───────────┤ -│ 0 │ '不合格' │ '[[12,21,16],[27,45,33],[24,39,28]]' │ undefined │ '0.1487ms' │ '2.47 KB' │ -│ 1 │ '不合格' │ '[[45,45,45],[45,45,45],[45,45,45]]' │ undefined │ '0.0278ms' │ '2.61 KB' │ -└─────────┴──────────┴──────────────────────────────────────┴───────────┴────────────┴───────────┘ -問題の提出にジャンプする:https://leetcode.cn/problems/matrix-block-sum/ -✨ Done in 1.13s. -``` - -##### [3]. 解答を検索する [`lf`] - -パラメータはCLIの`lf`部分を参照してください: [lf](#3問題検索---lf) - -開発中... - -##### [4]. アップデート [`update`] - -プロジェクトのローカルファイルを更新する特定のスクリプトです。プロジェクトの最新機能を同期するために、srcディレクトリ以外のすべてのディレクトリが更新されます。 - -> 注意: 自分で最適化や変更を加えたコードがある場合は、このステップを慎重に行ってくださいを参照してください! - -### プラグインの使用 - -開発中... - -## 貢献者 - -[<img src="https://avatars.githubusercontent.com/u/48346853" style="border-radius:50%;" width="30" height="30" alt="EternalHeart"/>](https://github.com/wh131462) -[<img src="https://avatars.githubusercontent.com/u/61453917" style="border-radius:50%;" width="30" height="30" alt="SmartTeddy"/>](https://github.com/SmallTeddy) -[<img src="https://avatars.githubusercontent.com/u/35305691" style="border-radius:50%;" width="30" height="30" alt="Hedwig-Fang"/>](https://github.com/Hedwig-Fang) - -## フィードバック - -もし何か`問題`があったり、`素晴らしい提案`があれば、お気軽に`フィードバックグループ`にご参加いただき、`フィードバック`を提供してください!私たちは迅速に対処いたします! - - diff --git a/docs/README_KR.md b/docs/README_KR.md deleted file mode 100644 index 5fc660a..0000000 --- a/docs/README_KR.md +++ /dev/null @@ -1,503 +0,0 @@ -# Leetcode practice - -[중국어 문서](./README_CN.md)|[영어 문서](../README.md)|[일본어 문서](./README_JP.md)|**한국어 문서** - -## 소개 - -한 문장으로 설명하면: "에디터에서 `LeetCode` 매일 한 문제를 연습하세요!" - -만약 당신이 에디터에서 당신의 문제 해결을 작성하고 싶다면... - -만약 당신이 매일 한 문제를 간편하고 빠르게 받고 싶다면... - -만약 당신이 자신의 문제 해결 저장소를 만들고 싶다면... - -그러면 `LeetCode 연습`이 당신의 모든 요구를 충족시켜줄 것입니다! - -## 미리보기 - - - -## 어떻게 사용할까요? (3가지 옵션) - -### 옵션 A: CLI (추천) - -가장 좋고 자유로운 사용 방법은 터미널에서 우리의 스캐폴딩을 사용하여 세 가지 핵심 명령어 `lk`, `lf`, `lc`를 사용하여 당신의 문제를 생성하고 검사하는 것입니다. - -[설치](<#전역-스캐폴딩-설치-(옵션-A)>) · [사용](#CLI의-사용) - -### 옵션 B: fork (지원됨) - -`github`의 `fork` 기능을 사용하여 프로젝트의 복제본을 만들고, 프로젝트 내부 명령을 사용하여 문제를 생성하고 검사할 수 있습니다. - -[설치](<#fork를-사용하여-나만의-Leetcode-연습-저장소-복제-(옵션-B)>) · [사용](#fork-프로젝트의-사용) - -### 옵션 C: 플러그인 (지원됨) - -플러그인 시장에서 배포된 `LeetCode 연습` 플러그인을 사용하여 대화 형으로 문제를 생성하고 검사할 수도 있습니다. (`WebStorm` 및 `VS Code`와 같은 두 가지 주요 편집기를 지원합니다.) - -[설치](<#플러그인-마켓에서-플러그인-설치-(옵션-C)>) · [사용](#플러그인의-사용) - -## 준비 사항 - -| 의존성 패키지 | 버전 | -| ------------- | ---- | -| nodejs | lts | -| git | lts | - -> 참고: nodejs:[nodejs 설치 안내](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs) -> -> git:[git 다운로드 링크](https://git-scm.com/downloads) - -## 설치 - -### 전역 스캐폴딩 설치 (옵션 A) - -원하는 npm 패키지 관리 소프트웨어(예: `npm`, `yarn`, `pnpm` 등)를 사용하여 전역 설치를 수행할 수 있습니다. - -```shell -# npm을 사용하여 설치 -npm install -g leetcode-practice -# pnpm을 사용하여 설치 -pnpm install -g leetcode-practice -# yarn을 사용하여 설치 -yarn global install leetcode-practice -``` - -### fork를 사용하여 나만의 Leetcode 연습 저장소 복제 (옵션 B) - -#### 일반적인 방법 - -1. 우리의 프로젝트 주소를 엽니다: [Leetcode 연습](https://github.com/wh131462/leetcode-practice) - - - -2. `fork` 버튼을 클릭합니다. - -다음과 같은 페이지가 표시됩니다. 그런 다음 리포지토리 이름과 설명을 수정하고, `Copy the master branch only`를 선택하십시오. - - - -3. 확인하여 생성을 기다립니다. - - - -4. 생성이 완료되면 리포지토리를 가져와서 문제 해결을 시작할 수 있습니다! - - - -#### 간편한 방법 - -1. 로컬로 리포지토리를 가져옵니다. - -```shell -git clone https://github.com/wh131462/leetcode-practice.git -``` - -2. 배포 스크립트를 실행합니다. - -```shell -# 원하는 패키지 관리자로 스크립트를 실행하십시오. -npm run easy-fork -``` - -3. 배포 완료 - -### 플러그인 마켓에서 플러그인 설치 (옵션 C) - -개발 중... - -## 사용법 - -### CLI의 사용 - -#### 1. 문제 생성 - `lc` - -##### [1]. 오늘의 문제 가져오기 - [`-t`/`--today`] - -터미널에서 `lc` 명령어를 입력하면 현재 터미널 작업 영역에 오늘의 문제가 기본적으로 가져와집니다. - -```shell -lc -# 완전한 명령어 -lc -t -``` - -오늘의 문제 가져오기 예시: - -```shell -# 예를 들어 현재 실행 디렉토리가 src 디렉토리인 경우 -➜ src git:(dev) ✗ lc -MODE: today -문제[2867.통계 트리에서 유효한 경로 수 세기] 가져오기 성공! -문제 파일 주소는: /home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js -``` - -##### [2]. 특정 문제 가져 - -오기 - [`-i`/`--identity`] - -터미널에서 `lc` 명령어 다음에 해당 문제 번호를 입력하면 현재 작업 영역에서 해당 문제를 가져옵니다. - -```shell -lc 1314 -# 완전한 명령어 -lc -i 1314 -# 큰따옴표(")를 사용하여 번호를 둘러싸면 문제 번호를 정확하게 지정할 수 있습니다. 특히 공백이 포함된 문제 번호의 경우에 유용합니다. -lc -i "LCP 50" -``` - -특정 문제 가져오기 예시: - -```shell -➜ src git:(dev) ✗ lc "LCP 50" -MODE: identity -문제[LCP 50.보석 공급] 가져오기 성공! -문제 파일 주소는: /home/wh131462/workspace/leetcode-practice/src/LCP 50.WHnhjV/index.js -``` - -##### [3]. 무작위 문제 가져오기 - [`-r`/`--random`] - -터미널에서 `lc` 명령어 뒤에 `-r` 매개변수를 추가하면 현재 작업 영역에서 무작위 문제를 가져옵니다. 현재 디렉토리에 문제가 없는 경우 우선적으로 가져옵니다. - -```shell -# 완전한 명령어 -lc -r -``` - -무작위 문제 가져오기 예시: - -```shell -➜ src git:(dev) ✗ lc -r -MODE: random -문제[14.가장 긴 공통 접두사] 가져오기 성공! -문제 파일 주소는: /home/wh131462/workspace/leetcode-practice/src/14.longest-common-prefix/index.js -``` - -##### [4]. 간편 생성 모드(대화형 생성) - [`-e`/`--easy`] - -정확한 명령어를 사용하여 빠르게 문제를 생성하는 것 외에도 간단한 생성 모드를 사용하여 대화형으로 문제를 생성할 수도 있습니다. - -```shell -lc -e -``` - -간단한 모드를 사용하여 오늘의 문제 만들기 예시: - -```shell -➜ src git:(dev) ✗ lc -e -? 문제 생성 모드를 선택하십시오: today -? 디렉토리 [ /home/wh131462/workspace/leetcode-practice/src ]에서 문제 [ 2867.count-valid-paths-in-a-tree ]를 만드시겠습니까? Yes -문제[2867.count-valid-paths-in-a-tree] 생성 완료! -파일 주소는: /home/wh131462/workspace/leetcode-practice/src/2867.count-valid-paths-in-a-tree/index.js - -``` - -#### 2. 문제 검사 - `lk` - -##### [1]. 오늘의 문제 검사 [`-t`/`--today`] - -터미널에서 `lk` 명령어를 입력하면 현재 작업 영역에서 오늘의 문제를 검사합니다. - -```shell -# 기본적으로 오늘의 문제를 검사합니다. -lk -# 완전한 명령어 -lk -t -``` - -사용 예시: - -```shell -# src 디렉토리가 루트 디렉토리로 지정되었습니다. -workspace/leetcode-practice [dev●] » lk -d src -t -MODE: today -문제[2581.가능한 트리 루트 수를 세는 것] 검사 결과: -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ 테스트 결과 │ 예상 결과 │ 실행 결과 │ 실행 시간 │ 메모리 사용량 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '미통과' │ '3' │ undefined │ '0.0921ms' │ '2.52 KB' │ -│ 1 │ '미통과' │ '5' │ undefined │ '0.0119ms' │ '2.66 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -문제 제출로 이동하려면 클릭하십시오: https://leetcode-cn/problems/count-number-of-possible-root-nodes/ -``` - -##### [2]. 특정 문제 검사 [`-i`/`--identity` + `<identity>`] - -터미널에서 `lk` 명령어를 입력하고 문제 번호를 입력하면 현재 작업 영역에서 해당 문제를 검사합니다. - -```shell -# 특정 문제 검사 -lk 2581 -# 완전한 명령어 -lk -i 2581 -# 큰따옴표(")를 사용하여 번호를 둘러싸면 문제 번호 - -를 정확하게 지정할 수 있습니다. 특히 공백이 포함된 문제 번호의 경우에 유용합니다. -lk "LCP 50" -``` - -특정 문제 검사 사용 예시: - -```shell -workspace/leetcode-practice [dev●] » lk -d src 2581 -MODE: identity -문제[2581.가능한 트리 루트 수를 세는 것] 검사 결과: -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ 테스트 결과 │ 예상 결과 │ 실행 결과 │ 실행 시간 │ 메모리 사용량 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '통과' │ '3' │ '3' │ '0.1668ms' │ '2.52 KB' │ -│ 1 │ '통과' │ '5' │ '5' │ '0.0234ms' │ '2.66 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -문제 제출로 이동하려면 클릭하십시오: https://leetcode-cn/problems/count-number-of-possible-root-nodes/ -``` - -##### [3]. 무작위로 가져온 문제 검사 [`-r`/`--random`] - -터미널에서 `lk` 명령어를 입력하고 `-r` 매개변수를 사용하면 최근에 가져온 무작위 문제를 현재 작업 영역에서 검사합니다. - -```shell -# 완전한 명령어 -lk -r -``` - -사용 예시: - -```shell -workspace/leetcode-practice [dev●] » lk -r -MODE: random -문제[41.누락된 첫 번째 양의 정수] 검사 결과: -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ 테스트 결과 │ 예상 결과 │ 실행 결과 │ 실행 시간 │ 메모리 사용량 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '미통과' │ '3' │ undefined │ '0.0896ms' │ '2.42 KB' │ -│ 1 │ '미통과' │ '2' │ undefined │ '0.0110ms' │ '2.56 KB' │ -│ 2 │ '미통과' │ '1' │ undefined │ '0.0045ms' │ '2.56 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -문제 제출로 이동하려면 클릭하십시오: https://leetcode-cn/problems/first-missing-positive/ -``` - -> 참고: 이 명령을 실행하기 전에 반드시 `lc -r`을 실행하여 무작위 문제를 만들어야 합니다. - -##### [4]. 간편 모드(대화형 검사) [`-e`/`--easy`] - -터미널에서 `lk` 명령어를 입력하고 `-e` 매개변수를 사용하면 대화형으로 문제를 검사할 수 있습니다. - -```shell -# 완전한 명령어 -lk -e -``` - -간단한 모드를 사용하여 특정 문제 검사: - -```shell -workspace/leetcode-practice [dev●] » lk -e -? 검사 모드를 선택하십시오: identity -? 문제 번호를 입력하십시오: 41 -? 현재 디렉토리 [ /Users/mac-106/wh131462/workspace/leetcode-practice ]에서 문제 [ 41.first-missing-positive ]를 검사하시겠습니까? Yes -┌─────────┬──────────┬──────────┬───────────┬────────────┬───────────┐ -│ (index) │ 테스트 결과 │ 예상 결과 │ 실행 결과 │ 실행 시간 │ 메모리 사용량 │ -├─────────┼──────────┼──────────┼───────────┼────────────┼───────────┤ -│ 0 │ '미통과' │ '3' │ undefined │ '0.0969ms' │ '2.42 KB' │ -│ 1 │ '미통과' │ '2' │ undefined │ '0.0139ms' │ '2.56 KB' │ -│ 2 │ '미통과' │ '1' │ undefined │ '0.0051ms' │ '2.56 KB' │ -└─────────┴──────────┴──────────┴───────────┴────────────┴───────────┘ -문제 제출로 이동하려면 클릭하십시오: https://leetcode-cn/problems/first-missing-positive/ -문제[41.first-missing-positive] 검사 완료! -파일 주소는: /Users/mac-106/wh131462/workspace/leetcode-practice/41.first-missing-positive/index.js -``` - -#### 3. 문제 찾기 - `lf` - -- 개발 중... - -##### [1]. 문제 목록 보기[미개발] - -#### 4. 일반 매개변수 - -##### [1]. 현재 프로그래밍 언어 가져오거나 지정하기 - [`-l`/`-language` [언어]] - -`-l`을 인수 없이 사용하여 현재 프로그래밍 언어 설정을 가져올 수 있습니다. 또한 언어 매개변수를 지정하여 현재 CLI의 언어 환경을 지정된 언어로 설정할 수도 있습니다. - -```shell -# lc/lk/lf에서 이 매개변수는 동일하게 동작합니다 -lc -l -lk -l java -``` - -사용 예시: - -```shell -# 언어 환경 가져오기 -➜ leetcode-practice git:(dev) ✗ lc -l -현재 CLI 언어 환경은:javascript -# 언어 환경 변경 -➜ leetcode-practice git:(dev) ✗ lc -l java -? CLI의 언어 환경을 설정하시겠습니까 (옵션과 일치하는 경우 Enter 키를 눌러 확인하십시오) java -언어 환경이 설정되었습니다: java - -``` - -> 참고: 이 환경에서는 테스트 케이스를 실행할 수 없습니다. - -##### [2]. 디렉터리 지정 - [`-d`/`-directory`] - -`생성` 및 `검사` 명령은 현재 작업 디렉터리를 기준으로 상대 주소를 지정하는 `-d` 매개변수를 사용할 수 있습니다. 지정된 디렉터리에서 생성 또는 검사 작업이 수행됩니다. - -```shell -# 현재 디렉터리의 하위 디렉터리 src를 생성 디렉터리로 지정 -lc -d src -t -# 현재 디렉터리의 하위 디렉터리 src를 검사 디렉터리로 지정 -lk -d src -i -``` - -사용 예시: - -```shell -➜ src git:(dev) ✗ lc -d src -t -MODE: today -문제[2867.트리에서 유효한 경로 수 세기]가 생성되었습니다! -문제 파일 주소는:/home/wh131462/workspace/leetcode-practice/src/src/2867.count-valid-paths-in-a-tree/index.js -``` - -> 참고: 지정된 디렉터리가 존재하지 않으면 빈 디렉터리가 자동으로 생성됩니다. - -##### [3]. 버전 확인 [`-V`/`--version`] - -```shell -# lc 버전 확인 -lc -V -# lk 버전 확인 -lk -V -# lf 버전 확인 -lf -V -``` - -lc 버전 확인 예시: - -```shell -workspace/leetcode-practice [dev●] » lc -V -0.0.0 -``` - -##### [4]. 업데이트 확인 [`-u`/`--update`] - -`-u` 또는 `--update` 매개변수를 사용하여 현재 버전이 최신 버전인지 확인할 수 있습니다. 현재 버전이 최신 버전이 아닌 경우 사용자에게 업데이트를 진행할지 여부를 알립니다. - -```shell -lk -u -lf -u -lc -u -``` - -```shell -? 자동 감지된 환경은 [프로젝트]입니다. 아닌 경우 선택하고, 맞으면 엔터를 누르십시오. 프로젝트 -npm 저장소에서 버전 번호 가져 오기 시작 ... -npm 저장소의 버전 번호를 성공적으로 가져 왔습니다! -github 저장소의 버전 번호 가져 오기 시작 ... -github 저장소의 버전 번호를 성공적으로 가져 왔습니다! -로컬 버전 번호 가져 오기 시작 ... -로컬 버전 번호가 성공적으로 가져 왔습니다! -현재 버전 : [1.0.0] npm 패키지의 최신 버전 : [1.0.1] github 버전 : [1.0.1] -? [프로젝트]에서 업데이트 가능한 버전 [1.0.1] 감지되었습니다. 업데이트를 수행 하시겠습니까? (Y/n) Yes -업데이트 완료 ~ 즐거운 사용 되세요 ~ -``` - -### fork 프로젝트의 사용 - -##### [0]. 의존성 설치 - -사용하기 전에 의존성을 설치하기 위해 패키지 관리 도구를 사용하세요. - -```shell -# 의존성 설치 -npm install -# 또는 yarn (원하는 패키지 관리 도구를 사용할 수 있습니다.) -yarn -``` - -fork된 프로젝트의 명령어는 CLI의 사용 방법과 매개변수가 동일하지만, 스크립트를 실행하기 위해 `npm run`과 같은 패키지 관리 도구를 사용해야 합니다. - -> 참고: 프로젝트의 스크립트는 "src" 디렉토리를 기본적으로 `-d` 매개변수로 지정하여 프로젝트의 루트 디렉토리에 있는 파일을 실행하도록 되어 있습니다. 따라서 모든 명령은 기본적으로 src에서 실행됩니다. - -##### [1]. 문제 생성 [`lc`] - -CLI의 `lc` 섹션을 참고하여 매개변수를 사용할 수 있습니다: [lc](#1-문제-생성---lc) - -간단한 사용 예시: - -```shell -# yarn을 사용하여 실행 -yarn lc 1314 -``` - -실행 결과: - -```shell -# src 디렉토리에 생성됩니다 -> yarn lc 1314 -yarn run v1.22.19 -$ node bin/lc.js -d src 1314 -MODE: identity -문제[1314.행렬 블록 합]이 생성되었습니다! -문제 파일 주소는: /Users/mac-106/wh131462/workspace/leetcode-practice/src/1314.matrix-block-sum/index.js -✨ Done in 1.06s. -``` - -##### [2]. 문제 검사 [`lk`] - -CLI의 `lk` 섹션을 참고하여 매개변수를 사용할 수 있습니다: [lk](#2-문제-검사---lk) - -간단한 사용 예시: - -```shell -# yarn을 사용하여 실행 -yarn lk 1314 -``` - -실행 결과: - -```shell -# src 디렉토리에서 검사됩니다 -> yarn lk 1314 -yarn run v1.22.19 -$ node bin/lk.js -d src 1314 -MODE: identity -문제[1314.행렬 블록 합] 검사 결과: -┌─────────┬──────────┬──────────────────────────────────────┬───────────┬────────────┬───────────┐ -│ (index) │ 테스트 결과 │ 예상 결과 │ 실행 결과 │ 실행 시간 │ 메모리 사용량 │ -├─────────┼──────────┼──────────────────────────────────────┼───────────┼────────────┼───────────┤ -│ 0 │ '미통과' │ '[[12,21,16],[27,45,33],[24,39,28]]' │ undefined │ '0.1487ms' │ '2.47 KB' │ -│ 1 │ '미통과' │ '[[45,45,45],[45,45,45],[45,45,45]]' │ undefined │ '0.0278ms' │ '2.61 KB' │ -└─────────┴──────────┴──────────────────────────────────────┴───────────┴────────────┴───────────┘ -문제 제출로 이동하려면 클릭하십시오: https://leetcode-cn/problems/matrix-block-sum/ -✨ Done in 1.13s. -``` - -##### [3]. 문제 찾기 [`lf`] - -CLI의 `lf` 섹션을 참고하여 매개변수를 사용할 수 있습니다: [lf](#3-문제-찾기---lf) - -미개발... - -##### [4]. 업데이트 [`update`] - -로컬 프로젝트를 업데이트하는 특정 스크립트는 모든 src 디렉토리가 아닌 업데이트를 위해 모든 비-src 디렉토리를 업데이트합니다. - -> 참고: 자체적으로 최적화된 변경 코드가 있는 경우 이 단계를 신중하게 수행하십시오! 특별한 경우의 업그레이드 방법은 [특별한 경우의 업그레이드 방법](./update.md)을 참조하십시오! - -### 플러그인의 사용 - -미개발... - -## 기여자 - -[<img src="https://avatars.githubusercontent.com/u/48346853" style="border-radius:50%;" width="30" height="30" alt="EternalHeart"/>](https://github.com/wh131462) -[<img src="https://avatars.githubusercontent.com/u/61453917" style="border-radius:50%;" width="30" height="30" alt="SmartTeddy"/>](https://github.com/SmallTeddy) -[<img src="https://avatars.githubusercontent.com/u/35305691" style="border-radius:50%;" width="30" height="30" alt="Hedwig-Fang"/>](https://github.com/Hedwig-Fang) - -## 피드백 - -사용 중에 `문제`가 있거나 `좋은 제안`이 있으면 언제든지 `피드백 그룹`에 참여하여 `피드백`을 제공하십시오! 우리는 신속하게 처리할 것입니다! - - diff --git a/docs/update.md b/docs/update.md deleted file mode 100644 index d8d2b17..0000000 --- a/docs/update.md +++ /dev/null @@ -1,11 +0,0 @@ -# 中文说明 - -## 特殊情况下的升级方案 - -待编写... - -# English Explanation - -## Upgrade Plan for Special Cases - -To be written... diff --git a/esbuild.config.js b/esbuild.config.js index 6074108..001d2b7 100644 --- a/esbuild.config.js +++ b/esbuild.config.js @@ -1,12 +1,11 @@ +import fs from 'node:fs' import path from 'node:path' -import fs, { mkdirSync } from 'node:fs' -import esbuild from 'esbuild' import { rootPath } from '#common/utils/file/getRootPath.js' +import { logger } from '#common/utils/logger/logger.js' +import esbuild from 'esbuild' // 读取 package.json 文件内容 -const packageJson = JSON.parse( - fs.readFileSync(path.resolve(rootPath, 'package.json'), 'utf-8') -) +const packageJson = JSON.parse(fs.readFileSync(path.resolve(rootPath, 'package.json'), 'utf-8')) const esbuildConfig = { entryPoints: ['bin/lk.js', 'bin/lf.js', 'bin/lc.js'], outdir: 'pl-cli/bin', @@ -17,68 +16,36 @@ const esbuildConfig = { minify: true, packages: 'external', define: { - 'process.env.VERSION': JSON.stringify(packageJson.version) - } + 'process.env.VERSION': JSON.stringify(packageJson.version), + }, } const buildBinConfig = { lk: 'bin/lk.js', lf: 'bin/lf.js', - lc: 'bin/lc.js' + lc: 'bin/lc.js', } -const publishExcludeFields = [ - 'scripts', - 'devDependencies', - 'imports', - 'main', - 'config', - 'packageManager' -] +const publishExcludeFields = ['scripts', 'devDependencies', 'imports', 'main', 'config', 'packageManager'] // 清理文件 function clean() { return new Promise((resolve) => { fs.rm(path.resolve(rootPath, 'pl-cli'), { recursive: true }, (err) => { - if (err) resolve() + if (err) + resolve() else resolve() }) }) } -/** - * 创建入口文件 暴露三个接口 - */ -function createIndex() { - const dirs = buildBinConfig - const expTem = `export * from ` - - const content = Object.values(dirs).reduce((p, file) => { - return `${p + expTem}'${file}'\n` - }, '') - const filePath = 'pl-cli/index.js' - fs.writeFileSync(filePath, content) -} - /** * 复制文档 */ function copyDocs() { - // 复制文件 - const docs = fs.readdirSync(path.resolve(rootPath, 'docs')) // 创建docs - mkdirSync(path.resolve(rootPath, 'pl-cli/docs'), { recursive: true }) + const docs = ['README.md', 'README_CN.md', 'README_JP.md'] docs.forEach((doc) => { - fs.copyFileSync( - path.resolve(rootPath, 'docs', doc), - path.resolve(rootPath, 'pl-cli/docs/', doc) - ) + fs.copyFileSync(path.resolve(rootPath, doc), path.resolve(rootPath, `pl-cli/${doc}`)) }) - fs.copyFileSync( - path.resolve(rootPath, 'README.md'), - path.resolve(rootPath, 'pl-cli/README.md') - ) - fs.copyFileSync( - path.resolve(rootPath, 'LICENSE'), - path.resolve(rootPath, 'pl-cli/LICENSE') - ) + fs.copyFileSync(path.resolve(rootPath, 'LICENSE'), path.resolve(rootPath, 'pl-cli/LICENSE')) } /** @@ -86,25 +53,40 @@ function copyDocs() { */ function rewritePackageFile() { const newPackageJson = Object.assign(packageJson, { - bin: buildBinConfig + bin: buildBinConfig, }) publishExcludeFields?.forEach((key) => { delete newPackageJson[key] }) - Object.assign(newPackageJson, { main: 'index.js' }) - fs.writeFileSync( - path.resolve(rootPath, 'pl-cli/package.json'), - JSON.stringify(newPackageJson) - ) + fs.writeFileSync(path.resolve(rootPath, 'pl-cli/package.json'), JSON.stringify(newPackageJson)) } +/** + * 创建原始目录下的文件 需要将js转化成压缩后的形式 + */ +function createOrigin() { + const originFiles = fs + .readdirSync(path.resolve(rootPath, 'common/origin')) + ?.filter(path => path.endsWith('.js')) + .map(file => path.resolve(rootPath, `common/origin/${file}`)) + esbuild.buildSync({ + entryPoints: originFiles, + minify: true, + bundle: true, + outdir: 'pl-cli/origin', + platform: 'node', + target: ['node20'], + packages: 'external', + format: 'esm', + }) +} /** * 构建完成之后的流程 */ function afterBuild() { copyDocs() rewritePackageFile() - createIndex() + createOrigin() } /** @@ -117,11 +99,13 @@ async function main() { .then(() => { // 构建完成后执行的操作 afterBuild() - console.log('[LP]脚本打包完成,查看目录[pl-cli].') + logger.info('[LP]脚本打包完成,请查看目录[ pl-cli ].') + process.exit(0) }) .catch((e) => { - console.error('[LP]脚本打包失败', e) + logger.error('[LP]脚本打包失败', e) process.exit(1) }) } + await main() diff --git a/eslint.config.js b/eslint.config.js index 4d0a629..000f9f0 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,6 +6,6 @@ export default antfu({ 'no-console': 'off', 'no-irregular-whitespace': 'off', 'eslint-comments/no-unlimited-disable': 'off', - 'no-cond-assign': 'off' - } + 'no-cond-assign': 'off', + }, }) diff --git a/package.json b/package.json index 1ce9f95..75fd610 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { "name": "leetcode-practice", "type": "module", - "version": "1.0.5", - "packageManager": "yarn@1.22.0", + "version": "1.0.9", "description": "A powerful practice platform for leetcode.Using any way you want to create questions.", "author": { "name": "EternalHeart", @@ -29,8 +28,6 @@ "lc": "node bin/lc.js -d src", "lk": "node bin/lk.js -d src", "lf": "node bin/lf.js -d src", - "release:cli": "node scripts/release.js", - "update": "node scripts/update.js", "build-cli": "node esbuild.config.js", "publish-cli": "cd pl-cli && npm publish --registry https://registry.npmjs.org/", "unpublish-cli": "cd pl-cli && npm unpublish --force --registry https://registry.npmjs.org/", @@ -43,40 +40,43 @@ "prepare": "husky install", "create-color-font": "node scripts/create-color-font.js", "release": "release-it", - "try-release": "release-it --dry-run" + "try-release": "release-it --dry-run", + "rebase": "HUSKY=0 git rebase " }, "dependencies": { "@inquirer/input": "^2.0.1", - "@inquirer/select": "^2.0.0", + "@inquirer/select": "^4.0.0", "chalk": "^5.3.0", "commander": "^12.0.0", "console-table-printer": "^2.12.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", "glob": "^10.3.10", - "inquirer": "^9.2.14", - "lint-staged": "^15.2.2", - "prettier": "^3.2.5", - "realm": "^12.6.0" + "inquirer": "^12.0.0", + "ora": "^8.0.1", + "realm": "^12.6.2" }, "devDependencies": { - "@antfu/eslint-config": "^2.8.0", - "@commitlint/cli": "^17.0.3", - "@commitlint/config-conventional": "^17.0.3", + "@antfu/eslint-config": "^3.8.0", + "@commitlint/cli": "^19.1.0", + "@commitlint/config-conventional": "^19.1.0", "@release-it/bumper": "^6.0.1", "@release-it/conventional-changelog": "^8.0.1", - "@types/node": "^20.11.5", + "@types/node": "^22.7.7", "@vitest/coverage-v8": "^1.2.2", "commitizen": "^4.2.5", "cz-conventional-changelog": "^3.3.0", - "esbuild": "^0.20.0", - "eslint": "^8.57.0", + "esbuild": "^0.24.0", + "eslint": "^9.0.0", "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", - "gradient-string": "^2.0.2", - "husky": "^8.0.1", + "eslint-plugin-prettier": "^5.1.3", + "gradient-string": "^3.0.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", "release-it": "^17.1.1", "rimraf": "^5.0.5", + "typescript": "^5.4.2", "vite": "^5.0.11", "vitest": "^1.2.2" }, diff --git a/resources/headers/allQuestionRequestUrlJson.js b/resources/headers/allQuestionRequestUrlJson.js new file mode 100644 index 0000000..76f151a --- /dev/null +++ b/resources/headers/allQuestionRequestUrlJson.js @@ -0,0 +1,7 @@ +export function getAllQuestionRequestUrlJson() { + return { + headers: { 'content-type': 'application/json' }, + body: '{"operationName":"allQuestionUrls","variables":{},"query":"query allQuestionUrls {\\n allQuestionUrls {\\n questionUrl\\n __typename\\n }\\n}\\n"}', + method: 'POST', + } +} diff --git a/resources/headers/codeSubmitJson.js b/resources/headers/codeSubmitJson.js index 4d4c52a..81e37c6 100644 --- a/resources/headers/codeSubmitJson.js +++ b/resources/headers/codeSubmitJson.js @@ -14,6 +14,6 @@ export function codeSubmitJson(lang, id, code) { "question_id": "${id}", "typed_code": "${code}" }`, - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/questionListHot100Json.js b/resources/headers/planQuestionListJson.js similarity index 53% rename from resources/headers/questionListHot100Json.js rename to resources/headers/planQuestionListJson.js index 2d3707d..c1dcd55 100644 --- a/resources/headers/questionListHot100Json.js +++ b/resources/headers/planQuestionListJson.js @@ -2,10 +2,10 @@ * 获取hot 100 的请求header * @returns {{headers: {"content-type": string}, method: string, body: string}} */ -export function getQuestionListHot100Json() { +export function getPlanQuestionListJson(slug) { return { headers: { 'content-type': 'application/json' }, - body: '{"query":"\\n query studyPlanPastSolved($slug: String!) {\\n studyPlanV2Detail(planSlug: $slug) {\\n planSubGroups {\\n slug\\n questions {\\n titleSlug\\n status\\n }\\n }\\n }\\n}\\n ","variables":{"slug":"top-100-liked"},"operationName":"studyPlanPastSolved"}', - method: 'POST' + body: `{"query":"\\n query studyPlanPastSolved($slug: String!) {\\n studyPlanV2Detail(planSlug: $slug) {\\n planSubGroups {\\n slug\\n questions {\\n titleSlug\\n translatedTitle\\n status\\n }\\n }\\n }\\n}\\n ","variables":{"slug":"${slug}"},"operationName":"studyPlanPastSolved"}`, + method: 'POST', } } diff --git a/resources/headers/questionCodeListJson.js b/resources/headers/questionCodeListJson.js index 1856538..feed28f 100644 --- a/resources/headers/questionCodeListJson.js +++ b/resources/headers/questionCodeListJson.js @@ -2,6 +2,6 @@ export function getQuestionCodeListJson(slug) { return { headers: { 'content-type': 'application/json' }, body: `{"query":"\\n query questionEditorData($titleSlug: String!) {\\n question(titleSlug: $titleSlug) {\\n questionId\\n questionFrontendId\\n codeSnippets {\\n lang\\n langSlug\\n code\\n }\\n envInfo\\n enableRunCode\\n hasFrontendPreview\\n frontendPreviews\\n }\\n}\\n ","variables":{"titleSlug":"${slug}"},"operationName":"questionEditorData"}`, - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/questionDetailJson.js b/resources/headers/questionDetailJson.js index 9cb0aa2..d60d47d 100644 --- a/resources/headers/questionDetailJson.js +++ b/resources/headers/questionDetailJson.js @@ -1,7 +1,7 @@ export function getQuestionDetailJson(slug) { return { headers: { 'content-type': 'application/json' }, - body: `{"query":"\\n query questionTranslations($titleSlug: String!) {\\n question(titleSlug: $titleSlug) {questionId\\n translatedTitle\\n translatedContent\\n }\\n}\\n ","variables":{"titleSlug":"${slug}"},"operationName":"questionTranslations"}`, - method: 'POST' + body: `{"query":"\\n query questionTranslations($titleSlug: String!) {\\n question(titleSlug: $titleSlug) {questionId\\n translatedTitle\\n translatedContent\\n jsonExampleTestcases\\n exampleTestcases\\n }\\n}\\n ","variables":{"titleSlug":"${slug}"},"operationName":"questionTranslations"}`, + method: 'POST', } } diff --git a/resources/headers/questionLanguageListJson.js b/resources/headers/questionLanguageListJson.js index fea9d0c..a932d6e 100644 --- a/resources/headers/questionLanguageListJson.js +++ b/resources/headers/questionLanguageListJson.js @@ -10,6 +10,6 @@ export function getQuestionLanguageListJson() { "variables": {}, "operationName": "languageList" }`, - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/questionListJson.js b/resources/headers/questionListJson.js index d197c2f..f6ce9e1 100644 --- a/resources/headers/questionListJson.js +++ b/resources/headers/questionListJson.js @@ -2,6 +2,6 @@ export function getQuestionListJson(skip = 0, limit = 50) { return { headers: { 'content-type': 'application/json' }, body: `{"query":"query problemsetQuestionList($categorySlug: String, $limit: Int, $skip: Int, $filters: QuestionListFilterInput) {\\nproblemsetQuestionList(\\ncategorySlug: $categorySlug\\nlimit: $limit\\nskip: $skip\\nfilters: $filters) {\\ntotal\\nquestions {\\n frontendQuestionId\\n title\\n titleCn\\n titleSlug\\n}\\n}\\n}","variables":{"categorySlug":"all-code-essentials","skip":${skip},"limit":${limit},"filters":{}},"operationName":"problemsetQuestionList"}`, - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/questionSearchJson.js b/resources/headers/questionSearchJson.js index ad2a370..fdaf703 100644 --- a/resources/headers/questionSearchJson.js +++ b/resources/headers/questionSearchJson.js @@ -2,6 +2,6 @@ export function getQuestionSearchJson(keyword) { return { headers: { 'content-type': 'application/json' }, body: `{"query":"\\n query problemsetQuestionList($categorySlug: String, $limit: Int, $skip: Int, $filters: QuestionListFilterInput) {\\n problemsetQuestionList(\\n categorySlug: $categorySlug\\n limit: $limit\\n skip: $skip\\n filters: $filters\\n ) {\\n hasMore\\n total\\n questions {\\n acRate\\n difficulty\\n freqBar\\n frontendQuestionId\\n isFavor\\n paidOnly\\n solutionNum\\n status\\n title\\n titleCn\\n titleSlug\\n topicTags {\\n name\\n nameTranslated\\n id\\n slug\\n }\\n extra {\\n hasVideoSolution\\n topCompanyTags {\\n imgUrl\\n slug\\n numSubscribed\\n }\\n }\\n }\\n }\\n}\\n ","variables":{"categorySlug":"all-code-essentials","skip":0,"limit":50,"filters":{"searchKeywords":"${keyword}"}},"operationName":"problemsetQuestionList"}`, - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/questionTagTypeJson.js b/resources/headers/questionTagTypeJson.js new file mode 100644 index 0000000..b280db5 --- /dev/null +++ b/resources/headers/questionTagTypeJson.js @@ -0,0 +1,7 @@ +export function getQuestionTagTypeJson() { + return { + headers: { 'content-type': 'application/json' }, + body: '{"query":"\\n query questionTagTypeWithTags {\\n questionTagTypeWithTags {\\n name\\n transName\\n tagRelation {\\n questionNum\\n tag {\\n name\\n id\\n nameTranslated\\n slug\\n }\\n }\\n }\\n}\\n ","variables":{},"operationName":"questionTagTypeWithTags"}', + method: 'POST', + } +} diff --git a/resources/headers/questionTodayJson.js b/resources/headers/questionTodayJson.js index 608c5fa..583b28b 100644 --- a/resources/headers/questionTodayJson.js +++ b/resources/headers/questionTodayJson.js @@ -2,6 +2,6 @@ export function getQuestionTodayJson() { return { headers: { 'content-type': 'application/json' }, body: '{"query":"\\n query questionOfToday {\\n todayRecord {\\n date\\n userStatus\\n question {\\n questionId\\n frontendQuestionId: questionFrontendId\\n difficulty\\n title\\n titleCn: translatedTitle\\n titleSlug\\n paidOnly: isPaidOnly\\n freqBar\\n isFavor\\n acRate\\n status\\n solutionNum\\n hasVideoSolution\\n topicTags {\\n name\\n nameTranslated: translatedName\\n id\\n }\\n extra {\\n topCompanyTags {\\n imgUrl\\n slug\\n numSubscribed\\n }\\n }\\n }\\n lastSubmission {\\n id\\n }\\n }\\n}\\n ","variables":{},"operationName":"questionOfToday"}', - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/questionTypeJson.js b/resources/headers/questionTypeJson.js index 176c020..a123442 100644 --- a/resources/headers/questionTypeJson.js +++ b/resources/headers/questionTypeJson.js @@ -6,6 +6,6 @@ export function getQuestionTypesJson() { "variables": {}, "operationName": "questionTagTypeWithTags" }`, - method: 'POST' + method: 'POST', } } diff --git a/resources/headers/studyPlanListJson.js b/resources/headers/studyPlanListJson.js new file mode 100644 index 0000000..d5b192e --- /dev/null +++ b/resources/headers/studyPlanListJson.js @@ -0,0 +1,10 @@ +// 'sprint-interview-company' // 名企面试 · 突击备战 +// 'cracking-coding-interview' // 面试准备 · 全面通关 +// 'deep-dive-topics' // 专项计划 · 深入学习 +export function getStudyPlanListJson(type) { + return { + headers: { 'content-type': 'application/json' }, + body: `{\"query\":\"\\n query GetStudyPlanByCatalog($catalogSlug: String!, $offset: Int!, $limit: Int!) {\\n studyPlansV2ByCatalog(catalogSlug: $catalogSlug, offset: $offset, limit: $limit) {\\n hasMore\\n total\\n studyPlans {\\n slug\\n questionNum\\n premiumOnly\\n onGoing\\n name\\n highlight\\n cover\\n }\\n }\\n}\\n \",\"variables\":{\"offset\":0,\"catalogSlug\":\"${type}\",\"limit\":12},\"operationName\":\"GetStudyPlanByCatalog\"}`, + method: 'POST', + } +} diff --git a/resources/images/create-finish.png b/resources/images/create-finish.png new file mode 100644 index 0000000..fd6a514 Binary files /dev/null and b/resources/images/create-finish.png differ diff --git a/resources/images/create-new-by-template.png b/resources/images/create-new-by-template.png new file mode 100644 index 0000000..06db0bf Binary files /dev/null and b/resources/images/create-new-by-template.png differ diff --git a/resources/images/fulfill-template-new.png b/resources/images/fulfill-template-new.png new file mode 100644 index 0000000..280cb8a Binary files /dev/null and b/resources/images/fulfill-template-new.png differ diff --git a/resources/images/generating-your-template.png b/resources/images/generating-your-template.png new file mode 100644 index 0000000..612d93f Binary files /dev/null and b/resources/images/generating-your-template.png differ diff --git a/resources/images/github-fork.png b/resources/images/github-fork.png deleted file mode 100644 index a4ac9b8..0000000 Binary files a/resources/images/github-fork.png and /dev/null differ diff --git a/resources/images/github-forked.png b/resources/images/github-forked.png deleted file mode 100644 index 2d4376f..0000000 Binary files a/resources/images/github-forked.png and /dev/null differ diff --git a/resources/images/github-forking.png b/resources/images/github-forking.png deleted file mode 100644 index 7f9fe35..0000000 Binary files a/resources/images/github-forking.png and /dev/null differ diff --git a/resources/images/lc-cli-h.png b/resources/images/lc-cli-h.png index 2a3cc93..f736771 100644 Binary files a/resources/images/lc-cli-h.png and b/resources/images/lc-cli-h.png differ diff --git a/resources/images/leetcode-practice-github.png b/resources/images/leetcode-practice-github.png deleted file mode 100644 index 936643e..0000000 Binary files a/resources/images/leetcode-practice-github.png and /dev/null differ diff --git a/resources/images/service-qrcode.jpg b/resources/images/service-qrcode.jpg new file mode 100644 index 0000000..93ae901 Binary files /dev/null and b/resources/images/service-qrcode.jpg differ diff --git a/resources/images/service-qrcode.png b/resources/images/service-qrcode.png deleted file mode 100644 index 3a20b9f..0000000 Binary files a/resources/images/service-qrcode.png and /dev/null differ diff --git a/resources/images/template-page.png b/resources/images/template-page.png new file mode 100644 index 0000000..252a7c7 Binary files /dev/null and b/resources/images/template-page.png differ diff --git a/resources/text/description.js b/resources/text/description.js index ebcc133..a6e696b 100644 --- a/resources/text/description.js +++ b/resources/text/description.js @@ -1,5 +1,7 @@ +import { GITHUB_HOST, PackageName } from '#common/constants/question.const.js' + export const description = ` A powerful practice platform for leetcode. CLI / Template Project / Plugin, you can create question by any way you like. -See https://github.com/wh131462/leetcode-practice +See https://github.com/${GITHUB_HOST}/${PackageName} ` diff --git a/resources/text/examples.js b/resources/text/examples.js index 7ea9cf6..cf3e1c1 100644 --- a/resources/text/examples.js +++ b/resources/text/examples.js @@ -13,7 +13,8 @@ Examples: $ lc -u // Check the version to determine whether to update to the latest one. $ lc -l // Get the code language of question. $ lc -l java // Set the code language of question. - $ lc -v // Check the CLI version. + $ lc -a // Fetch all questions from server and store them locally, prepare database for lf command. + $ lc -v // Check the version info and some extra info about leetcode-practice. $ lc -h // Check the help information. ` @@ -33,7 +34,7 @@ Examples: $ lk -l // Get the code language of question. $ lk -l java // Set the code language of question. $ lk -u // Check the version to determine whether to update to the latest one. - $ lk -v // Check the CLI version. + $ lk -v // Check the version info and some extra info about leetcode-practice. $ lk -h // Display the help information. ` @@ -41,16 +42,16 @@ Examples: export const lfExamples = ` Examples: # Command with no parameters - + nothing... # Exclusive commands - + nothing... # Other instructions $ lf -e // Easy mode to check a question. $ lf -d src // Use the relative path to the source folder. $ lf -l // Get the code language of question. $ lf -l java // Set the code language of question. $ lf -u // Check the version to determine whether to update to the latest one. - $ lf -v // Check the CLI version. + $ lf -v // Check the version info and some extra info about leetcode-practice. $ lf -h // Display the help information. ` diff --git a/scripts/create-color-font.js b/scripts/create-color-font.js index d464df3..b9b4fd2 100644 --- a/scripts/create-color-font.js +++ b/scripts/create-color-font.js @@ -1,12 +1,12 @@ -import inquirer from 'inquirer' import { createColorFont } from '#common/utils/etc/createColorFont.js' +import inquirer from 'inquirer' const question = [ { type: 'input', name: 'font', - message: '请输入要渐变色的文本:' - } + message: '请输入要渐变色的文本:', + }, ] // 第一个问题 选择的模式 const { font } = await inquirer.prompt(question, null) diff --git a/scripts/loading.js b/scripts/loading.js new file mode 100644 index 0000000..5399e09 --- /dev/null +++ b/scripts/loading.js @@ -0,0 +1,4 @@ +import ora from 'ora' + +const loading = ora('LP!给我加载!!!!').start() +setTimeout(() => loading.stop(), 300000) diff --git a/scripts/release.js b/scripts/release.js deleted file mode 100644 index 0f81b06..0000000 --- a/scripts/release.js +++ /dev/null @@ -1,52 +0,0 @@ -import fs from 'node:fs' -import { fileURLToPath } from 'node:url' -import path, { dirname } from 'node:path' -import * as child_process from 'node:child_process' -import packageJson from '../package.json' assert { type: 'json' } - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) -;(async function () { - // 自动更新版本 - // version可以传递如 6.1.1 | patch | minor | major - const execCommand = (arr) => - (Array.isArray(arr) ? arr : [arr]).forEach((c) => { - try { - console.log(`start: ${c}...`) - console.log(child_process.execSync(c).toString('utf8')) - } catch (error) { - console.log('\x1B[31m%s\x1B[0m', error.stdout.toString()) - process.exit(1) - } - }) - const getNewVersion = (oldVersion, version = 'patch') => { - // [<newversion> | major | minor | patch] - if (/^([0-9]+\.*)+$/.test(version)) return version - const types = ['major', 'minor', 'patch'] - const index = types.indexOf(version) - if (index >= 0) { - const versionArr = oldVersion.split('.') - versionArr[index] = Number(versionArr[index]) + 1 - return versionArr.map((e, i) => (i > index ? 0 : e)).join('.') - } - return getNewVersion(oldVersion) - } - const newVersionObj = { - version: getNewVersion(packageJson.version, process.argv[2]) - } - fs.writeFileSync( - path.resolve(__dirname, '../package.json'), - `${JSON.stringify( - Object.assign({}, packageJson, newVersionObj), - null, - 2 - )}\n` - ) - console.log(newVersionObj) - execCommand([ - `git commit -a -m 'chore: update version cli-v${newVersionObj.version}'`, - `git tag cli-v${newVersionObj.version}`, - 'git push && git push --tags' - ]) - console.log('\x1B[32m%s\x1B[0m', '发布完成,请关注github CI构建') -})() diff --git a/scripts/update.js b/scripts/update.js deleted file mode 100644 index ba74ec6..0000000 --- a/scripts/update.js +++ /dev/null @@ -1,30 +0,0 @@ -// 更新脚本 默认是项目中 -import inquirer from 'inquirer' -import { checkUpdate } from '#common/utils/update/update.js' -import { updateProject } from '#common/utils/update/updateByEnv.js' - -const { isGithubUpdate, githubVersion, localVersion } = await checkUpdate() -console.log(`当前版本: [${localVersion}] github版本: [${githubVersion}] `) -if (isGithubUpdate) { - const checkQuestion = { - type: 'confirm', - name: 'willUpdate', - message: `是否进行更新?` - } - const { willUpdate } = await inquirer.prompt(checkQuestion, null) - if (willUpdate) { - // 4.1 选择更新 - console.log('开始更新...') - await updateProject() - console.log('更新完成~祝你使用愉快~') - } else { - // 4.2 取消更新 - console.log( - '你选择跳过此次更新,如果想要进行更新,随时可以使用参数 -u 进行更新检测!祝你使用愉快~' - ) - } - process.exit(0) -} else { - console.log('当前版本为最新版本~无需更新!') -} -process.exit(0) diff --git a/test/create.spec.js b/test/create.spec.js index da89d7e..8550403 100644 --- a/test/create.spec.js +++ b/test/create.spec.js @@ -1,18 +1,18 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' -import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js' +import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' import { generateTemplateContent } from '#common/utils/question-handler/fulfillQuestion.js' +import { afterEach, describe, expect, it, vi } from 'vitest' vi.mock('fs/promises', () => { return { - writeFile: vi.fn() + writeFile: vi.fn(), } }) -const funRegex = /var\s+(\w+)\s*=\s*function\s*\(([^)]*)\)\s*{\s*([^}]*)\s*}/ -const isContainJsCode = (input) => funRegex.test(input) -const isContainTestCase = (input) => input.includes('showLogs(') +const funRegex = /var\s+(\w+)\s*=\s*function\s*\(([^)]*)\)\s*\{\s*([^}]*)\s*\}/ +const isContainJsCode = input => funRegex.test(input) +const isContainTestCase = input => input.includes('showLogs(') -const mockKeys = ['id', 'slug', 'title', 'detail', 'lang', 'code', 'date'] +const mockKeys = ['id', 'slug', 'title', 'detail', 'lang', 'code', 'jsonExampleTestcases', 'exampleTestcases', 'date'] function isValidQuestion(res) { const content = generateTemplateContent(res) diff --git a/test/getHot100List.spec.js b/test/getHot100List.spec.js deleted file mode 100644 index 8b74225..0000000 --- a/test/getHot100List.spec.js +++ /dev/null @@ -1,10 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { getQuestionListHot100 } from '#common/utils/question-getter/getQuestionListHot100.js' - -describe('hot 100获取数据测试', () => { - it('是否正确获取了hot 100合集', async () => { - const res = await getQuestionListHot100() - - expect(Object.keys(res)).toStrictEqual(['planSubGroups']) - }) -}) diff --git a/test/graph.spec.js b/test/graph.spec.js index c86cb53..77a1db0 100644 --- a/test/graph.spec.js +++ b/test/graph.spec.js @@ -1,43 +1,43 @@ /* eslint-disable */ -import { expect, it } from 'vitest' -import { Node } from '#common/structures/Node' +import { expect, it } from 'vitest'; +import { Node } from '#common/structures/Node'; const graphArray1 = [ - [2, 4], - [1, 3], - [2, 4], - [1, 3] -] -const graphArray2 = [[]] -const graphArray3 = [] -const graphArray4 = [[2], [1]] + [2, 4], + [1, 3], + [2, 4], + [1, 3] +]; +const graphArray2 = [[]]; +const graphArray3 = []; +const graphArray4 = [[2], [1]]; const graphArray5 = [ - [2, 5], - [1, 3, 5], - [2, 4], - [3, 5], - [1, 2, 4] -] + [2, 5], + [1, 3, 5], + [2, 4], + [3, 5], + [1, 2, 4] +]; const graphArray6 = [ - [2, 5], - [1, 3], - [2, 4], - [3, 5], - [4, 1] -] + [2, 5], + [1, 3], + [2, 4], + [3, 5], + [4, 1] +]; const graphArray7 = [ - [2, 4], - [1, 3], - [2, 4], - [3, 1] -] -const graphArray8 = [[2, 3, 4, 5], [1, 3, 4], [1, 2], [1, 2], [1]] -const max = 9 + [2, 4], + [1, 3], + [2, 4], + [3, 1] +]; +const graphArray8 = [[2, 3, 4, 5], [1, 3, 4], [1, 2], [1, 2], [1]]; +const max = 9; it('测试无向连通图', () => { - for (let i = 1; i < max; i++) { - const currentArray = `graphArray${[i]}` - const graph = Node.parse(eval(currentArray)) - expect(eval(currentArray)).toEqual(Node.toArray(graph)) - } -}) + for (let i = 1; i < max; i++) { + const currentArray = `graphArray${[i]}`; + const graph = Node.parse(eval(currentArray)); + expect(eval(currentArray)).toEqual(Node.toArray(graph)); + } +}); diff --git a/test/listNode.spec.js b/test/listNode.spec.js index c211562..074455b 100644 --- a/test/listNode.spec.js +++ b/test/listNode.spec.js @@ -1,5 +1,5 @@ -import { expect, it } from 'vitest' import { ListNode } from '#common/structures/ListNode' +import { expect, it } from 'vitest' it('toArray 正常数组', () => { // 创建链表 diff --git a/test/parseFilePath.spec.js b/test/parseFilePath.spec.js deleted file mode 100644 index e1b8354..0000000 --- a/test/parseFilePath.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { parseFilePath } from '#common/utils/file/parseFilePath.js' - -const path = 'src/LRC 257.pp' -describe('parseFilePath', () => { - it('是否正确的转化了地址', () => { - expect(parseFilePath(path)).equal(`\"src/LRC 257.pp\"`, '正确解析地址') - }) -}) diff --git a/test/paseDataStructure.spec.js b/test/paseDataStructure.spec.js index 5db2133..03a525b 100644 --- a/test/paseDataStructure.spec.js +++ b/test/paseDataStructure.spec.js @@ -1,5 +1,5 @@ -import { expect, it } from 'vitest' import { getDataStructure } from '#common/utils/question-handler/parseStructure.js' +import { expect, it } from 'vitest' const mockJSDOC_multiple = `/** * Definition for singly-linked list. @@ -93,9 +93,7 @@ it('获取入参的数据结构 单参 匹配值', () => { }) it('获取入参的数据结构 单参 ListNode[]', () => { - expect(getDataStructure(mockJSDOC_ListNodeArray, 'param')).toEqual([ - 'ListNode[]' - ]) + expect(getDataStructure(mockJSDOC_ListNodeArray, 'param')).toEqual(['ListNode[]']) }) it('获取返回值的数据结构 单参 匹配值', () => { expect(getDataStructure(mockJSDOC_single, 'return')).toEqual(['ListNode']) diff --git a/test/setDataStructure.spec.js b/test/setDataStructure.spec.js index 732362f..937f8b9 100644 --- a/test/setDataStructure.spec.js +++ b/test/setDataStructure.spec.js @@ -1,5 +1,5 @@ -import { expect, it } from 'vitest' import { getDataStructure } from '#common/utils/question-handler/parseStructure.js' +import { expect, it } from 'vitest' const jsDoc = `/** * Definition for singly-linked list. diff --git a/test/tree.spec.js b/test/tree.spec.js index 63aad82..ff0d8be 100644 --- a/test/tree.spec.js +++ b/test/tree.spec.js @@ -1,5 +1,5 @@ -import { expect, it } from 'vitest' import { TreeNode } from '#common/structures/TreeNode' +import { expect, it } from 'vitest' const mockTree = [1, 2, 3] const mockTree2 = [1, null, 2] @@ -21,23 +21,13 @@ it('测试树 parse 特殊值', () => { expect(TreeNode.parse([])).toBeNull() }) it('测试树 parse mockTree', () => { - expect(TreeNode.parse(mockTree)).toEqual( - new TreeNode(1, new TreeNode(2), new TreeNode(3)) - ) + expect(TreeNode.parse(mockTree)).toEqual(new TreeNode(1, new TreeNode(2), new TreeNode(3))) }) it('测试树 pase mockTree2', () => { - expect(TreeNode.parse(mockTree2)).toEqual( - new TreeNode(1, null, new TreeNode(2)) - ) + expect(TreeNode.parse(mockTree2)).toEqual(new TreeNode(1, null, new TreeNode(2))) }) it('测试树 pase mockTree3', () => { - expect(TreeNode.parse(mockTree3)).toEqual( - new TreeNode( - 3, - new TreeNode(9, null), - new TreeNode(20, new TreeNode(15, null), new TreeNode(7)) - ) - ) + expect(TreeNode.parse(mockTree3)).toEqual(new TreeNode(3, new TreeNode(9, null), new TreeNode(20, new TreeNode(15, null), new TreeNode(7)))) }) it('测试树 pase mockTree4', () => { expect(TreeNode.parse([0])).toEqual(new TreeNode())