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/workflows/release-cli.yml b/.github/workflows/release-cli.yml
index df27140..04b2e9d 100644
--- a/.github/workflows/release-cli.yml
+++ b/.github/workflows/release-cli.yml
@@ -8,7 +8,7 @@ on:
jobs:
build:
runs-on: ubuntu-latest
- if: github.repository == 'EternalHeartTeam/leetcode-practice'
+ if: github.repository == 'EternalHeartTeam/leetcode-practice' && github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v3
# Setup .npmrc file to publish to npm
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 992a33b..496ac5e 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,13 +1,7 @@
#!/usr/bin/env sh
# 导入 Husky 脚本
. "$(dirname -- "$0")/_/husky.sh"
-
-# 检查是否处于 rebase 状态
-if [ -z "$GIT_DIR" ]; then
- # 处于 rebase 状态,退出脚本
- exit 0
-fi
-
-# 不处于 rebase 状态,执行 pre-commit 脚本
+# 如果要执行 rebase 需要跳过当前所有hooks
+# todo-highlight HUSKY=0 git rebase ...
echo "Running pre-commit script..."
-npm run lint && npm run format
\ No newline at end of file
+npm run lint && npm run format && git add .
\ No newline at end of file
diff --git a/.release-it.json b/.release-it.json
index 2d90a60..cece73f 100644
--- a/.release-it.json
+++ b/.release-it.json
@@ -5,8 +5,9 @@
"autoGenerate": true
},
"git": {
- "commitMessage": "feat: v${version}",
+ "commitMessage": "chore: release v${version}",
"tagName": "cli-v${version}",
+ "branch": "stable-v${version}",
"tag": true,
"push": true,
"pushArgs": ["--follow-tags"]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5b8642..31647b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,19 +1,29 @@
+## [1.0.8](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.7...cli-v1.0.8) (2024-03-14)
+### Bug Fixes
-## [1.0.7](https://github.com/wh131462/leetcode-practice/compare/cli-v1.0.6...cli-v1.0.7) (2024-03-12)
+- 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))
+- 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)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
new file mode 100644
index 0000000..da2a273
--- /dev/null
+++ b/CONTRIBUTORS.md
@@ -0,0 +1,23 @@
+# CONTRIBUTORS
+
+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 and Dev Branches
+
+By default, feature and fix branches will be deleted after being merged into `master` via pull request.
+
+The `dev` branch will not be deleted.
+
+## References
+
+Reference Link: [Branch Management](https://www.ruanyifeng.com/blog/2012/07/git.html)
diff --git a/CONTRIBUTORS_CN.md b/CONTRIBUTORS_CN.md
new file mode 100644
index 0000000..b63f050
--- /dev/null
+++ b/CONTRIBUTORS_CN.md
@@ -0,0 +1,23 @@
+# CONTRIBUTORS
+
+如果你也想参与我们的项目共建,请详细阅读以下开发约定,只有大家拥有一个共识,我们的项目才会越来越好,
+
+## 贡献代码
+
+### 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`分支不会进行删除.
+
+## 参考信息
+
+参考链接: [分支管理](https://www.ruanyifeng.com/blog/2012/07/git.html)
diff --git a/README.md b/README.md
index c337ed5..50be8a3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Leetcode practice
-[中文文档](./README_CN.md)|**English Document**||[日本語の文書](./README_JP.md)
+[中文](./README_CN.md) · **English** ·[日本語](./README_JP.md)
## I. Project Information
@@ -282,7 +282,11 @@ The development and improvement of the project would not be possible without the
-### 2. Feedback
+### 2. How to Contribute
+
+If you share a passion for open source and would like to contribute to our open source initiative, please refer to our [contribution guidelines](./CONTRIBUTORS.md).
+
+### 3. Feedback
If you have any questions about usage or would like to offer some suggestions, feel free to join our feedback group!
@@ -290,6 +294,6 @@ Engage in face-to-face discussions with developers in the group, hoping to reson

-### 3. Star Trend Chart
+### 4. Star Trend Chart
[](https://star-history.com/#EternalHeartTeam/leetcode-practice&Date)
diff --git a/README_CN.md b/README_CN.md
index 0d364a1..3171959 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -1,6 +1,6 @@
# Leetcode practice
-**中文文档**|[English Document](./README.md)|[日本語の文書](./README_JP.md)
+**中文** · [English](./README.md) · [日本語](./README_JP.md)
## I.项目信息
@@ -287,7 +287,11 @@ npm i --save-dev leetcode-practice
-### 2.使用反馈
+### 2.如何贡献
+
+如果你也有一颗热爱开源的心,想要为我们的开源事业贡献一份力量,那么请参考我们的[贡献手册](./CONTRIBUTORS.md)。
+
+### 3.使用反馈
如果你有使用上的问题需要解惑,或者一些好的建议想要提出,可以加我们的使用反馈群进行反馈!
@@ -295,6 +299,6 @@ npm i --save-dev leetcode-practice

-### 3.Star趋势图
+### 4.Star趋势图
[](https://star-history.com/#EternalHeartTeam/leetcode-practice&Date)
diff --git a/README_JP.md b/README_JP.md
index ae0b4dd..f856320 100644
--- a/README_JP.md
+++ b/README_JP.md
@@ -1,6 +1,6 @@
# Leetcode practice
-[中文文档](./README_CN.md)|[English Document](./README.md)|**日本語の文書**
+[中文](./README_CN.md) · [English](./README.md) · **日本語**
## I.プロジェクト情報
@@ -278,7 +278,11 @@ npm i --save-dev leetcode-practice
-### 2. 使用フィードバック
+### 2. 貢献方法
+
+もしオープンソースに対する情熱を持ち、私たちのオープンソースイニシアチブに貢献したいとお考えでしたら、[貢献ガイドライン](./CONTRIBUTORS.md) を参照してください。
+
+### 3. 使用フィードバック
使用上の問題がある場合や、提案がある場合は、使用フィードバックグループにご参加ください!
@@ -286,6 +290,6 @@ npm i --save-dev leetcode-practice

-### 3. Starのトレンドチャート
+### 4. Starのトレンドチャート
[](https://star-history.com/#EternalHeartTeam/leetcode-practice&Date)
diff --git a/bin/lc.js b/bin/lc.js
index bc79697..d0000a2 100755
--- a/bin/lc.js
+++ b/bin/lc.js
@@ -1,27 +1,21 @@
#! /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 { referMode } from '#common/utils/cli-utils/referMode.js'
+import { getArgs } from '#common/utils/cli-utils/getArgs.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 { logger } from '#common/utils/logger/logger.js'
+import { createQuestionById } from '#common/utils/cli-utils/createQuestion.js'
+import { create } from '#common/utils/cli-utils/create.js'
+import { commonMode } from '#common/utils/cli-utils/commonMode.js'
const version = process.env.VERSION ?? DefaultVer
program
@@ -43,41 +37,8 @@ program
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()
- logger.info(`当前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: () => {
diff --git a/bin/lf.js b/bin/lf.js
index 2c7a58e..fe13730 100755
--- a/bin/lf.js
+++ b/bin/lf.js
@@ -1,16 +1,14 @@
#! /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 { commonMode } from '#common/utils/cli-utils/commonMode.js'
+import { willUse } from '#common/utils/etc/willUse.js'
const version = process.env.VERSION ?? DefaultVer
program
@@ -25,32 +23,9 @@ program
)
.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()
- logger.info(`当前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)
-}
-// 进入视图操作
-await easyFinderView(baseDir)
+// 通用参数执行
+const baseDir = await commonMode(cmdOpts, easyFinderView)
+willUse(cmdArgs, baseDir)
process.exit(0)
diff --git a/bin/lk.js b/bin/lk.js
index 931aac6..69e2245 100755
--- a/bin/lk.js
+++ b/bin/lk.js
@@ -2,23 +2,25 @@
import fs from 'node:fs'
import path from 'node:path'
import { program } from 'commander'
+import select from '@inquirer/select'
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 { referMode } from '#common/utils/cli-utils/referMode.js'
+import { getArgs } from '#common/utils/cli-utils/getArgs.js'
+import { checkQuestionByPath } from '#common/utils/question-handler/checkQuestionByPath.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 { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js'
import { easyCheckView } from '#common/view/check.view.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 { DefaultLang, DefaultVer } from '#common/constants/question.const.js'
import { logger } from '#common/utils/logger/logger.js'
+import { commonMode } from '#common/utils/cli-utils/commonMode.js'
+import { getFilePathById } from '#common/utils/file/getFilePathById.js'
+import { getQuestionFileInDir } from '#common/utils/file/getQuestionInDir.js'
const version = process.env.VERSION ?? DefaultVer
program
@@ -44,43 +46,10 @@ program
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()
- logger.info(`当前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) {
@@ -98,7 +67,7 @@ async function check(mode, question) {
logger.info(
`MODE: ${mode}\n题目[${getQuestionChineseName(question)}]检测结果:`
)
- await checkQuestion(filePath)
+ await checkQuestionByPath(filePath)
}
return true
}
@@ -115,13 +84,78 @@ 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)
+ const needToSelect = {
+ type: 'list',
+ name: 'need',
+ message: '在当前目录下存在多个题目,请选择你要检测的题目:',
+ choices: []
+ }
+ /**
+ * 只检查一个题目
+ * @param fileOrFiles
+ * @returns {Promise}
+ */
+ 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
+ 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 }
+ })
+ files = getQuestionFileInDir(
+ path.resolve(baseDir, await select(needToSelect))
+ )
+ break
+ }
+ await checkOne(files)
+ }
process.exit(0)
}
}
-
// 执行指令分发
callModeAction[mode](args)
diff --git a/common/utils/cli-utils/commonMode.js b/common/utils/cli-utils/commonMode.js
new file mode 100644
index 0000000..8400cd1
--- /dev/null
+++ b/common/utils/cli-utils/commonMode.js
@@ -0,0 +1,48 @@
+import path from 'node:path'
+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 { logger } from '#common/utils/logger/logger.js'
+
+/**
+ * 执行逻辑:
+ * 目录检测 - 设置基础目录
+ * 模式检测 - 检测是不是easy mode
+ * [参数检测 - 执行对应参数]
+ */
+/**
+ * 通用参数的执行逻辑
+ * @param cmdOpts{{directory:string,language:string|boolean,easy:boolean,update:boolean,[key:string]:*}}
+ * @param easyCallback{(baseDir:string)=>Promise}
+ * @returns {Promise}
+ */
+export async function commonMode(cmdOpts, easyCallback) {
+ // 根据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.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 65%
rename from common/utils/create-check/createUtil.js
rename to common/utils/cli-utils/create.js
index bfb570e..183301a 100644
--- a/common/utils/create-check/createUtil.js
+++ b/common/utils/cli-utils/create.js
@@ -1,14 +1,19 @@
import path from 'node:path'
-import { createQuestion } from '#common/utils/question-handler/createQuestion.js'
+import { logger } from '#common/utils/logger/logger.js'
+import { setQuestion } from '#common/utils/store/controller/question.js'
import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js'
+import { createQuestion } from '#common/utils/question-handler/createQuestion.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 { logger } from '#common/utils/logger/logger.js'
+import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js'
+/**
+ * 创建函数
+ * @param mode
+ * @param question
+ * @param baseDir
+ * @returns {Promise}
+ */
export function create(mode, question, baseDir) {
logger.info(`MODE: ${mode}`)
return new Promise((resolve) => {
@@ -24,17 +29,3 @@ export function create(mode, question, baseDir) {
})
})
}
-
-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) logger.warn(`指定编号: [ ${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..4fde403
--- /dev/null
+++ b/common/utils/cli-utils/createQuestion.js
@@ -0,0 +1,30 @@
+import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js'
+import { getQuestionIdBySlug } from '#common/utils/question-handler/getQuestionIdBySlug.js'
+import { logger } from '#common/utils/logger/logger.js'
+import { create } from '#common/utils/cli-utils/create.js'
+
+/**
+ * 通过指定的titleSlug创建题目
+ * @param titleSlug
+ * @param baseDir
+ * @returns {Promise}
+ */
+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}
+ */
+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/create-check/refer-mode.js b/common/utils/cli-utils/referMode.js
similarity index 100%
rename from common/utils/create-check/refer-mode.js
rename to common/utils/cli-utils/referMode.js
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/getQuestionInDir.js b/common/utils/file/getQuestionInDir.js
new file mode 100644
index 0000000..75d46da
--- /dev/null
+++ b/common/utils/file/getQuestionInDir.js
@@ -0,0 +1,15 @@
+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/logger/logger.js b/common/utils/logger/logger.js
index 40f442d..71494f6 100644
--- a/common/utils/logger/logger.js
+++ b/common/utils/logger/logger.js
@@ -1,24 +1,39 @@
import chalk from 'chalk'
import { getStore } from '#common/utils/store/controller/store.js'
-class Logger {
- constructor(env) {
- console.log(
- chalk.bgGray(`[logger init] The current env is ${env ?? 'not plugin'}.`)
- )
+class LOGGER {
+ constructor(_env) {
+ // console.log(
+ // chalk.bgGray(`[logger init] The current env is ${env ?? 'not plugin'}.`)
+ // )
}
- info(message) {
- console.log(chalk.blue(message))
+ /**
+ * 普通消息
+ * @param message{*}
+ * @param args{*[]}
+ */
+ info(message, ...args) {
+ console.log(chalk.blue(message, ...args))
}
- warn(message) {
- console.log(chalk.yellow(message))
+ /**
+ * 警告
+ * @param message{*}
+ * @param args{*[]}
+ */
+ warn(message, ...args) {
+ console.log(chalk.yellow(message, ...args))
}
- error(message) {
- console.log(chalk.red(message))
+ /**
+ * 错误信息
+ * @param message{*}
+ * @param args{*[]}
+ */
+ error(message, ...args) {
+ console.log(chalk.red(message, ...args))
}
}
const { env = null } = (await getStore('config')) ?? {}
-export const logger = new Logger(env)
+export const logger = new LOGGER(env)
diff --git a/common/utils/question-getter/getStudyPlanList.js b/common/utils/question-getter/getStudyPlanList.js
index e1cc5fd..ad6efba 100644
--- a/common/utils/question-getter/getStudyPlanList.js
+++ b/common/utils/question-getter/getStudyPlanList.js
@@ -1,10 +1,12 @@
import { graphql } from '#common/utils/http/graphql.js'
import { getStudyPlanListJson } from '#resources/headers/studyPlanListJson.js'
-export async function getStudyPlanList() {
- const res = await graphql(getStudyPlanListJson())
+export async function getStudyPlanList(type) {
+ const res = await graphql(getStudyPlanListJson(type))
const {
- data: { studyPlansV2AdQuestionPage }
+ data: {
+ studyPlansV2ByCatalog: { studyPlans }
+ }
} = res
- return studyPlansV2AdQuestionPage
+ return studyPlans
}
diff --git a/common/utils/question-handler/checkQuestion.js b/common/utils/question-handler/checkQuestionByPath.js
similarity index 91%
rename from common/utils/question-handler/checkQuestion.js
rename to common/utils/question-handler/checkQuestionByPath.js
index 43f5393..cdbe42f 100644
--- a/common/utils/question-handler/checkQuestion.js
+++ b/common/utils/question-handler/checkQuestionByPath.js
@@ -18,7 +18,7 @@ export function executeScript(filePath, context) {
* 执行问题检测进程
* @param path
*/
-export async function checkQuestion(path) {
+export async function checkQuestionByPath(path) {
return await executeScript(
path,
vm.createContext({
diff --git a/common/utils/question-handler/code.js b/common/utils/question-handler/code.js
index 04469a8..125d6fb 100644
--- a/common/utils/question-handler/code.js
+++ b/common/utils/question-handler/code.js
@@ -14,7 +14,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
}
/**
* 获取支持的代码语言
diff --git a/common/utils/question-handler/getHot100QuestionListCode.js b/common/utils/question-handler/getHot100QuestionListCode.js
deleted file mode 100644
index d3a6d8b..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 { getPlanQuestionList } from '#common/utils/question-getter/getPlanQuestionList.js'
-
-// 获取题目列表
-export async function getTitleSlugList() {
- const res = await getPlanQuestionList()
- 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/getQuestionListCodeBySlug.js b/common/utils/question-handler/getQuestionListCodeBySlug.js
new file mode 100644
index 0000000..b2193b7
--- /dev/null
+++ b/common/utils/question-handler/getQuestionListCodeBySlug.js
@@ -0,0 +1,24 @@
+import { createQuestionByTitleSlug } from '#common/utils/cli-utils/createQuestion.js'
+import { getPlanQuestionList } from '#common/utils/question-getter/getPlanQuestionList.js'
+
+// 获取创建promise列表
+async function createCreatePromiseList(slugList, baseDir = process.cwd()) {
+ return slugList.map((titleSlug) => {
+ return createQuestionByTitleSlug(titleSlug, 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 createCreatePromiseList(questionTitleList, baseDir)
+ return await Promise.allSettled(promiseList)
+}
diff --git a/common/view/check.view.js b/common/view/check.view.js
index 4894a37..f16d4d7 100644
--- a/common/view/check.view.js
+++ b/common/view/check.view.js
@@ -3,7 +3,7 @@ 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 { checkQuestionByPath } from '#common/utils/question-handler/checkQuestionByPath.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'
@@ -66,7 +66,7 @@ export async function easyCheckView() {
]
const { newDir } = await inquirer.prompt(newDirQuestion, null)
if (!newDir) {
- logger.info('[LK-LOG]用户终止操作~')
+ logger.info('[LK-logger]用户终止操作~')
process.exit(0)
}
questionDir = path.join(
@@ -96,7 +96,7 @@ export async function easyCheckView() {
)
}
const filePath = path.join(questionDir, `question${question.lang}`)
- await checkQuestion(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 332c9e7..0e9eacf 100644
--- a/common/view/create.view.js
+++ b/common/view/create.view.js
@@ -9,7 +9,7 @@ import { createQuestionCopy } from '#common/utils/question-handler/createQuestio
import { setQuestion } from '#common/utils/store/controller/question.js'
import { logger } from '#common/utils/logger/logger.js'
-export async function easyCreateView() {
+export async function easyCreateView(baseDir = process.cwd()) {
const modeQuestion = [
{
type: 'list',
@@ -47,14 +47,13 @@ export async function easyCreateView() {
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)
@@ -63,18 +62,15 @@ export async function easyCreateView() {
{
type: 'input',
name: 'newDir',
- message: `请选择新目录(基础地址为${process.cwd()})[按回车[Enter]终止操作]:`
+ message: `请选择新目录(基础地址为${baseDir})[按回车[Enter]终止操作]:`
}
]
const { newDir } = await inquirer.prompt(newDirQuestion, null)
if (!newDir) {
- logger.info('[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)
diff --git a/common/view/finder.view.js b/common/view/finder.view.js
index 4452e11..66d6818 100644
--- a/common/view/finder.view.js
+++ b/common/view/finder.view.js
@@ -1,31 +1,49 @@
-import select from '@inquirer/select'
+import path from 'node:path'
+import select, { Separator } from '@inquirer/select'
import input from '@inquirer/input'
-
-// import { getHot100QuestionListCode } from '#common/utils/question-handler/getHot100QuestionListCode.js'
import {
createQuestionById,
createQuestionByTitleSlug
-} from '#common/utils/create-check/createUtil.js'
+} from '#common/utils/cli-utils/createQuestion.js'
import { getQuestionByKeyword } from '#common/utils/question-getter/getQuestionByKeyword.js'
import { getStudyPlanList } from '#common/utils/question-getter/getStudyPlanList.js'
import { getPlanQuestionList } from '#common/utils/question-getter/getPlanQuestionList.js'
import { logger } from '#common/utils/logger/logger.js'
+import { getQuestionListCodeBySlug } from '#common/utils/question-handler/getQuestionListCodeBySlug.js'
+
+function handleQuestionList(list) {
+ return list.map((item) => ({
+ name: `${item.name}${item.premiumOnly ? '(VIP)' : ''}`,
+ value: item.slug
+ }))
+}
async function studyMode(baseDir = process.cwd()) {
- const questionList = await getStudyPlanList()
+ 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.map((item) => ({
- name: `${item.name}${item.premiumOnly ? '(VIP)' : ''}`,
- value: item.slug
- }))
+ 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') {
@@ -46,14 +64,19 @@ async function studyMode(baseDir = process.cwd()) {
choices: planList.map((res) => ({
name: res.cnTitle,
value: res.enTitle
- }))
+ })),
+ pageSize: 30
}
const singleChoice = await select(singleMode)
await createQuestionByTitleSlug(singleChoice, baseDir)
}
- if (createMode === 'all') logger.warn('暂不支持')
- // await getHot100QuestionListCode()
+ if (createMode === 'all') {
+ await getQuestionListCodeBySlug(
+ planSlug,
+ path.resolve(baseDir, planSlug.toString())
+ )
+ }
}
async function keywordMode(baseDir = process.cwd()) {
diff --git a/common/view/update.view.js b/common/view/update.view.js
index c60431c..666dd90 100644
--- a/common/view/update.view.js
+++ b/common/view/update.view.js
@@ -18,9 +18,9 @@ export async function easyUpdateView() {
const { choseEnv } = await inquirer.prompt(envQuestion, null)
// 2. 检测版本更新
const {
- localVersion,
- npmVersion,
- githubVersion,
+ localVersion = '未检出',
+ npmVersion = '未检出',
+ githubVersion = '未检出',
isCliUpdate,
isGithubUpdate
} = await checkUpdate()
diff --git a/package.json b/package.json
index cc396e1..f636882 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "leetcode-practice",
"type": "module",
- "version": "1.0.7",
+ "version": "1.0.8",
"packageManager": "yarn@1.22.0",
"description": "A powerful practice platform for leetcode.Using any way you want to create questions.",
"author": {
@@ -43,7 +43,8 @@
"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",
@@ -57,22 +58,22 @@
},
"devDependencies": {
"@antfu/eslint-config": "^2.8.0",
- "@commitlint/cli": "^17.0.3",
- "@commitlint/config-conventional": "^17.0.3",
+ "@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",
"@vitest/coverage-v8": "^1.2.2",
"commitizen": "^4.2.5",
"cz-conventional-changelog": "^3.3.0",
- "eslint-plugin-prettier": "^5.1.3",
"esbuild": "^0.20.0",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-prettier": "^5.1.3",
"gradient-string": "^2.0.2",
- "husky": "^8.0.1",
+ "husky": "^9.0.11",
"lint-staged": "^15.2.2",
"prettier": "^3.2.5",
"release-it": "^17.1.1",
diff --git a/resources/headers/studyPlanListJson.js b/resources/headers/studyPlanListJson.js
index ef910a7..b33bd44 100644
--- a/resources/headers/studyPlanListJson.js
+++ b/resources/headers/studyPlanListJson.js
@@ -1,7 +1,10 @@
-export function getStudyPlanListJson() {
+// 'sprint-interview-company' // 名企面试 · 突击备战
+// 'cracking-coding-interview' // 面试准备 · 全面通关
+// 'deep-dive-topics' // 专项计划 · 深入学习
+export function getStudyPlanListJson(type) {
return {
headers: { 'content-type': 'application/json' },
- body: '{"query":"\\n query GetProblemSetStudyPlanAds {\\n studyPlansV2AdQuestionPage {\\n cover\\n highlight\\n name\\n onGoing\\n premiumOnly\\n questionNum\\n slug\\n }\\n}\\n ","variables":{},"operationName":"GetProblemSetStudyPlanAds"}',
+ 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'
}
}