From 3f0714dcd09d9eb0d98b0a63743238f7711128a3 Mon Sep 17 00:00:00 2001 From: EternalHeart <48346853+wh131462@users.noreply.github.com> Date: Fri, 15 Mar 2024 10:50:23 +0800 Subject: [PATCH 1/4] chore: update release-it json (#55) * docs: update the condition for rebase on dev and explain * chore: update release-it json --- .release-it.json | 2 +- CHANGELOG.md | 5 +---- CONTRIBUTORS.md | 10 +++++++--- CONTRIBUTORS_CN.md | 6 +++++- package.json | 1 - 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.release-it.json b/.release-it.json index e80d5b4..c5d28fb 100644 --- a/.release-it.json +++ b/.release-it.json @@ -15,7 +15,7 @@ "publish": false }, "hooks": { - "after:bump": "prettier --write CHANGELOG.md && git add CHANGELOG.md ", + "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": { diff --git a/CHANGELOG.md b/CHANGELOG.md index d58031c..0e5269d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,8 @@ - - ## [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)) +- 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) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 506fc42..95d2b02 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,11 +14,15 @@ Do not develop on the `master` branch. The `master` branch is only for merging p 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 +## 3. About Feature Branches and Dev Branch -By default, feature and fix branches will be deleted after being merged into `master` via pull request. +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 will not be deleted. +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 diff --git a/CONTRIBUTORS_CN.md b/CONTRIBUTORS_CN.md index bb2cf75..40761c1 100644 --- a/CONTRIBUTORS_CN.md +++ b/CONTRIBUTORS_CN.md @@ -18,7 +18,11 @@ 默认`特性分支`和`修复分支`提交`pr`合并到`master`之后,会进行`删除`分支. -`dev`分支不会进行删除. +`dev`分支不会进行删除,但是在其上开发的时候,请先进行`git rebase master`同步主分支(因为`主分支`接受`特性分支`和`修复分支`的`合并`,所以会出现`master分支`早于`dev分支`的情况). + +## 4. rebase同步操作说明 + +在进行对`主仓库的同步`的时候,使用`rebase`解决完成`冲突`之后,使用`git status`你会发现出现`pull [数字]`和`push [数字]`标识,其含义为`落后`和`领先`远程分支的记录数, 这种是`rebase`产生的`正常情况`,在这个时候需要执行`git push -f`对远端进行`强制推送`,实现`同步`master分支,就不会产生多余的commit了. ## 参考信息 diff --git a/package.json b/package.json index 34a1dcf..6a73cd9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "leetcode-practice", "type": "module", "version": "1.0.9-4", - "packageManager": "yarn@1.22.0", "description": "A powerful practice platform for leetcode.Using any way you want to create questions.", "author": { "name": "EternalHeart", From f72a281faa613024ba94e356a2a8d17ed9089f2b Mon Sep 17 00:00:00 2001 From: EternalHeart <48346853+wh131462@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:03:55 +0800 Subject: [PATCH 2/4] feat: lc -a and lf and store all question (#67) * feat(update): check update when first run lc and will be not allow until one day * fix: fix the hidden check update * docs: instead of incorrect symble * chore: remove unsless code (#45) * docs: add contributors markdown * ci(release): modify ci to release when tag add and change the release-it to create new branch * feat(update): check update when first run lc and will be not allow until one day * chore(release): set new branch by correct command * docs: update QRCode (#39) * docs: simplified doc * chore: release v1.0.9-0 * fix: fix the hidden check update * chore: remove unsless code --------- Co-authored-by: thinkasany <480968828@qq.com> * docs: simplifying the npm install command (#44) * ci(test): update file name (#46) * docs: add ci and npm badge (#47) * ci: update name (#48) * chore(pre-commit): modify command (#49) * feat: add get question tag type api * fix: finder error * feat(update): check update when first run lc and will be not allow until one day * fix: fix the hidden check update * feat: add getAllQuestion api * feat: add all question store * feat: add lc all option * fix: allQuestion controller * fix: allQuestion realm data structure * chore: fix update error info * chore: finish lc -a and store get set question by all question store * fix: delete the list of irrelevant questions from the front end * feat: get 'jsonExampleTestcases', 'exampleTestcases' * chore: change jsdoc for function * fix(lk): fix the lk in specified directory fix #61 * chore: prettier add print width * fix(lc): fix the process to handle the question has no enough data fix #60 * perf(allquestion): modify the controller to get/set preferly fix #63 * feat lf command select mode (#65) * feat: add lf select mode --------- Co-authored-by: thinkasany <480968828@qq.com> Co-authored-by: SmallTeddy Co-authored-by: SmallTeddy <61453917+SmallTeddy@users.noreply.github.com> Co-authored-by: hyfree-msi --- .commitlintrc.cjs | 4 +- .eslintrc.js | 44 +- .github/dependabot.yml | 8 +- .github/workflows/ci.yml | 24 +- .github/workflows/contributors.yml | 32 +- .github/workflows/pr-add-label.yml | 36 +- .github/workflows/release-cli.yml | 36 +- .prettierrc | 19 +- .release-it.json | 54 +- CHANGELOG.md | 416 +++++++-------- TO-DO.md | 78 +-- bin/lc.js | 121 ++--- bin/lf.js | 53 +- bin/lk.js | 278 +++++----- common/constants/date.const.js | 12 +- common/constants/manager.const.js | 10 +- common/constants/question.const.js | 18 +- common/origin/checkUpdate.js | 40 +- common/structures/ListNode.js | 36 +- common/structures/Node.js | 92 ++-- common/structures/TreeNode.js | 78 +-- common/utils/cli-utils/commonMode.js | 89 ++-- common/utils/cli-utils/create.js | 40 +- common/utils/cli-utils/createQuestion.js | 23 +- common/utils/cli-utils/getArgs.js | 16 +- common/utils/cli-utils/referMode.js | 8 +- common/utils/etc/checkEnv.js | 8 +- common/utils/etc/createColorFont.js | 24 +- common/utils/etc/open.js | 36 +- common/utils/etc/typeof_.js | 4 +- common/utils/etc/willUse.js | 2 +- common/utils/file/getCountBySameName.js | 4 +- common/utils/file/getDirname.js | 8 +- common/utils/file/getFileListBySameName.js | 4 +- common/utils/file/getFilePathById.js | 10 +- common/utils/file/getLineNumberByContent.js | 49 +- common/utils/file/getQuestionInDir.js | 12 +- common/utils/file/getRootPath.js | 11 +- common/utils/file/parseFilePath.js | 4 +- common/utils/functions/isSameData.js | 40 +- common/utils/functions/removeDomTags.js | 14 +- common/utils/functions/sizeUtil.js | 26 +- common/utils/http/fetch_.js | 10 +- common/utils/http/graphql.js | 6 +- common/utils/http/submit.js | 6 +- common/utils/http/urlJoin.js | 12 +- common/utils/loading/loading.js | 56 +- common/utils/logger/logger.js | 104 ++-- .../question-getter/getAllQuestionList.js | 22 + .../question-getter/getPlanQuestionList.js | 14 +- .../utils/question-getter/getQuestionById.js | 26 +- .../question-getter/getQuestionByKeyword.js | 8 +- .../question-getter/getQuestionCodeList.js | 8 +- .../getQuestionLanguageList.js | 8 +- .../utils/question-getter/getQuestionList.js | 12 +- .../question-getter/getQuestionRandom.js | 20 +- .../question-getter/getQuestionTagType.js | 8 + .../utils/question-getter/getQuestionToday.js | 16 +- .../utils/question-getter/getQuestionTypes.js | 12 +- .../utils/question-getter/getStudyPlanList.js | 18 +- .../question-handler/checkQuestionByPath.js | 26 +- common/utils/question-handler/code.js | 49 +- .../utils/question-handler/createMarkdown.js | 11 +- .../utils/question-handler/createQuestion.js | 67 ++- .../question-handler/createQuestionCopy.js | 26 +- .../utils/question-handler/fulfillQuestion.js | 60 +-- .../utils/question-handler/getConsoleText.js | 13 +- .../getQuestionChineseName.js | 2 +- .../question-handler/getQuestionDetail.js | 40 +- .../question-handler/getQuestionFileName.js | 4 +- .../question-handler/getQuestionIdBySlug.js | 37 +- .../question-handler/getQuestionListCodeBy.js | 41 ++ .../getQuestionListCodeBySlug.js | 24 - .../utils/question-handler/getQuestionUrl.js | 2 +- common/utils/question-handler/getRandomId.js | 74 ++- common/utils/question-handler/getTestCase.js | 111 ++-- .../utils/question-handler/parseStructure.js | 68 +-- .../question-handler/questionLanguage.js | 493 +++++++++--------- common/utils/question-handler/showLogs.js | 119 ++--- common/utils/store/controller/allQuestion.js | 94 ++++ common/utils/store/controller/question.js | 50 +- common/utils/store/controller/store.js | 98 ++-- common/utils/store/schemas/allQuestion.js | 26 + common/utils/store/schemas/question.js | 38 +- common/utils/store/schemas/store.js | 20 +- common/utils/store/store-realm.js | 67 +-- common/utils/update/update.js | 99 ++-- common/utils/update/updateByEnv.js | 14 +- common/view/check.view.js | 182 +++---- common/view/create.view.js | 148 +++--- common/view/finder.view.js | 273 ++++++---- common/view/language.view.js | 40 +- common/view/update.view.js | 58 +-- esbuild.config.js | 164 +++--- eslint.config.js | 18 +- jsconfig.json | 12 +- package.json | 182 +++---- .../headers/allQuestionRequestUrlJson.js | 7 + resources/headers/codeSubmitJson.js | 10 +- resources/headers/planQuestionListJson.js | 10 +- resources/headers/questionCodeListJson.js | 10 +- resources/headers/questionDetailJson.js | 10 +- resources/headers/questionLanguageListJson.js | 10 +- resources/headers/questionListJson.js | 10 +- resources/headers/questionSearchJson.js | 10 +- resources/headers/questionTagTypeJson.js | 7 + resources/headers/questionTodayJson.js | 10 +- resources/headers/questionTypeJson.js | 10 +- resources/headers/studyPlanListJson.js | 10 +- resources/template/template.js | 2 +- resources/text/aim.js | 2 +- resources/text/art-font-logo.js | 2 +- resources/text/description.js | 2 +- resources/text/examples.js | 6 +- resources/text/love.js | 2 +- scripts/create-color-font.js | 20 +- scripts/loading.js | 6 +- test/create.spec.js | 118 ++--- test/graph.spec.js | 70 +-- test/listNode.spec.js | 56 +- test/parseFilePath.spec.js | 9 - test/paseDataStructure.spec.js | 48 +- test/setDataStructure.spec.js | 16 +- test/tree.spec.js | 58 +-- 124 files changed, 2869 insertions(+), 2799 deletions(-) create mode 100644 common/utils/question-getter/getAllQuestionList.js create mode 100644 common/utils/question-getter/getQuestionTagType.js create mode 100644 common/utils/question-handler/getQuestionListCodeBy.js delete mode 100644 common/utils/question-handler/getQuestionListCodeBySlug.js create mode 100644 common/utils/store/controller/allQuestion.js create mode 100644 common/utils/store/schemas/allQuestion.js create mode 100644 resources/headers/allQuestionRequestUrlJson.js create mode 100644 resources/headers/questionTagTypeJson.js delete mode 100644 test/parseFilePath.spec.js diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs index a4f4369..a989bfc 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..fe18778 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,23 +1,23 @@ module.exports = { - env: { - browser: true, - commonjs: true, - es2021: true - }, - extends: '@antfu', - overrides: [ - { - env: { - node: true - }, - files: ['.eslintrc.{js,cjs}'], - parserOptions: { - sourceType: 'script' - } - } - ], - parserOptions: { - ecmaVersion: 'latest' - }, - rules: {} -} + env: { + browser: true, + commonjs: true, + es2021: true + }, + extends: '@antfu', + overrides: [ + { + env: { + node: true + }, + files: ['.eslintrc.{js,cjs}'], + parserOptions: { + sourceType: 'script' + } + } + ], + parserOptions: { + ecmaVersion: 'latest' + }, + rules: {} +}; diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2d9cac1..d418754 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: npm # See documentation for possible values - directory: / # Location of package manifests - schedule: - interval: weekly + - package-ecosystem: npm # See documentation for possible values + directory: / # Location of package manifests + schedule: + interval: weekly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08a925d..0ebff98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,18 +3,18 @@ name: ci on: [push, pull_request] jobs: - ci: - runs-on: ubuntu-latest + ci: + runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 + steps: + - uses: actions/checkout@v3 - - name: Use Node.js 20.x - uses: actions/setup-node@v3 - with: - node-version: 20.x + - name: Use Node.js 20.x + uses: actions/setup-node@v3 + with: + node-version: 20.x - - name: ci - run: | - npm install - npm run test + - name: ci + run: | + npm install + npm run test diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 0d7b46e..1e2c6d7 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -1,21 +1,21 @@ name: gen-org-contributors on: - schedule: - - cron: '0 0 * * *' - workflow_dispatch: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: jobs: - generate: - runs-on: ubuntu-latest - if: github.repository == 'EternalHeartTeam/leetcode-practice' - steps: - - uses: thinkasany/organize-contributors@master - with: - organize_name: EternalHeartTeam - github_token: ${{ secrets.ACTION_TOKEN }} - png_path: images/contributors.png - json_path: contributors.json - branch: svg - commit_message: 'chore: update contributors' - excludes_list: 'ImgBotApp,github-actions[bot],actions-user,imgbot[bot],dependabot[bot]' + generate: + runs-on: ubuntu-latest + if: github.repository == 'EternalHeartTeam/leetcode-practice' + steps: + - uses: thinkasany/organize-contributors@master + with: + organize_name: EternalHeartTeam + github_token: ${{ secrets.ACTION_TOKEN }} + png_path: images/contributors.png + json_path: contributors.json + branch: svg + commit_message: 'chore: update contributors' + excludes_list: 'ImgBotApp,github-actions[bot],actions-user,imgbot[bot],dependabot[bot]' diff --git a/.github/workflows/pr-add-label.yml b/.github/workflows/pr-add-label.yml index e3e8cae..3c1b62a 100644 --- a/.github/workflows/pr-add-label.yml +++ b/.github/workflows/pr-add-label.yml @@ -1,24 +1,24 @@ name: pr-add-label on: - pull_request_target: - types: [opened, edited, reopened, synchronize] + pull_request_target: + types: [opened, edited, reopened, synchronize] jobs: - add-label: - permissions: - contents: read - pull-requests: write - runs-on: ubuntu-latest - steps: - - name: Check PR number - id: pr_number - run: echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV + add-label: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Check PR number + id: pr_number + run: echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV - - name: Run add-label Action - uses: thinkasany/pr-label-action@master - with: - github_token: ${{ secrets.ACTION_TOKEN }} - pr_number: ${{ env.PR_NUMBER }} - organize_name: EternalHeartTeam - team_name: eternalheartteam + - name: Run add-label Action + uses: thinkasany/pr-label-action@master + with: + github_token: ${{ secrets.ACTION_TOKEN }} + pr_number: ${{ env.PR_NUMBER }} + organize_name: EternalHeartTeam + team_name: eternalheartteam diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index df27140..82e014e 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -1,23 +1,23 @@ name: Create Cli Release on: - push: - tags: - - 'cli-v*' + push: + tags: + - 'cli-v*' jobs: - build: - runs-on: ubuntu-latest - if: github.repository == 'EternalHeartTeam/leetcode-practice' - steps: - - uses: actions/checkout@v3 - # Setup .npmrc file to publish to npm - - uses: actions/setup-node@v3 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' - - run: npm install - - run: npm run build-cli - - run: npm run publish-cli - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} + build: + runs-on: ubuntu-latest + if: github.repository == 'EternalHeartTeam/leetcode-practice' + steps: + - uses: actions/checkout@v3 + # Setup .npmrc file to publish to npm + - uses: actions/setup-node@v3 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + - run: npm install + - run: npm run build-cli + - run: npm run publish-cli + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 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 c5d28fb..0758eca 100644 --- a/.release-it.json +++ b/.release-it.json @@ -1,31 +1,31 @@ { - "github": { - "release": true, - "web": true, - "autoGenerate": true - }, - "git": { - "commitMessage": "chore: release v${version}", - "tagName": "cli-v${version}", - "tag": true, - "push": true, - "pushArgs": ["--follow-tags"] - }, - "npm": { - "publish": false - }, - "hooks": { - "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": { - "preset": "angular" + "github": { + "release": true, + "web": true, + "autoGenerate": true }, - "@release-it/conventional-changelog": { - "preset": "angular", - "infile": "CHANGELOG.md", - "ignoreRecommendedBump": true + "git": { + "commitMessage": "chore: release v${version}", + "tagName": "cli-v${version}", + "tag": true, + "push": true, + "pushArgs": ["--follow-tags"] + }, + "npm": { + "publish": false + }, + "hooks": { + "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": { + "preset": "angular" + }, + "@release-it/conventional-changelog": { + "preset": "angular", + "infile": "CHANGELOG.md", + "ignoreRecommendedBump": true + } } - } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e5269d..a50a52b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,191 +2,191 @@ ### Features -- ora loading ([#54](https://github.com/wh131462/leetcode-practice/issues/54)) ([b604316](https://github.com/wh131462/leetcode-practice/commit/b6043167752a74582e8d095721cf5b3849951e06)) +- 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 -- fix check info log ([#52](https://github.com/wh131462/leetcode-practice/issues/52)) ([6b710a1](https://github.com/wh131462/leetcode-practice/commit/6b710a1a2ff088d9806d33153bf811e5a5e19306)) +- 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) ### 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)) +- add loading and logger on/off ([#51](https://github.com/wh131462/leetcode-practice/issues/51)) ([bbff9b1](https://github.com/wh131462/leetcode-practice/commit/bbff9b1b80aea18255b089c5ad9c836bcbd18dae)) ## [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 -- 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) +- 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 -- check update with first lc run ([#41](https://github.com/wh131462/leetcode-practice/issues/41)) ([81a1439](https://github.com/wh131462/leetcode-practice/commit/81a1439cb970aa2cfe552ec70b8d1ad3ee9bbab7)) +- 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) ### Bug Fixes -- page size ([f3fd27c](https://github.com/wh131462/leetcode-practice/commit/f3fd27cc31a4d82dc9e8641a865a750b173f43f5)) -- page size ([1905454](https://github.com/wh131462/leetcode-practice/commit/1905454d71ece043da1badc3a604c72f23995ae5)) +- 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)) +- 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) ### Bug Fixes -- realm-compatible-problem ([#25](https://github.com/wh131462/leetcode-practice/issues/25)) ([d2d37d6](https://github.com/wh131462/leetcode-practice/commit/d2d37d68e6405507340b115d55bec15e070cf3ba)) +- 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)) +- 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) ### 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)) +- 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)) +- 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)) -- **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)) +- 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)) +- 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) @@ -196,148 +196,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/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 d0000a2..d36d68d 100755 --- a/bin/lc.js +++ b/bin/lc.js @@ -1,67 +1,72 @@ #! /usr/bin/env node -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/cli-utils/referMode.js' -import { getArgs } from '#common/utils/cli-utils/getArgs.js' -import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' +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/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 { getAllQuestionList } from '#common/utils/question-getter/getAllQuestionList.js'; +import { easyCreateView } from '#common/view/create.view.js'; +import { description } from '#resources/text/description.js'; +import { DefaultVer } from '#common/constants/question.const.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'; +import { setAllQuestion } from '#common/utils/store/controller/allQuestion.js'; +import { logger } from '#common/utils/logger/logger.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 { DefaultVer } from '#common/constants/question.const.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 +const version = process.env.VERSION ?? DefaultVer; program - .version(version) - .description(`${description}\n${artFontLogo}\n${aim}`) - .addHelpText('after', lcExamples + love) - .arguments('[identity]') - .option('-t, --today', 'Get a question today.') - .option('-i, --identity ', 'Specify a question by identity.') - .option('-r, --random', 'Get a question randomly.') - .option('-e, --easy', 'Use easy mode.') - .option('-d, --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.' - ) - .parse(process.argv) + .version(version) + .description(`${description}\n${artFontLogo}\n${aim}`) + .addHelpText('after', lcExamples + love) + .arguments('[identity]') + .option('-t, --today', 'Get a question today.') + .option('-i, --identity ', 'Specify a question by identity.') + .option('-r, --random', 'Get a question randomly.') + .option('-e, --easy', 'Use easy mode.') + .option('-d, --directory ', 'Set the question directory.') + .option('-l, --language [language]', 'Set/Get the code language of question.') + .option('-a, --all', 'Get all questions.') + .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 cmdArgs = program.args; +const cmdOpts = program.opts(); // 通用参数执行 -const baseDir = await commonMode(cmdOpts, easyCreateView) +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) - } -} + 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); + }, + all: async () => { + const allQuestionData = await getAllQuestionList(); + await setAllQuestion(allQuestionData); + logger.info('拉取全部题目成功!'); + process.exit(0); + } +}; // 获取模式和参数 -const mode = referMode(cmdArgs, cmdOpts) -const args = getArgs(mode, cmdArgs, cmdOpts) +const mode = referMode(cmdArgs, cmdOpts); +const args = getArgs(mode, cmdArgs, cmdOpts); // 执行指令分发 -await callModeAction[mode](args) +await callModeAction[mode](args); diff --git a/bin/lf.js b/bin/lf.js index 47ccdb4..4531419 100755 --- a/bin/lf.js +++ b/bin/lf.js @@ -1,33 +1,30 @@ #! /usr/bin/env node -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 { 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' +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 { 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 +const version = process.env.VERSION ?? DefaultVer; program - .version(version) - .description(`${description}\n${artFontLogo}\n${aim}`) - .addHelpText('after', lfExamples + love) - .option('-e, --easy', 'Use easy mode.') - .option('-d, --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.' - ) - .parse(process.argv) + .version(version) + .description(`${description}\n${artFontLogo}\n${aim}`) + .addHelpText('after', lfExamples + love) + .option('-e, --easy', 'Use easy mode.') + .option('-d, --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.') + .parse(process.argv); -const cmdArgs = program.args -const cmdOpts = program.opts() +const cmdArgs = program.args; +const cmdOpts = program.opts(); // 通用参数执行 -const baseDir = await commonMode(cmdOpts, easyFinderView) -await easyFinderView(baseDir) -willUse(cmdArgs, baseDir) -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 cf31de7..e9da5c3 100755 --- a/bin/lk.js +++ b/bin/lk.js @@ -1,161 +1,145 @@ #! /usr/bin/env node -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/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 { 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 { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.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' +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/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 { 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 { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.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 +const version = process.env.VERSION ?? DefaultVer; program - .version(version) - .description(`${description}\n${artFontLogo}\n${aim}`) - .addHelpText('after', lkExamples + love) - .arguments('[identity]') - .option('-t, --today', 'Check the question today.') - .option( - '-i, --identity ', - 'Check the specified question by identity.' - ) - .option('-r, --random', 'Check the last random question.') - .option('-e, --easy', 'Use easy mode.') - .option('-d, --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.' - ) - .parse(process.argv) + .version(version) + .description(`${description}\n${artFontLogo}\n${aim}`) + .addHelpText('after', lkExamples + love) + .arguments('[identity]') + .option('-t, --today', 'Check the question today.') + .option('-i, --identity ', 'Check the specified question by identity.') + .option('-r, --random', 'Check the last random question.') + .option('-e, --easy', 'Use easy mode.') + .option('-d, --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.') + .parse(process.argv); -const cmdArgs = program.args -const cmdOpts = program.opts() +const cmdArgs = program.args; +const cmdOpts = program.opts(); // 获取模式和参数 -const mode = referMode(cmdArgs, cmdOpts) -const args = getArgs(mode, cmdArgs, cmdOpts) +const mode = referMode(cmdArgs, cmdOpts); +const args = getArgs(mode, cmdArgs, cmdOpts); // 通用参数执行 -const baseDir = await commonMode(cmdOpts, easyCheckView) +const baseDir = await commonMode(cmdOpts, easyCheckView); // 检测函数 async function check(mode, question) { - if (!question) { - logger.info('题目信息不存在,请使用lc指令进行创建~') - return false - } - const filePath = path.join( - baseDir, - getQuestionFileName(question), - `question${getQuestionFileExtension(question?.lang)}` - ) - if (!fs.existsSync(filePath)) { - logger.info(`文件[${filePath}]不存在,请确保已经创建!`) - } else { - logger.info( - `MODE: ${mode}\n题目[${getQuestionChineseName(question)}]检查结果:` - ) - await checkQuestionByPath(filePath) - } - return true + if (!question) { + logger.info('题目信息不存在,请使用lc指令进行创建~'); + return false; + } + const filePath = path.join(baseDir, getQuestionFileName(question), `question${getQuestionFileExtension(question?.lang)}`); + if (!fs.existsSync(filePath)) { + logger.info(`文件[${filePath}]不存在,请确保已经创建!`); + } else { + logger.info(`MODE: ${mode}\n题目[${getQuestionChineseName(question)}]检查结果:`); + await checkQuestionByPath(filePath); + } + return true; } // 模式对应的action const callModeAction = { - today: async () => { - const question = await getQuestionByMode('today') - await check('today', question) - process.exit(0) - }, - random: async () => { - const question = await getQuestionByMode('random') - await check('random', question) - process.exit(0) - }, - identity: async (id) => { - 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: `在当前目录下存在id为[${id}]的题目副本,请选择你要检查的副本:`, - 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) - } + today: async () => { + const question = await getQuestionByMode('today'); + await check('today', question); + process.exit(0); + }, + random: async () => { + const question = await getQuestionByMode('random'); + await check('random', question); + process.exit(0); + }, + identity: async (id) => { + 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} + */ + 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) + 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); } - process.exit(0) - } -} +}; // 执行指令分发 -callModeAction[mode](args) +callModeAction[mode](args); diff --git a/common/constants/date.const.js b/common/constants/date.const.js index c13a6d8..7fec592 100644 --- a/common/constants/date.const.js +++ b/common/constants/date.const.js @@ -1,7 +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 +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 index 179d856..107b943 100644 --- a/common/constants/manager.const.js +++ b/common/constants/manager.const.js @@ -7,11 +7,11 @@ * @constructor */ export function NpmInstall(packageName, isUpdate, isGlobal) { - return `npm ${isUpdate ? 'update' : 'install'} ${isGlobal ? '-g' : ''} ${packageName}` + return `npm ${isUpdate ? 'update' : 'install'} ${isGlobal ? '-g' : ''} ${packageName}`; } /** - * yarn 的安装指令 + * @description yarn 的安装指令 * @param packageName * @param isUpdate * @param isGlobal @@ -19,11 +19,11 @@ export function NpmInstall(packageName, isUpdate, isGlobal) { * @constructor */ export function YarnInstall(packageName, isUpdate, isGlobal) { - return `yarn ${isGlobal ? 'global' : ''} ${isUpdate ? 'upgrade' : 'add'} ${packageName}` + return `yarn ${isGlobal ? 'global' : ''} ${isUpdate ? 'upgrade' : 'add'} ${packageName}`; } /** - * pnpm 的安装指令 + * @description pnpm 的安装指令 * @param packageName * @param isUpdate * @param isGlobal @@ -31,5 +31,5 @@ export function YarnInstall(packageName, isUpdate, isGlobal) { * @constructor */ export function PnpmInstall(packageName, isUpdate, isGlobal) { - return `pnpm ${isGlobal ? 'global' : ''} ${isUpdate ? 'update' : 'install'} ${packageName}` + return `pnpm ${isGlobal ? 'global' : ''} ${isUpdate ? 'update' : 'install'} ${packageName}`; } diff --git a/common/constants/question.const.js b/common/constants/question.const.js index c630e5a..bcaee59 100644 --- a/common/constants/question.const.js +++ b/common/constants/question.const.js @@ -1,24 +1,24 @@ // region 项目相关 // 默认语言 -export const DefaultLang = 'javascript' +export const DefaultLang = 'javascript'; // 默认版本号 -export const DefaultVer = '0.0.0' +export const DefaultVer = '0.0.0'; // 包名 -export const PackageName = 'leetcode-practice' +export const PackageName = 'leetcode-practice'; // github 主账号 -export const GITHUB_HOST = 'EternalHeartTeam' +export const GITHUB_HOST = 'EternalHeartTeam'; // endregion // region 域名列表 // npm 主域名 -export const NPM_URL = 'https://registry.npmjs.org/' +export const NPM_URL = 'https://registry.npmjs.org/'; // github raw 主域名 -export const GITHUB_RAW = 'https://raw.githubusercontent.com/' +export const GITHUB_RAW = 'https://raw.githubusercontent.com/'; // github -export const GITHUB_URL = 'https://github.com/' +export const GITHUB_URL = 'https://github.com/'; // gitee -export const GITEE_URL = 'https://gitee.com/' +export const GITEE_URL = 'https://gitee.com/'; // endregion // region 实用变量 // 默认请求数据数量限制 -export const DefaultLimit = 50 +export const DefaultLimit = 50; // endregion diff --git a/common/origin/checkUpdate.js b/common/origin/checkUpdate.js index aa8d960..618bac6 100644 --- a/common/origin/checkUpdate.js +++ b/common/origin/checkUpdate.js @@ -1,27 +1,21 @@ -import { logger } from '#common/utils/logger/logger.js' -import { checkUpdate } from '#common/utils/update/update.js' -import { getStore, setStore } from '#common/utils/store/controller/store.js' -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 { checkUpdate } from '#common/utils/update/update.js'; +import { getStore, setStore } from '#common/utils/store/controller/store.js'; +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'; -const { timestamp, hasShow } = (await getStore('checkResult')) ?? {} -if (Date.now() - timestamp <= Day || hasShow) process.exit(0) +const { timestamp, hasShow } = (await getStore('checkResult')) ?? {}; +if (Date.now() - timestamp <= Day || hasShow) process.exit(0); -const { localVersion, npmVersion, isCliUpdate } = await checkUpdate() -const needShow = false +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}`) + 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) +await setStore('checkResult', { timestamp: Date.now(), hasShow: needShow }); +process.exit(0); diff --git a/common/structures/ListNode.js b/common/structures/ListNode.js index bd57e2d..32a7521 100644 --- a/common/structures/ListNode.js +++ b/common/structures/ListNode.js @@ -6,27 +6,27 @@ */ export class ListNode { - constructor(val, next) { - this.val = val === undefined ? 0 : val - this.next = next === undefined ? null : next - } + constructor(val, next) { + this.val = val === undefined ? 0 : val; + this.next = next === undefined ? null : next; + } - static parse(arr) { - if (arr.length === 0) return null // Return null for an empty array + static parse(arr) { + if (arr.length === 0) return null; // Return null for an empty array - const head = new ListNode(arr.shift(), null) - let current = head - while (arr.length > 0) { - current.next = new ListNode(arr.shift(), null) - current = current.next + const head = new ListNode(arr.shift(), null); + let current = head; + while (arr.length > 0) { + current.next = new ListNode(arr.shift(), null); + current = current.next; + } + return head; } - return head - } - static toArray(listNodes, arr = []) { - if (listNodes === undefined || listNodes === null) return arr + static toArray(listNodes, arr = []) { + if (listNodes === undefined || listNodes === null) return arr; - arr.push(listNodes.val) - return ListNode.toArray(listNodes.next, 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..810061d 100644 --- a/common/structures/Node.js +++ b/common/structures/Node.js @@ -1,53 +1,53 @@ export class Node { - constructor(val, neighbors) { - this.val = val === undefined ? 0 : val - this.neighbors = neighbors === undefined ? [] : neighbors - } - - static parse(edges) { - const nodeMap = new Map() - - // 创建节点 - const getNode = (val) => { - if (!nodeMap.has(val)) { - const newNode = new Node(val) - nodeMap.set(val, newNode) - } - return nodeMap.get(val) + constructor(val, neighbors) { + this.val = val === undefined ? 0 : val; + this.neighbors = neighbors === undefined ? [] : neighbors; } - // 连接节点 - edges.forEach((neighbors, index) => { - const val = index + 1 - const currentNode = getNode(val) - neighbors.forEach((neighborVal) => { - const neighborNode = getNode(neighborVal) - currentNode.neighbors.push(neighborNode) - }) - }) - - return nodeMap.size > 0 ? nodeMap.values().next().value : null - } - - static toArray(node) { - if (!node) return [] - - const visited = new Set() - const result = [] - - const dfs = (currentNode) => { - if (visited.has(currentNode.val)) return - - const { neighbors, val } = currentNode - visited.add(val) - result.push(neighbors.map(({ val }) => val)) - currentNode.neighbors.forEach((neighbor) => { - dfs(neighbor) - }) + static parse(edges) { + const nodeMap = new Map(); + + // 创建节点 + const getNode = (val) => { + if (!nodeMap.has(val)) { + const newNode = new Node(val); + nodeMap.set(val, newNode); + } + return nodeMap.get(val); + }; + + // 连接节点 + edges.forEach((neighbors, index) => { + const val = index + 1; + const currentNode = getNode(val); + neighbors.forEach((neighborVal) => { + const neighborNode = getNode(neighborVal); + currentNode.neighbors.push(neighborNode); + }); + }); + + return nodeMap.size > 0 ? nodeMap.values().next().value : null; } - dfs(node) + static toArray(node) { + if (!node) return []; - return result - } + const visited = new Set(); + const result = []; + + const dfs = (currentNode) => { + if (visited.has(currentNode.val)) return; + + const { neighbors, val } = currentNode; + visited.add(val); + result.push(neighbors.map(({ val }) => val)); + currentNode.neighbors.forEach((neighbor) => { + dfs(neighbor); + }); + }; + + dfs(node); + + return result; + } } diff --git a/common/structures/TreeNode.js b/common/structures/TreeNode.js index 90c4146..ed5098d 100644 --- a/common/structures/TreeNode.js +++ b/common/structures/TreeNode.js @@ -1,48 +1,48 @@ export class TreeNode { - constructor(val, left, right) { - this.left = null - this.val = val === undefined ? 0 : val - this.left = left === undefined ? null : left - this.right = right === undefined ? null : right - } + constructor(val, left, right) { + this.left = null; + this.val = val === undefined ? 0 : val; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } - static parse(arr) { - if (arr.length === 0) return null - const root = new TreeNode(arr[0]) - const queue = [root] - for (let i = 1; i < arr.length; i += 2) { - const node = queue.shift() - if (arr[i] !== null) { - node.left = new TreeNode(arr[i]) - queue.push(node.left) - } - if (arr[i + 1] !== null) { - node.right = new TreeNode(arr[i + 1]) - queue.push(node.right) - } + static parse(arr) { + if (arr.length === 0) return null; + const root = new TreeNode(arr[0]); + const queue = [root]; + for (let i = 1; i < arr.length; i += 2) { + const node = queue.shift(); + if (arr[i] !== null) { + node.left = new TreeNode(arr[i]); + queue.push(node.left); + } + if (arr[i + 1] !== null) { + node.right = new TreeNode(arr[i + 1]); + queue.push(node.right); + } + } + return root; } - return root - } - static toArray(treeNode) { - const result = [] - if (!treeNode) return result + static toArray(treeNode) { + const result = []; + if (!treeNode) return result; - const queue = [treeNode] + const queue = [treeNode]; - while (queue.length > 0) { - const node = queue.shift() - if (node) { - result.push(node.val) - queue.push(node.left) - queue.push(node.right) - } else { - result.push(null) - } - } + while (queue.length > 0) { + const node = queue.shift(); + if (node) { + result.push(node.val); + queue.push(node.left); + queue.push(node.right); + } else { + result.push(null); + } + } - while (result.length > 0 && result[result.length - 1] === null) result.pop() + while (result.length > 0 && result[result.length - 1] === null) result.pop(); - return result - } + return result; + } } diff --git a/common/utils/cli-utils/commonMode.js b/common/utils/cli-utils/commonMode.js index f0571c9..9e2de68 100644 --- a/common/utils/cli-utils/commonMode.js +++ b/common/utils/cli-utils/commonMode.js @@ -1,11 +1,11 @@ -import path from 'node:path' -import { fork } from 'node:child_process' -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' -import { rootPath } from '#common/utils/file/getRootPath.js' -import { currentEnv } from '#common/utils/etc/checkEnv.js' +import path from 'node:path'; +import { fork } from 'node:child_process'; +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'; +import { rootPath } from '#common/utils/file/getRootPath.js'; +import { currentEnv } from '#common/utils/etc/checkEnv.js'; /** * 执行逻辑: @@ -20,46 +20,39 @@ import { currentEnv } from '#common/utils/etc/checkEnv.js' * @returns {Promise} */ 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) => {}) + // 启动一个额外的线程,并执行 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}`) + // 根据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); } - process.exit(0) - } - if (cmdOpts.easy) { - await easyCallback(baseDir) - process.exit(0) - } - // 检测更新 - if (cmdOpts.update) { - await easyUpdateView() - process.exit(0) - } - return baseDir + if (cmdOpts.easy) { + await easyCallback(baseDir); + process.exit(0); + } + // 检测更新 + if (cmdOpts.update) { + await easyUpdateView(); + process.exit(0); + } + return baseDir; } diff --git a/common/utils/cli-utils/create.js b/common/utils/cli-utils/create.js index 183301a..0acc7cf 100644 --- a/common/utils/cli-utils/create.js +++ b/common/utils/cli-utils/create.js @@ -1,11 +1,11 @@ -import path from 'node:path' -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 { getLineNumberByContent } from '#common/utils/file/getLineNumberByContent.js' -import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js' +import path from 'node:path'; +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 { getLineNumberByContent } from '#common/utils/file/getLineNumberByContent.js'; +import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js'; /** * 创建函数 @@ -15,17 +15,15 @@ import { getQuestionChineseName } from '#common/utils/question-handler/getQuesti * @returns {Promise} */ export function create(mode, question, baseDir) { - 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) - const line = (await getLineNumberByContent(path, '@QUESTION_START')) + 1 - logger.info( - `题目[${getQuestionChineseName(question)}]获取成功!\n题目文件地址为:file://${path}:${line}` - ) - resolve(true) - }) - }) + 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); + const line = (await getLineNumberByContent(path, '@QUESTION_START')) + 1; + logger.info(`题目[${getQuestionChineseName(question)}]获取成功!\n题目文件地址为:file://${path}:${line}`); + resolve(true); + }); + }); } diff --git a/common/utils/cli-utils/createQuestion.js b/common/utils/cli-utils/createQuestion.js index 4fde403..10aff23 100644 --- a/common/utils/cli-utils/createQuestion.js +++ b/common/utils/cli-utils/createQuestion.js @@ -1,7 +1,7 @@ -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' +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创建题目 @@ -9,12 +9,9 @@ import { create } from '#common/utils/cli-utils/create.js' * @param baseDir * @returns {Promise} */ -export async function createQuestionByTitleSlug( - titleSlug, - baseDir = process.cwd() -) { - const { question } = await getQuestionIdBySlug(titleSlug) - await createQuestionById(question.questionId, baseDir) +export async function createQuestionByTitleSlug(titleSlug, baseDir = process.cwd()) { + const { question } = await getQuestionIdBySlug(titleSlug); + await createQuestionById(question.questionId, baseDir); } /** @@ -24,7 +21,7 @@ export async function createQuestionByTitleSlug( * @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) + const question = await getQuestionById(id); + if (!question?.id) logger.warn(`指定编号: [ ${id} ] 题目不存在.`); + await create('identity', question, baseDir); } diff --git a/common/utils/cli-utils/getArgs.js b/common/utils/cli-utils/getArgs.js index e3df8cb..c0dd89e 100644 --- a/common/utils/cli-utils/getArgs.js +++ b/common/utils/cli-utils/getArgs.js @@ -1,11 +1,11 @@ // 获取模式对应的参数 export function getArgs(mode, cmdArgs, cmdOpts) { - switch (mode) { - case 'identity': - return cmdArgs.length ? cmdArgs.join(' ') : cmdOpts?.identity - case 'random': - case 'today': - default: - return null - } + switch (mode) { + case 'identity': + return cmdArgs.length ? cmdArgs.join(' ') : cmdOpts?.identity; + case 'random': + case 'today': + default: + return null; + } } diff --git a/common/utils/cli-utils/referMode.js b/common/utils/cli-utils/referMode.js index 42ff1f8..c4014e0 100644 --- a/common/utils/cli-utils/referMode.js +++ b/common/utils/cli-utils/referMode.js @@ -1,8 +1,10 @@ // 推测模式 export function referMode(args, opts) { - if (args.length > 0 || opts.identity) return 'identity' + if (args.length > 0 || opts.identity) return 'identity'; - if (opts.random) return 'random' + if (opts.random) return 'random'; - return 'today' + if (opts.all) return 'all'; + + return 'today'; } diff --git a/common/utils/etc/checkEnv.js b/common/utils/etc/checkEnv.js index fce4e63..15dfcb7 100644 --- a/common/utils/etc/checkEnv.js +++ b/common/utils/etc/checkEnv.js @@ -5,14 +5,14 @@ * project: file:///Users/mac-106/wh131462/workspace/leetcode-practice/common/utils/etc/checkEnv.js */ export function currentEnv() { - const url = import.meta.url - const projectReg = /etc\/checkEnv.js$/im - return projectReg.test(url) ? 'project' : 'cli' + const url = import.meta.url; + const projectReg = /etc\/checkEnv.js$/im; + return projectReg.test(url) ? 'project' : 'cli'; } /** * 检查npm安装时的位置 */ export function npmEnv() { - return true ? 'global' : 'module' + return true ? 'global' : 'module'; } diff --git a/common/utils/etc/createColorFont.js b/common/utils/etc/createColorFont.js index cd5eb60..d0ecd78 100644 --- a/common/utils/etc/createColorFont.js +++ b/common/utils/etc/createColorFont.js @@ -1,17 +1,15 @@ -import { writeFileSync } from 'node:fs' -import path from 'node:path' -import gradient_string from 'gradient-string' +import { writeFileSync } from 'node:fs'; +import path from 'node:path'; +import gradient_string from 'gradient-string'; // 创建渐变色字体 export function createColorFont(font) { - const code = gradient_string([ - { color: '#ff0000', pos: 0 }, - { color: '#ffc600', pos: 0.5 }, - { 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(code) + const code = gradient_string([ + { color: '#ff0000', pos: 0 }, + { color: '#ffc600', pos: 0.5 }, + { 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(code); } diff --git a/common/utils/etc/open.js b/common/utils/etc/open.js index 1289461..a3a1841 100644 --- a/common/utils/etc/open.js +++ b/common/utils/etc/open.js @@ -1,26 +1,26 @@ -import os from 'node:os' -import { exec } from 'node:child_process' -import { logger } from '#common/utils/logger/logger.js' +import os from 'node:os'; +import { exec } from 'node:child_process'; +import { logger } from '#common/utils/logger/logger.js'; -const platform = os.platform() +const platform = os.platform(); /** * 打开浏览器 * @param {string} url */ export function open(url) { - switch (platform) { - case 'darwin': - exec(`open "${url}"`) - break - case 'win32': - exec(`start "${url}"`) - break - case 'linux': - exec(`xdg-open "${url}"`) - break - default: - logger.info(`Unsupported platform: ${platform}`) - break - } + switch (platform) { + case 'darwin': + exec(`open "${url}"`); + break; + case 'win32': + exec(`start "${url}"`); + break; + case 'linux': + exec(`xdg-open "${url}"`); + break; + default: + logger.info(`Unsupported platform: ${platform}`); + break; + } } diff --git a/common/utils/etc/typeof_.js b/common/utils/etc/typeof_.js index 8d8458a..c24d18d 100644 --- a/common/utils/etc/typeof_.js +++ b/common/utils/etc/typeof_.js @@ -5,6 +5,6 @@ * @private */ export function typeof_(data) { - if (data === null) return 'null' - else return typeof data + if (data === null) return 'null'; + else return typeof data; } diff --git a/common/utils/etc/willUse.js b/common/utils/etc/willUse.js index 21d4ddb..81eb091 100644 --- a/common/utils/etc/willUse.js +++ b/common/utils/etc/willUse.js @@ -4,5 +4,5 @@ * @param args */ export function willUse(...args) { - return args + return args; } diff --git a/common/utils/file/getCountBySameName.js b/common/utils/file/getCountBySameName.js index 7966377..0d6d607 100644 --- a/common/utils/file/getCountBySameName.js +++ b/common/utils/file/getCountBySameName.js @@ -1,4 +1,4 @@ -import { readdirSync } from 'node:fs' +import { readdirSync } from 'node:fs'; /** * 根据指定的目录和文件名 给出存在的数量 @@ -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..4ac724e 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'; +import { dirname } from 'node:path'; -const __filename = fileURLToPath(import.meta.url) -export const __dirname = dirname(__filename) +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..9a9c592 100644 --- a/common/utils/file/getFileListBySameName.js +++ b/common/utils/file/getFileListBySameName.js @@ -1,5 +1,5 @@ -import { readdirSync } from 'node:fs' +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..6478171 100644 --- a/common/utils/file/getFilePathById.js +++ b/common/utils/file/getFilePathById.js @@ -1,4 +1,4 @@ -import fs from 'node:fs' +import fs from 'node:fs'; /** * 根据id获取文件的具体路径 @@ -7,8 +7,8 @@ import fs from 'node:fs' * @returns {string|undefined|string[]} */ 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 - return files?.[0] + const dir = fs.readdirSync(baseDir); + 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..a4fac7b 100644 --- a/common/utils/file/getLineNumberByContent.js +++ b/common/utils/file/getLineNumberByContent.js @@ -1,4 +1,5 @@ -import fs from 'node:fs' +import fs from 'node:fs'; +import { logger } from '#common/utils/logger/logger.js'; /** * 通过给入的文件地址和内容 给出对应的行号 @@ -7,30 +8,30 @@ import fs from 'node:fs' * @returns {Promise} */ export function getLineNumberByContent(filePath, searchString) { - return new Promise((resolve) => { - let lineNumber = 0 - const readStream = fs.createReadStream(filePath, { encoding: 'utf-8' }) + return new Promise((resolve) => { + let lineNumber = 0; + const readStream = fs.createReadStream(filePath, { encoding: 'utf-8' }); - readStream.on('data', (chunk) => { - const lines = chunk.split('\n') - for (const line of lines) { - lineNumber++ - if (line.includes(searchString)) { - readStream.close() - resolve(lineNumber) - return - } - } - }) + readStream.on('data', (chunk) => { + const lines = chunk.split('\n'); + for (const line of lines) { + lineNumber++; + if (line.includes(searchString)) { + readStream.close(); + resolve(lineNumber); + return; + } + } + }); - readStream.on('end', () => { - console.warn(`"${searchString}" not found in file: ${filePath}`) - resolve(0) - }) + readStream.on('end', () => { + logger.warn(`[WARN] "${searchString}" not found in file: ${filePath}`); + resolve(0); + }); - readStream.on('error', () => { - console.warn(`"${searchString}" not found in file: ${filePath}`) - resolve(0) - }) - }) + readStream.on('error', () => { + 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 index 75d46da..97175d0 100644 --- a/common/utils/file/getQuestionInDir.js +++ b/common/utils/file/getQuestionInDir.js @@ -1,5 +1,5 @@ -import fs from 'node:fs' -import path from 'node:path' +import fs from 'node:fs'; +import path from 'node:path'; /** * 在目录中查找题目文件 @@ -7,9 +7,7 @@ import path from 'node:path' * @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 + 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..bfd3431 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 path from 'node:path'; +import { __dirname } from '#common/utils/file/getDirname.js'; +import { currentEnv } from '#common/utils/etc/checkEnv.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/file/parseFilePath.js b/common/utils/file/parseFilePath.js index f1e189c..01b57ab 100644 --- a/common/utils/file/parseFilePath.js +++ b/common/utils/file/parseFilePath.js @@ -1,5 +1,5 @@ -import path from 'node:path' +import path from 'node:path'; export function parseFilePath(oldPath) { - return `\"${path.normalize(oldPath)}\"` + return `\"${path.normalize(oldPath)}\"`; } diff --git a/common/utils/functions/isSameData.js b/common/utils/functions/isSameData.js index b313fc6..73d5946 100644 --- a/common/utils/functions/isSameData.js +++ b/common/utils/functions/isSameData.js @@ -5,26 +5,26 @@ * @returns {this is string[]|boolean} */ export function isSameData(a, b) { - const typeA = typeof a - const typeB = typeof b - if (typeA !== typeB) return false - switch (typeA) { - case 'bigint': - case 'boolean': - case 'number': - case 'string': - case 'symbol': - case 'undefined': - return a === b - case 'function': - return a.toString() === b.toString() - case 'object': { - if (a === null || a === undefined) return a === b + const typeA = typeof a; + const typeB = typeof b; + if (typeA !== typeB) return false; + switch (typeA) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + case 'symbol': + case 'undefined': + return a === b; + case 'function': + return a.toString() === b.toString(); + case 'object': { + 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])) + 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])); + } } - } } diff --git a/common/utils/functions/removeDomTags.js b/common/utils/functions/removeDomTags.js index 0f38b86..5080c83 100644 --- a/common/utils/functions/removeDomTags.js +++ b/common/utils/functions/removeDomTags.js @@ -4,11 +4,11 @@ * @returns {string|string} */ export function removeDomTags(input) { - return input - .replace(/<[^>]*>/g, '') - .replaceAll(' ', ' ') - .replaceAll(' ', ' ') - .replaceAll('<', '<') - .replaceAll('>', '>') - .replaceAll('`', '') + return input + ?.replace(/<[^>]*>/g, '') + .replaceAll(' ', ' ') + .replaceAll(' ', ' ') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('`', ''); } diff --git a/common/utils/functions/sizeUtil.js b/common/utils/functions/sizeUtil.js index 72de534..1eba3b3 100644 --- a/common/utils/functions/sizeUtil.js +++ b/common/utils/functions/sizeUtil.js @@ -1,13 +1,13 @@ // 千 -export const KB = 1024 +export const KB = 1024; // 兆 -export const MB = 1024 * KB +export const MB = 1024 * KB; // 吉 -export const GB = 1024 * MB +export const GB = 1024 * MB; // 太 -export const TB = 1024 * GB +export const TB = 1024 * GB; // 拍 -export const PB = 1024 * GB +export const PB = 1024 * GB; /** * 获取文件的单位 @@ -15,13 +15,13 @@ 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' } + return { size: PB, label: 'PB' }; } /** * 获取文件的尺寸 @@ -29,6 +29,6 @@ export function getFileSizeUnit(size) { * @param precision 小数位 */ export function getFileSize(size, precision = 2) { - const fileSizeType = getFileSizeUnit(size) - return `${(size / fileSizeType.size).toFixed(precision)} ${fileSizeType.label}` + const fileSizeType = getFileSizeUnit(size); + return `${(size / fileSizeType.size).toFixed(precision)} ${fileSizeType.label}`; } diff --git a/common/utils/http/fetch_.js b/common/utils/http/fetch_.js index 9f67186..2182362 100644 --- a/common/utils/http/fetch_.js +++ b/common/utils/http/fetch_.js @@ -1,4 +1,4 @@ -import ora from 'ora' +import ora from 'ora'; /** * 基础请求-直接返回JSON格式的值 @@ -8,8 +8,8 @@ import ora from 'ora' * @private */ export async function fetch_(url, options) { - const loader = ora(options.loadText ?? 'loading...').start() - const resp = await fetch(url, options).then((res) => res.json()) - loader.stop() - return resp + 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/graphql.js b/common/utils/http/graphql.js index e059912..f418ad1 100644 --- a/common/utils/http/graphql.js +++ b/common/utils/http/graphql.js @@ -1,5 +1,5 @@ -import { fetch_ } from '#common/utils/http/fetch_.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'; /** * 请求 graphql @@ -8,5 +8,5 @@ import { url_join } from '#common/utils/http/urlJoin.js' * @returns {Promise} */ export async function graphql(options, host = 'https://leetcode.cn/') { - return await fetch_(url_join(host, 'graphql'), options) + return await fetch_(url_join(host, 'graphql'), options); } diff --git a/common/utils/http/submit.js b/common/utils/http/submit.js index 5f2b402..282a607 100644 --- a/common/utils/http/submit.js +++ b/common/utils/http/submit.js @@ -1,5 +1,5 @@ -import { fetch_ } from '#common/utils/http/fetch_.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'; /** * 请求 submit 提交 @@ -8,5 +8,5 @@ import { url_join } from '#common/utils/http/urlJoin.js' * @returns {Promise} */ export async function submit(options, host = 'https://leetcode.cn/') { - return await fetch_(url_join(host, 'submit'), options) + return await fetch_(url_join(host, 'submit'), options); } diff --git a/common/utils/http/urlJoin.js b/common/utils/http/urlJoin.js index 0d7ca09..daa8e6f 100644 --- a/common/utils/http/urlJoin.js +++ b/common/utils/http/urlJoin.js @@ -5,10 +5,10 @@ * @returns {string} */ export function url_join(host, ...rest) { - const host_base = host.replace(/\/$/, '') - const path = rest - .join('/') - .replace(/(\/){1,3}/gim, '/') - .replace(/^\//, '') - return [host_base, path].join('/') + const host_base = host.replace(/\/$/, ''); + const path = rest + .join('/') + .replace(/(\/){1,3}/gim, '/') + .replace(/^\//, ''); + return [host_base, path].join('/'); } diff --git a/common/utils/loading/loading.js b/common/utils/loading/loading.js index 3e12a6c..36e3522 100644 --- a/common/utils/loading/loading.js +++ b/common/utils/loading/loading.js @@ -1,36 +1,34 @@ -import chalk from 'chalk' +import chalk from 'chalk'; export class Loading { - text = 'loading...' - constructor(text) { - this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] - this.currentFrame = 0 - this.interval = null - this.text = text - } + 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}`) - ) + 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 - } + this.currentFrame++; + if (this.currentFrame === this.frames.length) this.currentFrame = 0; + }, 80); + return this; + } - stop() { - clearInterval(this.interval) - process.stdout.write('\r') // 清除动画最后一帧 - return this - } + stop() { + clearInterval(this.interval); + process.stdout.write('\r'); // 清除动画最后一帧 + return this; + } - // 在发生异常时调用此方法清除动画 - handleException() { - this.stop() - return this - } + // 在发生异常时调用此方法清除动画 + handleException() { + this.stop(); + return this; + } } diff --git a/common/utils/logger/logger.js b/common/utils/logger/logger.js index 8548352..a1c3484 100644 --- a/common/utils/logger/logger.js +++ b/common/utils/logger/logger.js @@ -1,61 +1,61 @@ -import chalk from 'chalk' -import { getStore } from '#common/utils/store/controller/store.js' +import chalk from 'chalk'; +import { getStore } from '#common/utils/store/controller/store.js'; class LOGGER { - isOn = true - constructor(_env) { - // console.log( - // chalk.bgGray(`[logger init] The current env is ${env ?? 'not plugin'}.`) - // ) - } + isOn = true; + constructor(_env) { + // console.log( + // chalk.bgGray(`[logger init] The current env is ${env ?? 'not plugin'}.`) + // ) + } - /** - * 开启 - */ - on() { - this.isOn = true - } + /** + * 开启 + */ + on() { + this.isOn = true; + } - /** - * 关闭 - */ - off() { - this.isOn = false - } + /** + * 关闭 + */ + off() { + this.isOn = false; + } - get forbidden() { - return !this.isOn - } + get forbidden() { + return !this.isOn; + } - /** - * 普通消息 - * @param message{*} - * @param args{*[]} - */ - info(message, ...args) { - if (this.forbidden) return - console.log(chalk.blue(message, ...args)) - } + /** + * 普通消息 + * @param message{*} + * @param args{*[]} + */ + info(message, ...args) { + if (this.forbidden) return; + console.log(chalk.blue(message, ...args)); + } - /** - * 警告 - * @param message{*} - * @param args{*[]} - */ - warn(message, ...args) { - if (this.forbidden) return - console.log(chalk.yellow(message, ...args)) - } + /** + * 警告 + * @param message{*} + * @param args{*[]} + */ + warn(message, ...args) { + if (this.forbidden) return; + console.log(chalk.yellow(message, ...args)); + } - /** - * 错误信息 - * @param message{*} - * @param args{*[]} - */ - error(message, ...args) { - if (this.forbidden) return - console.log(chalk.red(message, ...args)) - } + /** + * 错误信息 + * @param message{*} + * @param args{*[]} + */ + error(message, ...args) { + if (this.forbidden) return; + console.log(chalk.red(message, ...args)); + } } -const { env = null } = (await getStore('config')) ?? {} -export const logger = new LOGGER(env) +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..78ae688 --- /dev/null +++ b/common/utils/question-getter/getAllQuestionList.js @@ -0,0 +1,22 @@ +import ora from 'ora'; +import { graphql } from '#common/utils/http/graphql.js'; +import { getAllQuestionRequestUrlJson } from '#resources/headers/allQuestionRequestUrlJson.js'; + +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 index 0b5e54f..c4a8095 100644 --- a/common/utils/question-getter/getPlanQuestionList.js +++ b/common/utils/question-getter/getPlanQuestionList.js @@ -1,10 +1,10 @@ -import { graphql } from '#common/utils/http/graphql.js' -import { getPlanQuestionListJson } from '#resources/headers/planQuestionListJson.js' +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 + 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..a60b8e3 100644 --- a/common/utils/question-getter/getQuestionById.js +++ b/common/utils/question-getter/getQuestionById.js @@ -1,18 +1,16 @@ -import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' -import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js' -import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionDetail } from '../question-handler/getQuestionDetail.js'; +import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js'; +import { graphql } from '#common/utils/http/graphql.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() - ) - if (!questionContent) { - return { - id: null + const base = await graphql(getQuestionSearchJson(id.toString())); + const questionContent = base?.data?.problemsetQuestionList?.questions?.find((o) => o?.frontendQuestionId === id.toString()); + if (!questionContent) { + return { + id: null + }; } - } - const slug = questionContent.titleSlug - const question = await getQuestionDetail(slug, { id }) - return question + const slug = questionContent.titleSlug; + const question = await getQuestionDetail(slug, { id }); + return question; } diff --git a/common/utils/question-getter/getQuestionByKeyword.js b/common/utils/question-getter/getQuestionByKeyword.js index 1c1ddd5..db23d8e 100644 --- a/common/utils/question-getter/getQuestionByKeyword.js +++ b/common/utils/question-getter/getQuestionByKeyword.js @@ -1,7 +1,7 @@ -import { graphql } from '#common/utils/http/graphql.js' -import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js' +import { graphql } from '#common/utils/http/graphql.js'; +import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js'; export async function getQuestionByKeyword(keyword) { - const questionData = await graphql(getQuestionSearchJson(keyword.toString())) - return questionData?.data?.problemsetQuestionList?.questions + const questionData = await graphql(getQuestionSearchJson(keyword.toString())); + return questionData?.data?.problemsetQuestionList?.questions; } diff --git a/common/utils/question-getter/getQuestionCodeList.js b/common/utils/question-getter/getQuestionCodeList.js index 1abd2bb..54737ed 100644 --- a/common/utils/question-getter/getQuestionCodeList.js +++ b/common/utils/question-getter/getQuestionCodeList.js @@ -1,5 +1,5 @@ -import { graphql } from '#common/utils/http/graphql.js' -import { getQuestionCodeListJson } from '#resources/headers/questionCodeListJson.js' +import { graphql } from '#common/utils/http/graphql.js'; +import { getQuestionCodeListJson } from '#resources/headers/questionCodeListJson.js'; /** * 获取代码列表 @@ -7,6 +7,6 @@ import { getQuestionCodeListJson } from '#resources/headers/questionCodeListJson * @returns {Promise<*>} */ export async function getQuestionCodeList(slug) { - const res = await graphql(getQuestionCodeListJson(slug)) - return res.data.question?.codeSnippets + const res = await graphql(getQuestionCodeListJson(slug)); + return res.data.question?.codeSnippets; } diff --git a/common/utils/question-getter/getQuestionLanguageList.js b/common/utils/question-getter/getQuestionLanguageList.js index 4fe7df6..0ae8b83 100644 --- a/common/utils/question-getter/getQuestionLanguageList.js +++ b/common/utils/question-getter/getQuestionLanguageList.js @@ -1,7 +1,7 @@ -import { graphql } from '#common/utils/http/graphql.js' -import { getQuestionLanguageListJson } from '#resources/headers/questionLanguageListJson.js' +import { graphql } from '#common/utils/http/graphql.js'; +import { getQuestionLanguageListJson } from '#resources/headers/questionLanguageListJson.js'; export async function getQuestionLanguageList() { - const res = await graphql(getQuestionLanguageListJson()) - return res?.data.languageList + const res = await graphql(getQuestionLanguageListJson()); + return res?.data.languageList; } diff --git a/common/utils/question-getter/getQuestionList.js b/common/utils/question-getter/getQuestionList.js index 66df191..dd10412 100644 --- a/common/utils/question-getter/getQuestionList.js +++ b/common/utils/question-getter/getQuestionList.js @@ -1,9 +1,9 @@ -import { getQuestionListJson } from '#resources/headers/questionListJson.js' -import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionListJson } from '#resources/headers/questionListJson.js'; +import { graphql } from '#common/utils/http/graphql.js'; export async function getQuestionList() { - const base = await graphql(getQuestionListJson()) - // todo 列表 - const question = base.questions - return question + const base = await graphql(getQuestionListJson()); + // todo 列表 + const question = base.questions; + return question; } diff --git a/common/utils/question-getter/getQuestionRandom.js b/common/utils/question-getter/getQuestionRandom.js index a06154c..92cfc46 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 { 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'; 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 question = await getQuestionDetail(slug) - return question + 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 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..673afea --- /dev/null +++ b/common/utils/question-getter/getQuestionTagType.js @@ -0,0 +1,8 @@ +import { getQuestionTagTypeJson } from '#resources/headers/questionTagTypeJson.js'; +import { graphql } from '#common/utils/http/graphql.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..ce894a6 100644 --- a/common/utils/question-getter/getQuestionToday.js +++ b/common/utils/question-getter/getQuestionToday.js @@ -1,11 +1,11 @@ -import { getQuestionDetail } from '../question-handler/getQuestionDetail.js' -import { getQuestionTodayJson } from '#resources/headers/questionTodayJson.js' -import { graphql } from '#common/utils/http/graphql.js' +import { getQuestionDetail } from '../question-handler/getQuestionDetail.js'; +import { getQuestionTodayJson } from '#resources/headers/questionTodayJson.js'; +import { graphql } from '#common/utils/http/graphql.js'; export async function getQuestionToday() { - const question = await graphql(getQuestionTodayJson()) - const today = question.data.todayRecord[0].question - const { date } = question.data.todayRecord[0] - const questionInfo = await getQuestionDetail(today.titleSlug, { date }) - return questionInfo + const question = await graphql(getQuestionTodayJson()); + const today = question.data.todayRecord[0].question; + const { date } = question.data.todayRecord[0]; + const questionInfo = await getQuestionDetail(today.titleSlug, { date }); + return questionInfo; } diff --git a/common/utils/question-getter/getQuestionTypes.js b/common/utils/question-getter/getQuestionTypes.js index 74e809d..a31b35f 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'; +import { graphql } from '#common/utils/http/graphql.js'; /** * 获取问题的类型 @@ -23,8 +23,8 @@ import { graphql } from '#common/utils/http/graphql.js' * @returns {Promise<*>} */ export async function getQuestionTypes() { - const res = await graphql(getQuestionTypesJson()) - const tags = res.data?.questionTagTypeWithTags - // logger.info(JSON.stringify(tags)) - return tags + const res = await graphql(getQuestionTypesJson()); + const tags = res.data?.questionTagTypeWithTags; + // logger.info(JSON.stringify(tags)) + return tags; } diff --git a/common/utils/question-getter/getStudyPlanList.js b/common/utils/question-getter/getStudyPlanList.js index ad6efba..f1b2c1c 100644 --- a/common/utils/question-getter/getStudyPlanList.js +++ b/common/utils/question-getter/getStudyPlanList.js @@ -1,12 +1,12 @@ -import { graphql } from '#common/utils/http/graphql.js' -import { getStudyPlanListJson } from '#resources/headers/studyPlanListJson.js' +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 + const res = await graphql(getStudyPlanListJson(type)); + const { + data: { + studyPlansV2ByCatalog: { studyPlans } + } + } = res; + return studyPlans; } diff --git a/common/utils/question-handler/checkQuestionByPath.js b/common/utils/question-handler/checkQuestionByPath.js index cdbe42f..b854a0c 100644 --- a/common/utils/question-handler/checkQuestionByPath.js +++ b/common/utils/question-handler/checkQuestionByPath.js @@ -1,6 +1,6 @@ -import fs from 'node:fs' -import vm from 'node:vm' -import { showLogs } from '#common/utils/question-handler/showLogs.js' +import fs from 'node:fs'; +import vm from 'node:vm'; +import { showLogs } from '#common/utils/question-handler/showLogs.js'; /** * 执行脚本 - 可传入上下文 @@ -9,9 +9,9 @@ import { showLogs } from '#common/utils/question-handler/showLogs.js' * @returns {any} */ export function executeScript(filePath, context) { - const fileContent = fs.readFileSync(filePath, 'utf-8') - const script = new vm.Script(fileContent) - return script.runInContext(context) + const fileContent = fs.readFileSync(filePath, 'utf-8'); + const script = new vm.Script(fileContent); + return script.runInContext(context); } /** @@ -19,11 +19,11 @@ export function executeScript(filePath, context) { * @param path */ export async function checkQuestionByPath(path) { - return await executeScript( - path, - vm.createContext({ - showLogs, - console - }) - ) + return await executeScript( + path, + vm.createContext({ + showLogs, + console + }) + ); } diff --git a/common/utils/question-handler/code.js b/common/utils/question-handler/code.js index 125d6fb..c3671df 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 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'; /** * 获取代码 @@ -13,8 +10,8 @@ import { DefaultLang } from '#common/constants/question.const.js' * @returns {Promise<*>} */ export async function getCodeBySlug(slug, lang) { - const list = await getQuestionCodeList(slug) - return list?.find((o) => o.langSlug === lang)?.code + const list = await getQuestionCodeList(slug); + return list?.find((o) => o.langSlug === lang)?.code; } /** * 获取支持的代码语言 @@ -22,8 +19,8 @@ export async function getCodeBySlug(slug, lang) { * @returns {Promise} */ 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,28 +30,20 @@ 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')}`; } /** * 获取文件中的代码部分 */ export function getCodeInFile(filePath) { - const lang = getLangByExtension(filePath)?.lang ?? DefaultLang - const data = fs.readFileSync(filePath, 'utf-8') - 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 match = data.match(rangeReg) - if (!match) return null - return match[0]?.replace(rangeTagReg, '') + const lang = getLangByExtension(filePath)?.lang ?? DefaultLang; + const data = fs.readFileSync(filePath, 'utf-8'); + 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 match = data.match(rangeReg); + 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..b2f80d3 100644 --- a/common/utils/question-handler/createMarkdown.js +++ b/common/utils/question-handler/createMarkdown.js @@ -1,5 +1,5 @@ -import fs from 'node:fs' -import path from 'node:path' +import fs from 'node:fs'; +import path from 'node:path'; /** * 创建markdown @@ -7,7 +7,8 @@ import path from 'node:path' * @param {*} questionPath */ export function createMarkdown(description, questionPath) { - const dir = path.dirname(questionPath) - const descriptionPath = path.join(dir, 'description.md') - fs.writeFileSync(descriptionPath, description) + 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..49775b7 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 { 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' +import fs from 'node:fs'; +import path from 'node:path'; +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'; /** * 创建问题 @@ -11,39 +11,32 @@ import { getSupportCode } from '#common/utils/question-handler/code.js' * @returns {Promise} */ export function createQuestion(question, questionDir) { - return new Promise((resolve) => { - const filePath = path.normalize( - path.join( - questionDir, - `question${getQuestionFileExtension(question.lang)}` - ) - ) - if (fs.existsSync(filePath)) { - resolve(false) - } else { - createQuestionFile(questionDir, filePath, question) - .then((path) => resolve(path)) - .catch(() => resolve(false)) - } - }) + return new Promise((resolve) => { + const filePath = path.normalize(path.join(questionDir, `question${getQuestionFileExtension(question.lang)}`)); + if (fs.existsSync(filePath)) { + resolve(false); + } else { + createQuestionFile(questionDir, filePath, question) + .then((path) => resolve(path)) + .catch(() => resolve(false)); + } + }); } export function createQuestionFile(questionDir, questionFilePath, question) { - return new Promise((resolve, reject) => { - try { - // 创建题目的目录 - fs.mkdir(questionDir, { recursive: true }, async () => { - // 写入文件和模板 - await fulfillQuestion(questionFilePath, question) - if (!question.code) { - const supports = await getSupportCode(question.slug) - console.warn( - `此题目不支持当前语言[${question.lang}]!受支持的语言有[${supports.join(',')}]!` - ) + return new Promise((resolve, reject) => { + try { + // 创建题目的目录 + fs.mkdir(questionDir, { recursive: true }, async () => { + // 写入文件和模板 + await fulfillQuestion(questionFilePath, question); + if (!question.code) { + const supports = await getSupportCode(question.slug); + console.warn(`此题目不支持当前语言[${question.lang}]!受支持的语言有[${supports.join(',')}]!`); + } + resolve(questionFilePath); + }); + } catch (e) { + reject(e); } - resolve(questionFilePath) - }) - } catch (e) { - reject(e) - } - }) + }); } diff --git a/common/utils/question-handler/createQuestionCopy.js b/common/utils/question-handler/createQuestionCopy.js index 8720c9e..1935867 100644 --- a/common/utils/question-handler/createQuestionCopy.js +++ b/common/utils/question-handler/createQuestionCopy.js @@ -1,8 +1,8 @@ // todo 创建问题副本 -import path from 'node:path' -import { getCountBySameName } from '#common/utils/file/getCountBySameName.js' -import { createQuestionFile } from '#common/utils/question-handler/createQuestion.js' -import { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.js' +import path from 'node:path'; +import { getCountBySameName } from '#common/utils/file/getCountBySameName.js'; +import { createQuestionFile } from '#common/utils/question-handler/createQuestion.js'; +import { getQuestionFileExtension } from '#common/utils/question-handler/questionLanguage.js'; /** * 创建副本 @@ -11,15 +11,11 @@ import { getQuestionFileExtension } from '#common/utils/question-handler/questio * @returns {Promise} */ export function createQuestionCopy(question, questionDir) { - if (!question || !question.id) - return Promise.reject(new Error('question is empty')) - const dir = path.dirname(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)}` - ) - return createQuestionFile(copyFileDir, copyFilePath, question) + if (!question || !question.id) return Promise.reject(new Error('question is empty')); + const dir = path.dirname(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)}`); + return createQuestionFile(copyFileDir, copyFilePath, question); } diff --git a/common/utils/question-handler/fulfillQuestion.js b/common/utils/question-handler/fulfillQuestion.js index 830890b..7da075a 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 { getConsoleText } from '#common/utils/question-handler/getConsoleText.js' -import { template } from '#resources/template/template.js' -import { setBlockComment } from '#common/utils/question-handler/questionLanguage.js' -import { getCodeRange } from '#common/utils/question-handler/code.js' +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 { getConsoleText } from '#common/utils/question-handler/getConsoleText.js'; +import { template } from '#resources/template/template.js'; +import { setBlockComment } from '#common/utils/question-handler/questionLanguage.js'; +import { getCodeRange } from '#common/utils/question-handler/code.js'; /** * @typedef {object} Question @@ -28,16 +28,16 @@ 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 lang = question.lang - const code = question.code - return template - .replace('@Title', setBlockComment(lang, title + describe)) - .replace('@Describe', '') - .replace('@Function', getCodeRange(lang, code)) - .replace('@TestCase', getTestCase(question)) - .replace('@Console', getConsoleText(question)) + const title = `${getQuestionChineseName(question)} ${question.date ? `[${question.date}]` : ''}\n`; + const describe = removeDomTags(question.detail)?.replace(/\n+/g, '\n') ?? ''; + const lang = question.lang; + const code = question.code; + return template + .replace('@Title', setBlockComment(lang, title + describe)) + .replace('@Describe', '') + .replace('@Function', getCodeRange(lang, code)) + .replace('@TestCase', getTestCase(question)) + .replace('@Console', getConsoleText(question)); } /** * 模板文件内容替换并生成文件 @@ -45,15 +45,15 @@ export function generateTemplateContent(question) { * @param question */ export function fulfillQuestion(questionPath, question) { - return new Promise((resolve) => { - // 创建描述文件 md - createMarkdown(question.detail, questionPath) - // 开始填充内容 - const newData = generateTemplateContent(question) - // 创建文件 - fs.writeFile(questionPath, newData, (err) => { - if (err) throw err - resolve() - }) - }) + return new Promise((resolve) => { + // 创建描述文件 md + createMarkdown(question.detail, questionPath); + // 开始填充内容 + const newData = generateTemplateContent(question); + // 创建文件 + fs.writeFile(questionPath, newData, (err) => { + if (err) throw err; + resolve(); + }); + }); } diff --git a/common/utils/question-handler/getConsoleText.js b/common/utils/question-handler/getConsoleText.js index 535b449..11d17e6 100644 --- a/common/utils/question-handler/getConsoleText.js +++ b/common/utils/question-handler/getConsoleText.js @@ -1,10 +1,9 @@ -import { DefaultLang } from '#common/constants/question.const.js' -import { getQuestionUrl } from '#common/utils/question-handler/getQuestionUrl.js' -import { setLineComment } from '#common/utils/question-handler/questionLanguage.js' +import { DefaultLang } from '#common/constants/question.const.js'; +import { getQuestionUrl } from '#common/utils/question-handler/getQuestionUrl.js'; +import { setLineComment } from '#common/utils/question-handler/questionLanguage.js'; export function getConsoleText(question) { - const url = getQuestionUrl(question.slug) - if (question.lang === DefaultLang) - return `console.log('点击跳转到题目提交: ${url}');` - else return setLineComment(question.lang, `题目地址:${url}`) + const url = getQuestionUrl(question.slug); + if (question.lang === DefaultLang) return `console.log('点击跳转到题目提交: ${url}');`; + else return setLineComment(question.lang, `题目地址:${url}`); } diff --git a/common/utils/question-handler/getQuestionChineseName.js b/common/utils/question-handler/getQuestionChineseName.js index 08deaac..62557e3 100644 --- a/common/utils/question-handler/getQuestionChineseName.js +++ b/common/utils/question-handler/getQuestionChineseName.js @@ -4,5 +4,5 @@ * @returns {`${string}.${string}`} */ export function getQuestionChineseName(question) { - return `${question.id}.${question.title}` + return `${question.id}.${question.title}`; } diff --git a/common/utils/question-handler/getQuestionDetail.js b/common/utils/question-handler/getQuestionDetail.js index 4a4883e..6e58b24 100644 --- a/common/utils/question-handler/getQuestionDetail.js +++ b/common/utils/question-handler/getQuestionDetail.js @@ -1,27 +1,29 @@ -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 { 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'; /** * 获取代码详情 * @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 = {}) { - // 标题的英文字符串 - const questionDetail = await graphql(getQuestionDetailJson(slug)) - const detail = questionDetail.data.question - const curLang = await getQuestionLanguage() - const code = await getCodeBySlug(slug, curLang) - return { - id: detail?.questionId, - slug, - title: detail?.translatedTitle, - detail: detail?.translatedContent, - lang: curLang, - code, - ...extra - } + // 标题的英文字符串 + const questionDetail = await graphql(getQuestionDetailJson(slug)); + const detail = questionDetail.data.question; + const curLang = await getQuestionLanguage(); + const code = await getCodeBySlug(slug, curLang); + return { + id: detail?.questionId, + slug, + title: detail?.translatedTitle, + detail: detail?.translatedContent, + lang: curLang, + code, + 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..06ed540 100644 --- a/common/utils/question-handler/getQuestionFileName.js +++ b/common/utils/question-handler/getQuestionFileName.js @@ -4,6 +4,6 @@ * @returns {string} */ export function getQuestionFileName(question) { - if (!question || !question?.id) return '' - return `${question.id}.${question.slug}` + 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..5e46f52 100644 --- a/common/utils/question-handler/getQuestionIdBySlug.js +++ b/common/utils/question-handler/getQuestionIdBySlug.js @@ -1,26 +1,25 @@ -import { graphql } from '#common/utils/http/graphql.js' +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 ', - variables: { - titleSlug - }, - operationName: 'questionTitle' - } - const initJson = { - headers, - body: JSON.stringify(body), - method: 'POST' - } - const res = await graphql(initJson) - const { data: question } = res - return question + 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 ', + variables: { + titleSlug + }, + operationName: 'questionTitle' + }; + const initJson = { + headers, + body: JSON.stringify(body), + method: 'POST' + }; + const res = await graphql(initJson); + const { data: question } = res; + return question; } // await getQuestionIdBySlug("group-anagrams") diff --git a/common/utils/question-handler/getQuestionListCodeBy.js b/common/utils/question-handler/getQuestionListCodeBy.js new file mode 100644 index 0000000..f50787f --- /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/getQuestionListCodeBySlug.js b/common/utils/question-handler/getQuestionListCodeBySlug.js deleted file mode 100644 index b2193b7..0000000 --- a/common/utils/question-handler/getQuestionListCodeBySlug.js +++ /dev/null @@ -1,24 +0,0 @@ -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/utils/question-handler/getQuestionUrl.js b/common/utils/question-handler/getQuestionUrl.js index f976033..0c2a1cb 100644 --- a/common/utils/question-handler/getQuestionUrl.js +++ b/common/utils/question-handler/getQuestionUrl.js @@ -1,3 +1,3 @@ export function getQuestionUrl(slug) { - return `https://leetcode.cn/problems/${slug}/` + return `https://leetcode.cn/problems/${slug}/`; } diff --git a/common/utils/question-handler/getRandomId.js b/common/utils/question-handler/getRandomId.js index 72a615b..0725d83 100644 --- a/common/utils/question-handler/getRandomId.js +++ b/common/utils/question-handler/getRandomId.js @@ -1,57 +1,53 @@ -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 { logger } from '#common/utils/logger/logger.js' +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 { logger } from '#common/utils/logger/logger.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 - ) + const res = await graphql(getQuestionListJson(index, limit)); + return res?.data?.problemsetQuestionList?.questions?.map((q) => q.frontendQuestionId); } /** * 获取总数 * @returns {Promise} */ 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 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 - if (filtered.length) { - return filtered[random(filtered.length)] - } else { - waitIndexList.splice(waitIndexList.findIndex((i) => i === randomIndex)) - return await getOne(waitIndexList, localIds) - } - } - // 所有本地题目的id - const allLocalIds = readdirSync(process.cwd()).map(parse) - // 最大的数量 - const maxLength = await getCount() - const waitIndexList = Array.from({ - length: Math.ceil(maxLength / DefaultLimit) - }).map((_, i) => i) - const one = await getOne(waitIndexList, allLocalIds) - if (one === null) logger.info('恭喜!你已经刷完了所有的题目!') - else return one + // 去除所有的标题 剩下的就是id + const parse = (name) => name.replace(/\.[a-zA-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; + if (filtered.length) { + return filtered[random(filtered.length)]; + } else { + waitIndexList.splice(waitIndexList.findIndex((i) => i === randomIndex)); + return await getOne(waitIndexList, localIds); + } + }; + // 所有本地题目的id + const allLocalIds = readdirSync(process.cwd()).map(parse); + // 最大的数量 + const maxLength = await getCount(); + const waitIndexList = Array.from({ + length: Math.ceil(maxLength / DefaultLimit) + }).map((_, i) => i); + const one = await getOne(waitIndexList, allLocalIds); + if (one === null) logger.info('恭喜!你已经刷完了所有的题目!'); + else return one; } /** * 获取长度内的随机数组下标 @@ -59,5 +55,5 @@ export async function getRandomId() { * @returns {number} */ export function random(len = 10) { - return Math.trunc((Math.random() * len) % len) + return Math.trunc((Math.random() * len) % len); } diff --git a/common/utils/question-handler/getTestCase.js b/common/utils/question-handler/getTestCase.js index 2862f73..673d102 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'; +import { DefaultLang } from '#common/constants/question.const.js'; +import { setBlockComment } from '#common/utils/question-handler/questionLanguage.js'; /** * 输出的日志 @@ -22,7 +22,7 @@ import { setBlockComment } from '#common/utils/question-handler/questionLanguage )`} */ function logsTemplate(question, functionName, cases, expires) { - return `showLogs( + return `showLogs( ${functionName}, { data: [${cases}], @@ -32,7 +32,7 @@ function logsTemplate(question, functionName, cases, expires) { data: [${expires}], structure: ${JSON.stringify(getDataStructure(question.code, 'return'))} } -)` +)`; } /** @@ -43,59 +43,52 @@ function logsTemplate(question, functionName, cases, expires) { * @returns {string} */ export function getTestCase(question) { - // 完整的一条语句的reg - const inputReg = /(<[a-zA-Z]+>)?输入[:|:](<\/[a-zA-Z]+>)?.+\n/g - const inputStartReg = /(<[a-zA-Z]+>)?输入[:|:]/gm - // 输出的reg - const outputReg = /(<[a-zA-Z]+>)?输出[:|:](<\/[a-zA-Z]+>)?.+\n/g - const outputStartReg = /(<[a-zA-Z]+>)?输出[:|:]/gm - // 结尾 - const endReg = /(<\/[a-zA-Z]+>)?/gm + // 完整的一条语句的reg + const inputReg = /(<[a-zA-Z]+>)?输入[:|:](<\/[a-zA-Z]+>)?.+\n/g; + const inputStartReg = /(<[a-zA-Z]+>)?输入[:|:]/gm; + // 输出的reg + const outputReg = /(<[a-zA-Z]+>)?输出[:|:](<\/[a-zA-Z]+>)?.+\n/g; + const outputStartReg = /(<[a-zA-Z]+>)?输出[:|:]/gm; + // 结尾 + const endReg = /(<\/[a-zA-Z]+>)?/gm; - 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, '') - )}]` - ) - const expires = detail.match(outputReg)?.map((str) => - removeDomTags( - str - ?.replace(outputStartReg, '') - ?.replace(endReg, '') - ?.replace('\n', '') - .replace(/[a-zA-Z]+ =/g, '') - ) - ) - if (question.lang === DefaultLang) { - const functionName = question.code - ?.match(/(var|let|const).+=/g)?.[0] - ?.replace(/((var|let|const)|=)\s?/gm, '') - .trim() - 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++ - ) { - showText += `case ${i + 1}:\n` - showText += `${cases?.[i]}\n` ?? '[参数获取错误]\n' - showText += `${expires?.[i]}\n` ?? '[返回值获取错误]\n' + 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, '') + )}]` + ); + const expires = detail?.match(outputReg)?.map((str) => + removeDomTags( + str + ?.replace(outputStartReg, '') + ?.replace(endReg, '') + ?.replace('\n', '') + .replace(/[a-zA-Z]+ =/g, '') + ) + ); + if (question.lang === DefaultLang) { + const functionName = question.code + ?.match(/(var|let|const).+=/g)?.[0] + ?.replace(/((var|let|const)|=)\s?/gm, '') + .trim(); + 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++) { + showText += `case ${i + 1}:\n`; + showText += `${cases?.[i]}\n` ?? '[参数获取错误]\n'; + showText += `${expires?.[i]}\n` ?? '[返回值获取错误]\n'; + } + showText += `\n`; + return setBlockComment(question.lang, showText); } - showText += `\n` - return setBlockComment(question.lang, showText) - } } diff --git a/common/utils/question-handler/parseStructure.js b/common/utils/question-handler/parseStructure.js index 1ed941a..04ece73 100644 --- a/common/utils/question-handler/parseStructure.js +++ b/common/utils/question-handler/parseStructure.js @@ -1,25 +1,25 @@ -import { Node } from '../../structures/Node.js' -import { TreeNode } from '../../structures/TreeNode.js' -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 - }, - // 返回值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 - } -} + // 入参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 + }, + // 返回值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 + } +}; /** * * @param {Array} params @@ -27,11 +27,11 @@ const paramMap = { * @param {string} type */ export function setDataStructure(params, structs, type = 'cases') { - return params.map((param, index) => { - const struct = structs[index] - const map = paramMap[type] - return map[struct] ? map[struct](param) : map.default(param) - }) + return params.map((param, index) => { + const struct = structs[index]; + const map = paramMap[type]; + return map[struct] ? map[struct](param) : map.default(param); + }); } /** @@ -41,14 +41,14 @@ export function setDataStructure(params, structs, type = 'cases') { * @returns {string[]} */ export function getDataStructure(code, type = 'param') { - const regexMap = { - param: /@param\s+{\s*([^}\s]+)\s*}/g, - return: /@return\s+{\s*([^}\s]+)\s*}/g - } - const regex = regexMap[type] - const paramTypes = [] - let match - while ((match = regex.exec(code)) !== null) paramTypes.push(match[1]) + const regexMap = { + param: /@param\s+{\s*([^}\s]+)\s*}/g, + return: /@return\s+{\s*([^}\s]+)\s*}/g + }; + const regex = regexMap[type]; + const paramTypes = []; + let match; + while ((match = regex.exec(code)) !== null) paramTypes.push(match[1]); - return paramTypes + return paramTypes; } diff --git a/common/utils/question-handler/questionLanguage.js b/common/utils/question-handler/questionLanguage.js index ca4bc22..4b99152 100644 --- a/common/utils/question-handler/questionLanguage.js +++ b/common/utils/question-handler/questionLanguage.js @@ -1,228 +1,228 @@ -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'; +import { DefaultLang } from '#common/constants/question.const.js'; /** * 语言 * @type {*[]} */ export const LANGUAGES = [ - { - id: 0, - name: 'cpp', - extension: '.cpp', - blockComment: '/*\n*\n*/', // 块级注释 使用换行符来分割 - lineComment: '//' // 行级注释 不需要分割 - }, - { - id: 1, - name: 'java', - extension: '.java', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 2, - name: 'python', - extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' - }, - { - id: 11, - name: 'python3', - extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' - }, - { - id: 3, - name: 'mysql', - extension: '.sql', - blockComment: '/*\n*\n*/', - lineComment: '--' - }, - { - id: 14, - name: 'mssql', - extension: '.sql', - blockComment: '/*\n*\n*/', - lineComment: '--' - }, - { - id: 15, - name: 'oraclesql', - extension: '.sql', - blockComment: '/*\n*\n*/', - lineComment: '--' - }, - { - id: 4, - name: 'c', - extension: '.c', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 5, - name: 'csharp', - extension: '.cs', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 6, - name: 'javascript', - extension: '.js', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 20, - name: 'typescript', - extension: '.ts', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 8, - name: 'bash', - extension: '.sh', - blockComment: "'''\n\n'''", - lineComment: '#' - }, - { - id: 19, - name: 'php', - extension: '.php', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 9, - name: 'swift', - extension: '.swift', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 13, - name: 'kotlin', - extension: '.kt', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 24, - name: 'dart', - extension: '.dart', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 10, - name: 'golang', - extension: '.go', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 7, - name: 'ruby', - extension: '.rb', - blockComment: '=begin\n\n=end', - lineComment: '#' - }, - { - id: 12, - name: 'scala', - extension: '.scala', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 16, - name: 'html', - extension: '.html', - blockComment: '', - lineComment: '' - }, - { - id: 17, - name: 'pythonml', - extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' - }, - { - id: 18, - name: 'rust', - extension: '.rs', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 21, - name: 'racket', - extension: '.rkt', - blockComment: ';;\n\n;;', - lineComment: '' - }, - { - id: 22, - name: 'erlang', - extension: '.erl', - blockComment: '%%\n\n%%', - lineComment: '' - }, - { - id: 23, - name: 'elixir', - extension: '.ex', - blockComment: '#\n#\n#', - lineComment: '' - }, - { - id: 25, - name: 'pythondata', - extension: '.py', - blockComment: "'''\n\n'''", - lineComment: '#' - }, - { - id: 26, - name: 'react', - extension: '.jsx', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 27, - name: 'vanillajs', - extension: '.js', - blockComment: '/*\n*\n*/', - lineComment: '//' - }, - { - id: 28, - name: 'postgresql', - extension: '.sql', - blockComment: '/*\n*\n*/', - lineComment: '--' - } -] + { + id: 0, + name: 'cpp', + extension: '.cpp', + blockComment: '/*\n*\n*/', // 块级注释 使用换行符来分割 + lineComment: '//' // 行级注释 不需要分割 + }, + { + id: 1, + name: 'java', + extension: '.java', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 2, + name: 'python', + extension: '.py', + blockComment: "'''\n\n'''", + lineComment: '#' + }, + { + id: 11, + name: 'python3', + extension: '.py', + blockComment: "'''\n\n'''", + lineComment: '#' + }, + { + id: 3, + name: 'mysql', + extension: '.sql', + blockComment: '/*\n*\n*/', + lineComment: '--' + }, + { + id: 14, + name: 'mssql', + extension: '.sql', + blockComment: '/*\n*\n*/', + lineComment: '--' + }, + { + id: 15, + name: 'oraclesql', + extension: '.sql', + blockComment: '/*\n*\n*/', + lineComment: '--' + }, + { + id: 4, + name: 'c', + extension: '.c', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 5, + name: 'csharp', + extension: '.cs', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 6, + name: 'javascript', + extension: '.js', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 20, + name: 'typescript', + extension: '.ts', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 8, + name: 'bash', + extension: '.sh', + blockComment: "'''\n\n'''", + lineComment: '#' + }, + { + id: 19, + name: 'php', + extension: '.php', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 9, + name: 'swift', + extension: '.swift', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 13, + name: 'kotlin', + extension: '.kt', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 24, + name: 'dart', + extension: '.dart', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 10, + name: 'golang', + extension: '.go', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 7, + name: 'ruby', + extension: '.rb', + blockComment: '=begin\n\n=end', + lineComment: '#' + }, + { + id: 12, + name: 'scala', + extension: '.scala', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 16, + name: 'html', + extension: '.html', + blockComment: '', + lineComment: '' + }, + { + id: 17, + name: 'pythonml', + extension: '.py', + blockComment: "'''\n\n'''", + lineComment: '#' + }, + { + id: 18, + name: 'rust', + extension: '.rs', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 21, + name: 'racket', + extension: '.rkt', + blockComment: ';;\n\n;;', + lineComment: '' + }, + { + id: 22, + name: 'erlang', + extension: '.erl', + blockComment: '%%\n\n%%', + lineComment: '' + }, + { + id: 23, + name: 'elixir', + extension: '.ex', + blockComment: '#\n#\n#', + lineComment: '' + }, + { + id: 25, + name: 'pythondata', + extension: '.py', + blockComment: "'''\n\n'''", + lineComment: '#' + }, + { + id: 26, + name: 'react', + extension: '.jsx', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 27, + name: 'vanillajs', + extension: '.js', + blockComment: '/*\n*\n*/', + lineComment: '//' + }, + { + id: 28, + name: 'postgresql', + extension: '.sql', + blockComment: '/*\n*\n*/', + lineComment: '--' + } +]; /** * 设置编程主语言 */ export async function setQuestionLanguage(lang = DefaultLang) { - await setStore('language', lang) + await setStore('language', lang); } /** * 获取当前语言 - 默认语言是JS */ export async function getQuestionLanguage() { - const lang = await getStore('language') - return lang ?? DefaultLang + const lang = await getStore('language'); + return lang ?? DefaultLang; } /** @@ -231,15 +231,15 @@ 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()); } /** * 获取文件后缀 * @param lang */ export function getQuestionFileExtension(lang = DefaultLang) { - const detail = getLang(lang) - return detail?.extension + const detail = getLang(lang); + return detail?.extension; } /** @@ -248,10 +248,10 @@ export function getQuestionFileExtension(lang = DefaultLang) { * @returns {*} */ export function getLangByExtension(extensionLike) { - const reg = /\.[0-9a-zA-Z_]+$/im - const match = extensionLike.match(reg) - const extension = match === null ? `.${extensionLike}` : match[0] - return LANGUAGES?.find((o) => o.extension === extension) + const reg = /\.[0-9a-zA-Z_]+$/im; + const match = extensionLike.match(reg); + const extension = match === null ? `.${extensionLike}` : match[0]; + return LANGUAGES?.find((o) => o.extension === extension); } /** * 获取行注释 @@ -259,13 +259,13 @@ export function getLangByExtension(extensionLike) { * @returns {*} */ export function getLineComment(lang = DefaultLang) { - const langObj = getLang(lang) - if (langObj.lineComment !== '') { - return langObj.lineComment - } else { - // 因为保底是都有块级注释的 - return null - } + const langObj = getLang(lang); + if (langObj.lineComment !== '') { + return langObj.lineComment; + } else { + // 因为保底是都有块级注释的 + return null; + } } /** @@ -274,8 +274,8 @@ export function getLineComment(lang = DefaultLang) { * @returns {*} */ export function getBlockComment(lang = DefaultLang) { - const langObj = getLang(lang) - return langObj.blockComment + const langObj = getLang(lang); + return langObj.blockComment; } /** @@ -285,13 +285,13 @@ export function getBlockComment(lang = DefaultLang) { * @returns {*} */ export function setLineComment(lang = DefaultLang, comment = '') { - const lineComment = getLineComment(lang) - if (lineComment !== null) { - const lines = comment.split('\n') - return lines.reduce((p, line) => (p += `${lineComment} ${line}\n`), '') - } else { - return setBlockComment(lang, comment) - } + const lineComment = getLineComment(lang); + if (lineComment !== null) { + const lines = comment.split('\n'); + return lines.reduce((p, line) => (p += `${lineComment} ${line}\n`), ''); + } else { + return setBlockComment(lang, comment); + } } /** @@ -301,21 +301,18 @@ export function setLineComment(lang = DefaultLang, comment = '') { * @returns {*} */ export function setBlockComment(lang = DefaultLang, comment = '') { - const block = getBlockComment(lang) - const splitter = block.split('\n') - const lines = comment.split('\n') - switch (splitter.length) { - case 3: { - const start = splitter[0] - const end = splitter[2] - const startTag = splitter[1] - const content = lines.reduce( - (p, line) => (p += `${startTag} ${line}\n`), - '' - ) - return `${start}\n${content}${end}\n` + const block = getBlockComment(lang); + const splitter = block.split('\n'); + const lines = comment.split('\n'); + switch (splitter.length) { + case 3: { + const start = splitter[0]; + const end = splitter[2]; + const startTag = splitter[1]; + const content = lines.reduce((p, line) => (p += `${startTag} ${line}\n`), ''); + return `${start}\n${content}${end}\n`; + } + default: + return comment; } - default: - return comment - } } diff --git a/common/utils/question-handler/showLogs.js b/common/utils/question-handler/showLogs.js index 3c98ffb..6d7728d 100644 --- a/common/utils/question-handler/showLogs.js +++ b/common/utils/question-handler/showLogs.js @@ -1,8 +1,8 @@ -import v8 from 'node:v8' -import { Table } from 'console-table-printer' -import { getFileSize } from '../functions/sizeUtil.js' -import { isSameData } from '../functions/isSameData.js' -import { setDataStructure } from './parseStructure.js' +import v8 from 'node:v8'; +import { Table } from 'console-table-printer'; +import { getFileSize } from '../functions/sizeUtil.js'; +import { isSameData } from '../functions/isSameData.js'; +import { setDataStructure } from './parseStructure.js'; /** * 执行并输出时间和内存 @@ -13,73 +13,56 @@ import { setDataStructure } from './parseStructure.js' * @returns {{预期结果: string, 执行结果: string, 内存占用: string, 测试结果: (string), 执行用时: string}} */ export function parseLog(fnName, param, compare, compareStruct) { - // 记录开始时间 - const startTime = performance.now() - // 获取函数执行前的内存使用情况 - const startHeapStatsArray = v8.getHeapSpaceStatistics() - const callVal = fnName(...param) - 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 startTime = performance.now(); + // 获取函数执行前的内存使用情况 + const startHeapStatsArray = v8.getHeapSpaceStatistics(); + const callVal = fnName(...param); + 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); - return { - 测试结果: isSameData(parsedCompareArr, compare) ? '通过' : '未通过', - 预期结果: JSON.stringify(compare), - 执行结果: JSON.stringify(parsedCompareArr), - 执行用时: `${Number(endTime - startTime).toFixed(4)}ms`, - 内存占用: getFileSize(endHeapStats - startHeapStats) - } + return { + 测试结果: isSameData(parsedCompareArr, compare) ? '通过' : '未通过', + 预期结果: JSON.stringify(compare), + 执行结果: JSON.stringify(parsedCompareArr), + 执行用时: `${Number(endTime - startTime).toFixed(4)}ms`, + 内存占用: getFileSize(endHeapStats - startHeapStats) + }; } export function showLogs(fnName, paramMap, compareMap) { - const logsItems = [] - const { data: paramArr, structure: paramStruct } = paramMap - const { data: compareArr, structure: compareStruct } = compareMap + const logsItems = []; + const { data: paramArr, structure: paramStruct } = paramMap; + const { data: compareArr, structure: compareStruct } = compareMap; - paramArr.forEach((param, index) => { - const parsedParma = setDataStructure(param, paramStruct) - const logItem = parseLog( - fnName, - parsedParma, - compareArr[index], - compareStruct - ) - logsItems.push(logItem) - }) + paramArr.forEach((param, index) => { + const parsedParma = setDataStructure(param, paramStruct); + const logItem = parseLog(fnName, parsedParma, compareArr[index], compareStruct); + logsItems.push(logItem); + }); - const logTable = new Table({ - columns: [ - { name: '测试结果', title: '测试结果', alignment: 'center', maxLen: 10 }, - { name: '预期结果', title: '预期结果', alignment: 'center', maxLen: 40 }, - { name: '执行结果', title: '执行结果', alignment: 'center', maxLen: 40 }, - { 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] - } - } - logTable.addRow(item, { - color: item['测试结果'] === '通过' ? 'green' : 'red' - }) - }) - logTable.printTable() + const logTable = new Table({ + columns: [ + { name: '测试结果', title: '测试结果', alignment: 'center', maxLen: 10 }, + { name: '预期结果', title: '预期结果', alignment: 'center', maxLen: 40 }, + { name: '执行结果', title: '执行结果', alignment: 'center', maxLen: 40 }, + { 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]; + } + + logTable.addRow(item, { + 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..f4b935c --- /dev/null +++ b/common/utils/store/controller/allQuestion.js @@ -0,0 +1,94 @@ +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} + */ +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/question.js b/common/utils/store/controller/question.js index cb83830..c22cb0e 100644 --- a/common/utils/store/controller/question.js +++ b/common/utils/store/controller/question.js @@ -1,4 +1,4 @@ -import { exeOnce } from '#common/utils/store/store-realm.js' +import { exeOnce } from '#common/utils/store/store-realm.js'; /** * 根据模式读取对象 @@ -6,11 +6,11 @@ import { exeOnce } from '#common/utils/store/store-realm.js' * @returns {unknown} */ export function getQuestionByMode(mode) { - return exeOnce((realm) => { - const all = realm.objects('Question') - const question = all.filtered('mode=$0', mode)?.[0] - return question?.toJSON() - }) + return exeOnce((realm) => { + const all = realm.objects('Question'); + const question = all.filtered('mode=$0', mode)?.[0]; + return question?.toJSON(); + }); } /** @@ -20,14 +20,14 @@ export function getQuestionByMode(mode) { * @returns {*} */ export function setQuestion(mode, question) { - return exeOnce((realm) => { - let newQuestion - realm.write(() => { - realm.delete(realm.objects('Question').filtered('mode=$0', mode)) - newQuestion = realm.create('Question', Object.assign(question, { mode })) - }) - return newQuestion.toJSON() - }) + return exeOnce((realm) => { + let newQuestion; + realm.write(() => { + realm.delete(realm.objects('Question').filtered('mode=$0', mode)); + newQuestion = realm.create('Question', Object.assign(question, { mode })); + }); + return newQuestion.toJSON(); + }); } /** @@ -35,21 +35,21 @@ export function setQuestion(mode, question) { * @param mode */ export function deleteQuestionByMode(mode) { - return exeOnce((realm) => { - realm.write(() => { - const modes = realm.objects('Question').filtered('mode=$0', mode) - realm.delete(modes) - }) - }) + return exeOnce((realm) => { + realm.write(() => { + const modes = realm.objects('Question').filtered('mode=$0', mode); + realm.delete(modes); + }); + }); } /** * 删除全部 */ export function deleteAllQuestion() { - return exeOnce((realm) => { - realm.write(() => { - realm.delete(realm.objects('Question')) - }) - }) + return exeOnce((realm) => { + realm.write(() => { + realm.delete(realm.objects('Question')); + }); + }); } diff --git a/common/utils/store/controller/store.js b/common/utils/store/controller/store.js index 5da932b..3dc3bcb 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'; +import { typeof_ } from '#common/utils/etc/typeof_.js'; /** * 转化数据到特殊格式字符串 @@ -7,10 +7,10 @@ import { typeof_ } from '#common/utils/etc/typeof_.js' * @returns {string} */ function convData(data) { - const type = typeof_(data) - const dataStr = type === 'object' ? JSON.stringify(data) : data.toString() - const prefix = `$<${type}>$` - return prefix + dataStr + const type = typeof_(data); + const dataStr = type === 'object' ? JSON.stringify(data) : data.toString(); + const prefix = `$<${type}>$`; + return prefix + dataStr; } /** * 转化字符串到数据 @@ -18,26 +18,26 @@ function convData(data) { * @returns {any} */ function parseData(dataStr) { - const prefixReg = /^\$<.+>\$/im - if (!prefixReg.test(dataStr)) return null + const prefixReg = /^\$<.+>\$/im; + if (!prefixReg.test(dataStr)) return null; - const type = dataStr.match(prefixReg)[0].replace(/[$<>]+/g, '') - const remainStr = dataStr.replace(prefixReg, '') - switch (type) { - case 'object': - return JSON.parse(remainStr) - case 'bigint': - return BigInt(remainStr) - case 'boolean': - return remainStr === 'true' - case 'number': - return Number(remainStr) - case 'function': - return () => remainStr - case 'string': - default: - return remainStr - } + const type = dataStr.match(prefixReg)[0].replace(/[$<>]+/g, ''); + const remainStr = dataStr.replace(prefixReg, ''); + switch (type) { + case 'object': + return JSON.parse(remainStr); + case 'bigint': + return BigInt(remainStr); + case 'boolean': + return remainStr === 'true'; + case 'number': + return Number(remainStr); + case 'function': + return () => remainStr; + case 'string': + default: + return remainStr; + } } /** @@ -47,15 +47,15 @@ function parseData(dataStr) { * @returns {Promise} */ export function setStore(key, value) { - return exeOnce((realm) => { - let newStore - realm.write(() => { - const oldStore = realm.objects('Store').filtered(`key = "${key}"`)?.[0] - oldStore && realm.delete(oldStore) - newStore = realm.create('Store', { key, value: convData(value) }) - }) - return newStore.toJSON() - }) + return exeOnce((realm) => { + let newStore; + realm.write(() => { + const oldStore = realm.objects('Store').filtered(`key = "${key}"`)?.[0]; + oldStore && realm.delete(oldStore); + newStore = realm.create('Store', { key, value: convData(value) }); + }); + return newStore.toJSON(); + }); } /** @@ -64,11 +64,11 @@ export function setStore(key, value) { * @returns {Promise} */ export function getStore(key) { - return exeOnce((realm) => { - const all = realm.objects('Store') - const storeObj = all.filtered('key=$0', key)?.[0]?.toJSON() - return parseData(storeObj?.value) - }) + return exeOnce((realm) => { + const all = realm.objects('Store'); + const storeObj = all.filtered('key=$0', key)?.[0]?.toJSON(); + return parseData(storeObj?.value); + }); } /** @@ -77,11 +77,11 @@ export function getStore(key) { * @returns {Promise} */ export function deleteStore(key) { - return exeOnce((realm) => { - realm.write(() => { - realm.delete(realm.objects('Store').filtered('key=$0', key)) - }) - }) + return exeOnce((realm) => { + realm.write(() => { + realm.delete(realm.objects('Store').filtered('key=$0', key)); + }); + }); } /** @@ -90,9 +90,9 @@ export function deleteStore(key) { * @returns {Promise} */ export function clearStore() { - return exeOnce((realm) => { - realm.write(() => { - realm.delete(realm.objects('Store')) - }) - }) + return exeOnce((realm) => { + realm.write(() => { + realm.delete(realm.objects('Store')); + }); + }); } diff --git a/common/utils/store/schemas/allQuestion.js b/common/utils/store/schemas/allQuestion.js new file mode 100644 index 0000000..6d99f63 --- /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..000ab51 100644 --- a/common/utils/store/schemas/question.js +++ b/common/utils/store/schemas/question.js @@ -1,21 +1,23 @@ -import Realm from 'realm' +import Realm from 'realm'; export class Question extends Realm.Object { - static schema = { - name: 'Question', - properties: { - _id: { type: 'objectId', default: () => new Realm.BSON.ObjectId() }, - id: 'string', - mode: 'string', - slug: 'string', - title: 'string', - detail: 'string', - lang: 'string', - code: 'string?', - url: 'string?', - date: 'string?', - timestamp: { type: 'date', default: () => new Date() } - }, - primaryKey: '_id' - } + static schema = { + name: 'Question', + properties: { + _id: { type: 'objectId', default: () => new Realm.BSON.ObjectId() }, + id: 'string', + mode: '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() } + }, + primaryKey: '_id' + }; } diff --git a/common/utils/store/schemas/store.js b/common/utils/store/schemas/store.js index 9ee3f6f..8c1ebc7 100644 --- a/common/utils/store/schemas/store.js +++ b/common/utils/store/schemas/store.js @@ -1,13 +1,13 @@ -import Realm from 'realm' +import Realm from 'realm'; export class Store extends Realm.Object { - static schema = { - name: 'Store', - properties: { - key: 'string', - value: 'string', - timestamp: { type: 'date', default: () => new Date() } - }, - primaryKey: 'key' - } + static schema = { + name: 'Store', + properties: { + key: 'string', + value: 'string', + timestamp: { type: 'date', default: () => new Date() } + }, + primaryKey: 'key' + }; } diff --git a/common/utils/store/store-realm.js b/common/utils/store/store-realm.js index 7392047..a9b7868 100644 --- a/common/utils/store/store-realm.js +++ b/common/utils/store/store-realm.js @@ -1,31 +1,32 @@ -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 { rootPath } from '#common/utils/file/getRootPath.js' -import { Store } from '#common/utils/store/schemas/store.js' +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 { AllQuestion } from '#common/utils/store/schemas/allQuestion.js'; +import { rootPath } from '#common/utils/file/getRootPath.js'; +import { Store } from '#common/utils/store/schemas/store.js'; -const localPath = path.resolve(rootPath, 'resources/stores/store.realm') +const localPath = path.resolve(rootPath, 'resources/stores/store.realm'); /** * 开启 * @returns {Promise} */ export async function open() { - let realm - try { - realm = await Realm.open({ - schema: [Question, Store], - path: localPath - }) - } catch (e) { - if (e?.message?.includes('Migration')) await cleanStore() + let realm; + try { + realm = await Realm.open({ + schema: [Question, AllQuestion, Store], + path: localPath + }); + } catch (e) { + if (e?.message?.includes('Migration')) await cleanStore(); - realm = await Realm.open({ - schema: [Question, Store], - path: localPath - }) - } - return realm + realm = await Realm.open({ + schema: [Question, AllQuestion, Store], + path: localPath + }); + } + return realm; } /** * 执行一次 @@ -33,22 +34,22 @@ export async function open() { * @returns {Promise} */ export async function exeOnce(callback) { - const realm = await open() - const res = await callback(realm) - realm.close() - return res + const realm = await open(); + const res = await callback(realm); + realm.close(); + return res; } /** * 清理缓存 * @returns {Promise} */ export function cleanStore() { - return new Promise((resolve) => { - const dir = path.dirname(localPath) - const files = readdirSync(dir) - files.forEach((file) => { - rmSync(path.resolve(dir, file), { recursive: true, force: true }) - }) - resolve() - }) + return new Promise((resolve) => { + const dir = path.dirname(localPath); + const files = readdirSync(dir); + files.forEach((file) => { + rmSync(path.resolve(dir, file), { recursive: true, force: true }); + }); + resolve(); + }); } diff --git a/common/utils/update/update.js b/common/utils/update/update.js index bcce9b2..ef6b16e 100644 --- a/common/utils/update/update.js +++ b/common/utils/update/update.js @@ -1,83 +1,60 @@ -import fs from 'node:fs' -import path from 'node:path' -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 fs from 'node:fs'; +import path from 'node:path'; +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'; // 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_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库中的版本号 */ export async function getNpmVersion() { - try { - const res = await fetch_(npmUrl, { method: 'GET' }) - return res['dist-tags']?.latest - } catch (e) { - throw new Error(e) - } + try { + const res = await fetch_(npmUrl, { method: 'GET' }); + return res['dist-tags']?.latest; + } catch (e) { + return false; + } } /** * 获取github的最新提交sha * @returns {Promise} */ 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 - return ver - } catch (e) { - throw new Error(e) - } + 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; + return ver; + } catch (e) { + return false; + } } export function getLocalVersion() { - try { - const { version } = JSON.parse( - fs.readFileSync(path.resolve(rootPath, 'package.json'), 'utf-8') - ) - return version - } catch (e) { - return false - } + try { + const { version } = JSON.parse(fs.readFileSync(path.resolve(rootPath, 'package.json'), 'utf-8')); + return version; + } catch (e) { + return false; + } } /** * 检测整体的更新状况 * @returns {Promise<{localVersion: (any|boolean), githubVersion: *, isCliUpdate: boolean, remoteVersion: unknown, isGithubUpdate: boolean}>} */ export async function checkUpdate() { - const remote = await getNpmVersion() - const github = await getGithubVersion() - const local = getLocalVersion() - return { - localVersion: local, - npmVersion: remote, - githubVersion: github, - isCliUpdate: remote !== local, - isGithubUpdate: github !== local - } + const remote = await getNpmVersion(); + const github = await getGithubVersion(); + const local = getLocalVersion(); + return { + localVersion: local, + npmVersion: remote, + githubVersion: github, + isCliUpdate: remote && remote !== local, + isGithubUpdate: github && github !== local + }; } diff --git a/common/utils/update/updateByEnv.js b/common/utils/update/updateByEnv.js index b63f663..9312cc1 100644 --- a/common/utils/update/updateByEnv.js +++ b/common/utils/update/updateByEnv.js @@ -1,14 +1,14 @@ -import { exec } from 'node:child_process' +import { exec } from 'node:child_process'; /** * 更新CLI * @returns {Promise} */ export function updateCli() { - return new Promise((resolve, reject) => { - exec(`npm install -g leetcode-practice`, (err) => { - if (err) reject(err) - else resolve() - }) - }) + return new Promise((resolve, reject) => { + exec(`npm install -g leetcode-practice`, (err) => { + if (err) reject(err); + else resolve(); + }); + }); } diff --git a/common/view/check.view.js b/common/view/check.view.js index f16d4d7..be0c60c 100644 --- a/common/view/check.view.js +++ b/common/view/check.view.js @@ -1,102 +1,92 @@ -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 { 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' +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 { 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'; export async function easyCheckView() { - const modeQuestion = [ - { - type: 'list', - name: 'mode', - message: '请选择检查问题的模式:', - choices: ['today', 'identity', 'random'] + const modeQuestion = [ + { + type: 'list', + name: 'mode', + message: '请选择检查问题的模式:', + choices: ['today', 'identity', 'random'] + } + ]; + // 第一个问题 选择的模式 + const { mode } = await inquirer.prompt(modeQuestion, null); + const identityQuestion = [ + { + type: 'input', + name: 'identity', + message: '请输入题目编号:' + } + ]; + let question; + switch (mode) { + case 'identity': { + const { identity } = await inquirer.prompt(identityQuestion, null); + question = !identity ? await getQuestionByMode(mode) : await getQuestionById(identity); + break; + } + case 'random': + question = await getQuestionByMode(mode); + break; + case 'today': + default: + question = await getQuestionByMode(mode); + break; } - ] - // 第一个问题 选择的模式 - const { mode } = await inquirer.prompt(modeQuestion, null) - const identityQuestion = [ - { - type: 'input', - name: 'identity', - message: '请输入题目编号:' + // 检查题目 + const questionFileName = getQuestionFileName(question); + const currentDir = process.cwd(); + let questionDir = path.join(currentDir, questionFileName); + // 创建路径确认 + const pathRightQuestion = [ + { + type: 'confirm', + name: 'dirRight', + message: `是否检测当前目录[ ${currentDir} ]下的题目[ ${questionFileName} ]?` + } + ]; + const { dirRight } = await inquirer.prompt(pathRightQuestion, null); + if (!dirRight) { + const newDirQuestion = [ + { + type: 'input', + name: 'newDir', + message: `请选择新目录(基础地址为${currentDir})[按回车[Enter]终止操作]:` + } + ]; + const { newDir } = await inquirer.prompt(newDirQuestion, null); + if (!newDir) { + logger.info('[LK-logger]用户终止操作~'); + process.exit(0); + } + questionDir = path.join(path.join(process.cwd(), newDir), `${questionFileName}`); } - ] - let question - switch (mode) { - case 'identity': { - const { identity } = await inquirer.prompt(identityQuestion, null) - question = !identity - ? await getQuestionByMode(mode) - : await getQuestionById(identity) - break + const questionParentDir = path.dirname(questionDir); + // 先检测有几个副本 + if (getCountBySameName(questionParentDir, questionFileName) > 1) { + const selectQuestionQuestion = [ + { + type: 'list', + name: 'selectQuestion', + message: `题目[ ${questionFileName} ]有多个副本,请选择要检测的副本:`, + choices: getFileListBySameName(questionParentDir, questionFileName) + } + ]; + // 选择其中一个副本进行检查 + const { selectQuestion } = await inquirer.prompt(selectQuestionQuestion, null); + questionDir = path.join(questionParentDir, selectQuestion); + logger.info(`用户选择题目[ ${questionFileName}]的副本[ ${selectQuestion}]进行检测`); } - case 'random': - question = await getQuestionByMode(mode) - break - case 'today': - default: - question = await getQuestionByMode(mode) - break - } - // 检查题目 - const questionFileName = getQuestionFileName(question) - const currentDir = process.cwd() - let questionDir = path.join(currentDir, questionFileName) - // 创建路径确认 - const pathRightQuestion = [ - { - type: 'confirm', - name: 'dirRight', - message: `是否检测当前目录[ ${currentDir} ]下的题目[ ${questionFileName} ]?` - } - ] - const { dirRight } = await inquirer.prompt(pathRightQuestion, null) - if (!dirRight) { - const newDirQuestion = [ - { - type: 'input', - name: 'newDir', - message: `请选择新目录(基础地址为${currentDir})[按回车[Enter]终止操作]:` - } - ] - const { newDir } = await inquirer.prompt(newDirQuestion, null) - if (!newDir) { - logger.info('[LK-logger]用户终止操作~') - process.exit(0) - } - questionDir = path.join( - path.join(process.cwd(), newDir), - `${questionFileName}` - ) - } - const questionParentDir = path.dirname(questionDir) - // 先检测有几个副本 - if (getCountBySameName(questionParentDir, questionFileName) > 1) { - const selectQuestionQuestion = [ - { - type: 'list', - name: 'selectQuestion', - message: `题目[ ${questionFileName} ]有多个副本,请选择要检测的副本:`, - choices: getFileListBySameName(questionParentDir, questionFileName) - } - ] - // 选择其中一个副本进行检查 - const { selectQuestion } = await inquirer.prompt( - selectQuestionQuestion, - null - ) - questionDir = path.join(questionParentDir, selectQuestion) - logger.info( - `用户选择题目[ ${questionFileName}]的副本[ ${selectQuestion}]进行检测` - ) - } - const filePath = path.join(questionDir, `question${question.lang}`) - await checkQuestionByPath(filePath) - logger.info(`题目[${questionFileName}]检查完成!\n文件地址为: ${filePath}`) - process.exit(0) + const filePath = path.join(questionDir, `question${question.lang}`); + 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 0e9eacf..883f6a2 100644 --- a/common/view/create.view.js +++ b/common/view/create.view.js @@ -1,80 +1,80 @@ -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 { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js' -import { getQuestionRandom } from '#common/utils/question-getter/getQuestionRandom.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 { logger } from '#common/utils/logger/logger.js' +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 { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js'; +import { getQuestionRandom } from '#common/utils/question-getter/getQuestionRandom.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 { logger } from '#common/utils/logger/logger.js'; export async function easyCreateView(baseDir = process.cwd()) { - const modeQuestion = [ - { - type: 'list', - name: 'mode', - message: '请选择创建问题的模式:', - choices: ['today', 'identity', 'random'] + const modeQuestion = [ + { + type: 'list', + name: 'mode', + message: '请选择创建问题的模式:', + choices: ['today', 'identity', 'random'] + } + ]; + // 第一个问题 选择的模式 + const { mode } = await inquirer.prompt(modeQuestion, null); + const identityQuestion = [ + { + type: 'input', + name: 'identity', + message: '请输入题目编号:' + } + ]; + let question; + switch (mode) { + case 'identity': { + const { identity } = await inquirer.prompt(identityQuestion, null); + logger.info(identity); + question = await getQuestionById(identity); + break; + } + case 'random': + question = await getQuestionRandom(); + break; + case 'today': + default: + question = await getQuestionToday(); + break; } - ] - // 第一个问题 选择的模式 - const { mode } = await inquirer.prompt(modeQuestion, null) - const identityQuestion = [ - { - type: 'input', - name: 'identity', - message: '请输入题目编号:' + const store = await setQuestion(mode, question); + if (!store) console.warn(`[create][${mode}]问题[${question.title}]未成功缓存`); + // 创建题目 + const questionFileName = getQuestionFileName(question); + let questionDir = path.join(baseDir, questionFileName); + // 创建路径确认 + const pathRightQuestion = [ + { + type: 'confirm', + name: 'dirRight', + message: `是否在目录[ ${baseDir} ]下创建题目[ ${questionFileName} ]?` + } + ]; + const { dirRight } = await inquirer.prompt(pathRightQuestion, null); + if (!dirRight) { + const newDirQuestion = [ + { + type: 'input', + name: 'newDir', + message: `请选择新目录(基础地址为${baseDir})[按回车[Enter]终止操作]:` + } + ]; + const { newDir } = await inquirer.prompt(newDirQuestion, null); + if (!newDir) { + logger.info('[LC-logger]用户终止操作~'); + process.exit(0); + } + questionDir = path.join(path.join(baseDir, newDir), `${questionFileName}`); } - ] - let question - switch (mode) { - case 'identity': { - const { identity } = await inquirer.prompt(identityQuestion, null) - logger.info(identity) - question = await getQuestionById(identity) - break - } - case 'random': - question = await getQuestionRandom() - break - case 'today': - default: - question = await getQuestionToday() - break - } - const store = await setQuestion(mode, question) - if (!store) console.warn(`[create][${mode}]问题[${question.title}]未成功缓存`) - // 创建题目 - const questionFileName = getQuestionFileName(question) - let questionDir = path.join(baseDir, questionFileName) - // 创建路径确认 - const pathRightQuestion = [ - { - type: 'confirm', - name: 'dirRight', - message: `是否在目录[ ${baseDir} ]下创建题目[ ${questionFileName} ]?` - } - ] - const { dirRight } = await inquirer.prompt(pathRightQuestion, null) - if (!dirRight) { - const newDirQuestion = [ - { - type: 'input', - name: 'newDir', - message: `请选择新目录(基础地址为${baseDir})[按回车[Enter]终止操作]:` - } - ] - const { newDir } = await inquirer.prompt(newDirQuestion, null) - if (!newDir) { - logger.info('[LC-logger]用户终止操作~') - process.exit(0) - } - questionDir = path.join(path.join(baseDir, newDir), `${questionFileName}`) - } - let filePath = await createQuestion(question, questionDir) - if (!filePath) filePath = await createQuestionCopy(question, questionDir) + let filePath = await createQuestion(question, questionDir); + if (!filePath) filePath = await createQuestionCopy(question, questionDir); - logger.info(`题目[${questionFileName}]创建完成!\n文件地址为: ${filePath}`) - process.exit(0) + logger.info(`题目[${questionFileName}]创建完成!\n文件地址为: ${filePath}`); + process.exit(0); } diff --git a/common/view/finder.view.js b/common/view/finder.view.js index 3632915..e99eac0 100644 --- a/common/view/finder.view.js +++ b/common/view/finder.view.js @@ -1,125 +1,182 @@ -import path from 'node:path' -import select, { Separator } from '@inquirer/select' -import input from '@inquirer/input' -import { - createQuestionById, - createQuestionByTitleSlug -} 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' +import path from 'node:path'; +import select, { Separator } from '@inquirer/select'; +import input from '@inquirer/input'; +import { createQuestionById, createQuestionByTitleSlug } 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, getQuestionListCodeByTag } from '#common/utils/question-handler/getQuestionListCodeBy.js'; +import { getQuestionTagType } from '#common/utils/question-getter/getQuestionTagType.js'; +import { getAllQuestion } from '#common/utils/store/controller/allQuestion.js'; function handleQuestionList(list) { - return list.map((item) => ({ - name: `${item.name}${item.premiumOnly ? '(VIP)' : ''}`, - value: item.slug - })) + 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 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' } - ] - }) - if (createMode === 'single') { - 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: planList.map((res) => ({ - name: res.cnTitle, - value: res.enTitle - })), - pageSize: 30 - } - const singleChoice = await select(singleMode) + // 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' } + ] + }); + if (createMode === 'single') { + 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: planList.map((res) => ({ + name: res.cnTitle, + value: res.enTitle + })), + pageSize: 30 + }; + const singleChoice = await select(singleMode); - await createQuestionByTitleSlug(singleChoice, baseDir) - } - if (createMode === 'all') { - const dir = path.resolve(baseDir, planSlug.toString()) - logger.off() - await getQuestionListCodeBySlug(planSlug, dir) - logger.on() - logger.info(`题目全部拉取完成: file://${dir}`) - } + await createQuestionByTitleSlug(singleChoice, baseDir); + } + 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()) { - const keyword = await input({ message: '请输入关键词', name: 'keyword' }) - const data = await getQuestionByKeyword(keyword) - const list = data?.map((q) => { - return { - name: `${q.frontendQuestionId}.${q.titleCn}`, - value: q.frontendQuestionId - } - }) - const listQuestion = { - type: 'list', - name: 'chooseQuestion', - message: '请选择题目', - choices: list - } - const chooseQuestion = await select(listQuestion) - await createQuestionById(chooseQuestion, baseDir) + const keyword = await input({ message: '请输入关键词', name: 'keyword' }); + const data = await getQuestionByKeyword(keyword); + const list = data?.map((q) => { + return { + name: `${q.frontendQuestionId}.${q.titleCn}`, + value: q.frontendQuestionId + }; + }); + const listQuestion = { + type: 'list', + name: 'chooseQuestion', + message: '请选择题目', + choices: list, + pageSize: 30 + }; + const chooseQuestion = await select(listQuestion); + await createQuestionById(chooseQuestion, baseDir); } -async function selectMode(baseDir) { - logger.info(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(); + const tagQuestionList = await allQuestion.filter((question) => question.topicTags.some((topic) => topic.slug === chooseTag)); + + 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: '学习计划', value: 'study', description: '企业和经典面试题目列表' }, - { name: '筛选模式', value: 'select', description: '筛选题目' } - ] + const choices = [ + { name: '关键词搜索', value: 'keyword', description: '关键词描述' }, + { name: '学习计划', value: 'study', description: '企业和经典面试题目列表' }, + { name: '筛选模式', value: 'select', description: '筛选题目' } + ]; - const modeQuestion = { - message: '请选择查找的模式?', - choices - } - const mode = await select(modeQuestion) + const modeQuestion = { + message: '请选择查找的模式?', + choices + }; + const mode = await select(modeQuestion); - const modeMap = { - study: studyMode, - keyword: keywordMode, - select: selectMode - } - await modeMap[mode](baseDir) + const modeMap = { + study: studyMode, + keyword: keywordMode, + select: selectMode + }; + await modeMap[mode](baseDir); } diff --git a/common/view/language.view.js b/common/view/language.view.js index 75d461c..60d5a21 100644 --- a/common/view/language.view.js +++ b/common/view/language.view.js @@ -1,25 +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 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'; export async function easyLanguageView(defaultLang = DefaultLang) { - const list = LANGUAGES.map((o) => o.name) - const setQuestion = [ - { - type: 'list', - name: 'newSet', - message: - '请确认你要设置CLI的语言环境(如果选项匹配成功,那么按下回车确认即可)', - choices: list, - default: defaultLang - } - ] - const { newSet } = await inquirer.prompt(setQuestion, null) - logger.info('设置语言环境为:', newSet) - await setQuestionLanguage(newSet) - process.exit(0) + const list = LANGUAGES.map((o) => o.name); + const setQuestion = [ + { + type: 'list', + name: 'newSet', + message: '请确认你要设置CLI的语言环境(如果选项匹配成功,那么按下回车确认即可)', + choices: list, + default: defaultLang + } + ]; + const { newSet } = await inquirer.prompt(setQuestion, null); + logger.info('设置语言环境为:', newSet); + await setQuestionLanguage(newSet); + process.exit(0); } diff --git a/common/view/update.view.js b/common/view/update.view.js index 2d07757..4ebcd7b 100644 --- a/common/view/update.view.js +++ b/common/view/update.view.js @@ -1,37 +1,31 @@ -import inquirer from 'inquirer' -import { checkUpdate } from '#common/utils/update/update.js' -import { logger } from '#common/utils/logger/logger.js' -import { updateCli } from '#common/utils/update/updateByEnv.js' +import inquirer from 'inquirer'; +import { checkUpdate } from '#common/utils/update/update.js'; +import { logger } from '#common/utils/logger/logger.js'; +import { updateCli } from '#common/utils/update/updateByEnv.js'; export async function easyUpdateView() { - const { - localVersion = '未检出', - npmVersion = '未检出', - isCliUpdate - } = await checkUpdate() - logger.info(`当前版本:[ ${localVersion} ] npm包最新版本:[ ${npmVersion} ]`) - // 3. 询问是否更新 - if (isCliUpdate) { - const checkQuestion = { - type: 'confirm', - name: 'willUpdate', - message: `检测到可更新版本[ ${npmVersion} ],是否进行更新?` - } - const { willUpdate } = await inquirer.prompt(checkQuestion, null) - if (willUpdate) { - // 4.1 选择更新 - logger.info('开始更新...') - await updateCli() - logger.info('更新完成~祝你使用愉快~') + const { localVersion = '未检出', npmVersion = '未检出', isCliUpdate } = await checkUpdate(); + logger.info(`当前版本:[ ${localVersion} ] npm包最新版本:[ ${npmVersion} ]`); + // 3. 询问是否更新 + if (isCliUpdate) { + const checkQuestion = { + type: 'confirm', + name: 'willUpdate', + message: `检测到可更新版本[ ${npmVersion} ],是否进行更新?` + }; + const { willUpdate } = await inquirer.prompt(checkQuestion, null); + if (willUpdate) { + // 4.1 选择更新 + logger.info('开始更新...'); + await updateCli(); + logger.info('更新完成~祝你使用愉快~'); + } else { + // 4.2 取消更新 + logger.info('你选择跳过此次更新,如果想要进行更新,随时可以使用参数 -u 进行更新检测!祝你使用愉快~'); + } + process.exit(0); } else { - // 4.2 取消更新 - logger.info( - '你选择跳过此次更新,如果想要进行更新,随时可以使用参数 -u 进行更新检测!祝你使用愉快~' - ) + logger.info('当前已是最新版本!祝你使用愉快~'); + process.exit(0); } - process.exit(0) - } else { - logger.info('当前已是最新版本!祝你使用愉快~') - process.exit(0) - } } diff --git a/esbuild.config.js b/esbuild.config.js index 3a0abea..86966c6 100644 --- a/esbuild.config.js +++ b/esbuild.config.js @@ -1,128 +1,110 @@ -import path from 'node:path' -import fs from 'node:fs' -import esbuild from 'esbuild' -import { rootPath } from '#common/utils/file/getRootPath.js' -import { logger } from '#common/utils/logger/logger.js' +import path from 'node:path'; +import fs from 'node:fs'; +import esbuild from 'esbuild'; +import { rootPath } from '#common/utils/file/getRootPath.js'; +import { logger } from '#common/utils/logger/logger.js'; // 读取 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', - platform: 'node', - target: ['node20'], - format: 'esm', - bundle: true, - minify: true, - packages: 'external', - define: { - 'process.env.VERSION': JSON.stringify(packageJson.version) - } -} + entryPoints: ['bin/lk.js', 'bin/lf.js', 'bin/lc.js'], + outdir: 'pl-cli/bin', + platform: 'node', + target: ['node20'], + format: 'esm', + bundle: true, + minify: true, + packages: 'external', + define: { + 'process.env.VERSION': JSON.stringify(packageJson.version) + } +}; const buildBinConfig = { - lk: 'bin/lk.js', - lf: 'bin/lf.js', - lc: 'bin/lc.js' -} -const publishExcludeFields = [ - 'scripts', - 'devDependencies', - 'imports', - 'main', - 'config', - 'packageManager' -] + lk: 'bin/lk.js', + lf: 'bin/lf.js', + lc: 'bin/lc.js' +}; +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() - else resolve() - }) - }) + return new Promise((resolve) => { + fs.rm(path.resolve(rootPath, 'pl-cli'), { recursive: true }, (err) => { + if (err) resolve(); + else resolve(); + }); + }); } /** * 复制文档 */ function copyDocs() { - // 创建docs - const docs = ['README.md', 'README_CN.md', 'README_JP.md'] - docs.forEach((doc) => { - fs.copyFileSync( - path.resolve(rootPath, doc), - path.resolve(rootPath, `pl-cli/${doc}`) - ) - }) - fs.copyFileSync( - path.resolve(rootPath, 'LICENSE'), - path.resolve(rootPath, 'pl-cli/LICENSE') - ) + // 创建docs + const docs = ['README.md', 'README_CN.md', 'README_JP.md']; + docs.forEach((doc) => { + fs.copyFileSync(path.resolve(rootPath, doc), path.resolve(rootPath, `pl-cli/${doc}`)); + }); + fs.copyFileSync(path.resolve(rootPath, 'LICENSE'), path.resolve(rootPath, 'pl-cli/LICENSE')); } /** * 重写包文件 */ function rewritePackageFile() { - const newPackageJson = Object.assign(packageJson, { - bin: buildBinConfig - }) - publishExcludeFields?.forEach((key) => { - delete newPackageJson[key] - }) - fs.writeFileSync( - path.resolve(rootPath, 'pl-cli/package.json'), - JSON.stringify(newPackageJson) - ) + const newPackageJson = Object.assign(packageJson, { + bin: buildBinConfig + }); + publishExcludeFields?.forEach((key) => { + delete newPackageJson[key]; + }); + 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' - }) + 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() - createOrigin() + copyDocs(); + rewritePackageFile(); + createOrigin(); } /** * 主进程 */ async function main() { - await clean() - await esbuild - .build(esbuildConfig) - .then(() => { - // 构建完成后执行的操作 - afterBuild() - logger.info('[LP]脚本打包完成,请查看目录[ pl-cli ].') - process.exit(0) - }) - .catch((e) => { - logger.error('[LP]脚本打包失败', e) - process.exit(1) - }) + await clean(); + await esbuild + .build(esbuildConfig) + .then(() => { + // 构建完成后执行的操作 + afterBuild(); + logger.info('[LP]脚本打包完成,请查看目录[ pl-cli ].'); + process.exit(0); + }) + .catch((e) => { + logger.error('[LP]脚本打包失败', e); + process.exit(1); + }); } -await main() +await main(); diff --git a/eslint.config.js b/eslint.config.js index 4d0a629..c2dffd9 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,11 +1,11 @@ -import antfu from '@antfu/eslint-config' +import antfu from '@antfu/eslint-config'; export default antfu({ - rules: { - 'node/prefer-global/process': 'off', - 'no-console': 'off', - 'no-irregular-whitespace': 'off', - 'eslint-comments/no-unlimited-disable': 'off', - 'no-cond-assign': 'off' - } -}) + rules: { + 'node/prefer-global/process': 'off', + 'no-console': 'off', + 'no-irregular-whitespace': 'off', + 'eslint-comments/no-unlimited-disable': 'off', + 'no-cond-assign': 'off' + } +}); diff --git a/jsconfig.json b/jsconfig.json index 18a0e05..b010d48 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,9 +1,9 @@ { - "compilerOptions": { - "baseUrl": "./", - "paths": { - "#common/*": ["./common/*"], - "#resources/*": ["./resources/*"] + "compilerOptions": { + "baseUrl": "./", + "paths": { + "#common/*": ["./common/*"], + "#resources/*": ["./resources/*"] + } } - } } diff --git a/package.json b/package.json index 6a73cd9..9a3139c 100644 --- a/package.json +++ b/package.json @@ -1,94 +1,94 @@ { - "name": "leetcode-practice", - "type": "module", - "version": "1.0.9-4", - "description": "A powerful practice platform for leetcode.Using any way you want to create questions.", - "author": { - "name": "EternalHeart", - "email": "hao131462@qq.com" - }, - "publishConfig": { - "registry": "https://registry.npmjs.org/" - }, - "license": "ISC", - "repository": { - "type": "git", - "url": "git+https://github.com/wh131462/leetcode-practice.git" - }, - "imports": { - "#common/*": "./common/*", - "#resources/*": "./resources/*" - }, - "bin": { - "lk": "bin/lk.js", - "lf": "bin/lf.js", - "lc": "bin/lc.js" - }, - "scripts": { - "lc": "node bin/lc.js -d src", - "lk": "node bin/lk.js -d src", - "lf": "node bin/lf.js -d src", - "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/", - "commit": "cz", - "test": "vitest run --reporter=verbose --teardown-timeout=5000 --pool=forks", - "coverage": "vitest run --coverage --pool=forks", - "format": "prettier --write .", - "lint": "eslint . --fix", - "lint:all": "eslint .", - "prepare": "husky install", - "create-color-font": "node scripts/create-color-font.js", - "release": "release-it", - "try-release": "release-it --dry-run", - "rebase": "HUSKY=0 git rebase " - }, - "dependencies": { - "@inquirer/input": "^2.0.1", - "@inquirer/select": "^2.0.0", - "chalk": "^5.3.0", - "commander": "^12.0.0", - "console-table-printer": "^2.12.0", - "glob": "^10.3.10", - "inquirer": "^9.2.14", - "ora": "^8.0.1", - "realm": "^12.6.2" - }, - "devDependencies": { - "@antfu/eslint-config": "^2.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", - "@vitest/coverage-v8": "^1.2.2", - "commitizen": "^4.2.5", - "cz-conventional-changelog": "^3.3.0", - "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": "^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" - }, - "lint-staged": { - "*": [ - "eslint", - "prettier --write" - ] - }, - "config": { - "commitizen": { - "path": "./node_modules/cz-conventional-changelog" + "name": "leetcode-practice", + "type": "module", + "version": "1.0.9-4", + "description": "A powerful practice platform for leetcode.Using any way you want to create questions.", + "author": { + "name": "EternalHeart", + "email": "hao131462@qq.com" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/wh131462/leetcode-practice.git" + }, + "imports": { + "#common/*": "./common/*", + "#resources/*": "./resources/*" + }, + "bin": { + "lk": "bin/lk.js", + "lf": "bin/lf.js", + "lc": "bin/lc.js" + }, + "scripts": { + "lc": "node bin/lc.js -d src", + "lk": "node bin/lk.js -d src", + "lf": "node bin/lf.js -d src", + "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/", + "commit": "cz", + "test": "vitest run --reporter=verbose --teardown-timeout=5000 --pool=forks", + "coverage": "vitest run --coverage --pool=forks", + "format": "prettier --write .", + "lint": "eslint . --fix", + "lint:all": "eslint .", + "prepare": "husky install", + "create-color-font": "node scripts/create-color-font.js", + "release": "release-it", + "try-release": "release-it --dry-run", + "rebase": "HUSKY=0 git rebase " + }, + "dependencies": { + "@inquirer/input": "^2.0.1", + "@inquirer/select": "^2.0.0", + "chalk": "^5.3.0", + "commander": "^12.0.0", + "console-table-printer": "^2.12.0", + "glob": "^10.3.10", + "inquirer": "^9.2.14", + "ora": "^8.0.1", + "realm": "^12.6.2" + }, + "devDependencies": { + "@antfu/eslint-config": "^2.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", + "@vitest/coverage-v8": "^1.2.2", + "commitizen": "^4.2.5", + "cz-conventional-changelog": "^3.3.0", + "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": "^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" + }, + "lint-staged": { + "*": [ + "eslint", + "prettier --write" + ] + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } } - } } diff --git a/resources/headers/allQuestionRequestUrlJson.js b/resources/headers/allQuestionRequestUrlJson.js new file mode 100644 index 0000000..b701a41 --- /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..ab1cc44 100644 --- a/resources/headers/codeSubmitJson.js +++ b/resources/headers/codeSubmitJson.js @@ -7,13 +7,13 @@ * @returns {{headers: {"content-type": string}, method: string, body: string}} */ export function codeSubmitJson(lang, id, code) { - return { - headers: { 'content-type': 'application/json' }, - body: `{ + return { + headers: { 'content-type': 'application/json' }, + body: `{ "lang": "${lang}", "question_id": "${id}", "typed_code": "${code}" }`, - method: 'POST' - } + method: 'POST' + }; } diff --git a/resources/headers/planQuestionListJson.js b/resources/headers/planQuestionListJson.js index e08d174..b864bb1 100644 --- a/resources/headers/planQuestionListJson.js +++ b/resources/headers/planQuestionListJson.js @@ -3,9 +3,9 @@ * @returns {{headers: {"content-type": string}, method: string, body: string}} */ 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 translatedTitle\\n status\\n }\\n }\\n }\\n}\\n ","variables":{"slug":"${slug}"},"operationName":"studyPlanPastSolved"}`, - method: 'POST' - } + 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 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..5eeba0b 100644 --- a/resources/headers/questionCodeListJson.js +++ b/resources/headers/questionCodeListJson.js @@ -1,7 +1,7 @@ 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' - } + 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' + }; } diff --git a/resources/headers/questionDetailJson.js b/resources/headers/questionDetailJson.js index 9cb0aa2..6ec9b0a 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' - } + return { + headers: { 'content-type': 'application/json' }, + 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..666c0fc 100644 --- a/resources/headers/questionLanguageListJson.js +++ b/resources/headers/questionLanguageListJson.js @@ -3,13 +3,13 @@ * @returns {{headers: {"content-type": string}, method: string, body: string}} */ export function getQuestionLanguageListJson() { - return { - headers: { 'content-type': 'application/json' }, - body: `{ + return { + headers: { 'content-type': 'application/json' }, + body: `{ "query": "\\n query languageList {\\n languageList {\\n id\\n name\\n }\\n}\\n ", "variables": {}, "operationName": "languageList" }`, - method: 'POST' - } + method: 'POST' + }; } diff --git a/resources/headers/questionListJson.js b/resources/headers/questionListJson.js index d197c2f..c1f0b59 100644 --- a/resources/headers/questionListJson.js +++ b/resources/headers/questionListJson.js @@ -1,7 +1,7 @@ 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' - } + 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' + }; } diff --git a/resources/headers/questionSearchJson.js b/resources/headers/questionSearchJson.js index ad2a370..f52a491 100644 --- a/resources/headers/questionSearchJson.js +++ b/resources/headers/questionSearchJson.js @@ -1,7 +1,7 @@ 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' - } + 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' + }; } diff --git a/resources/headers/questionTagTypeJson.js b/resources/headers/questionTagTypeJson.js new file mode 100644 index 0000000..4963751 --- /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..10805e1 100644 --- a/resources/headers/questionTodayJson.js +++ b/resources/headers/questionTodayJson.js @@ -1,7 +1,7 @@ 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' - } + 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' + }; } diff --git a/resources/headers/questionTypeJson.js b/resources/headers/questionTypeJson.js index 176c020..667014e 100644 --- a/resources/headers/questionTypeJson.js +++ b/resources/headers/questionTypeJson.js @@ -1,11 +1,11 @@ export function getQuestionTypesJson() { - return { - headers: { 'content-type': 'application/json' }, - body: `{ + 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' - } + method: 'POST' + }; } diff --git a/resources/headers/studyPlanListJson.js b/resources/headers/studyPlanListJson.js index b33bd44..32a5047 100644 --- a/resources/headers/studyPlanListJson.js +++ b/resources/headers/studyPlanListJson.js @@ -2,9 +2,9 @@ // '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' - } + 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/template/template.js b/resources/template/template.js index 0463638..a82f250 100644 --- a/resources/template/template.js +++ b/resources/template/template.js @@ -6,4 +6,4 @@ export const template = `@Title @TestCase @Console -` +`; diff --git a/resources/text/aim.js b/resources/text/aim.js index 056735d..863df10 100644 --- a/resources/text/aim.js +++ b/resources/text/aim.js @@ -1 +1 @@ -export const aim = `☕️ Enjoy your time on coding.` +export const aim = `☕️ Enjoy your time on coding.`; diff --git a/resources/text/art-font-logo.js b/resources/text/art-font-logo.js index 141f876..55c2d35 100644 --- a/resources/text/art-font-logo.js +++ b/resources/text/art-font-logo.js @@ -3,4 +3,4 @@ export const artFontLogo = ` __ _ _ ___ / / / _ \\/ _ \\ __/ __/ _ \\ / _\` |/ _ \\ / /_)/ '__/ _\` |/ __| __| |/ __/ _ \\ / /__| __/ __/ || (_| (_) | (_| | __/ / ___/| | | (_| | (__| |_| | (_| __/ \\____/\\___|\\___|\\__\\___\\___/ \\__,_|\\___| \\/ |_| \\__,_|\\___|\\__|_|\\___\\___| - ` + `; diff --git a/resources/text/description.js b/resources/text/description.js index ebcc133..86094f2 100644 --- a/resources/text/description.js +++ b/resources/text/description.js @@ -2,4 +2,4 @@ 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 -` +`; diff --git a/resources/text/examples.js b/resources/text/examples.js index 7ea9cf6..30759d8 100644 --- a/resources/text/examples.js +++ b/resources/text/examples.js @@ -16,7 +16,7 @@ Examples: $ lc -v // Check the CLI version. $ lc -h // Check the help information. -` +`; export const lkExamples = ` Examples: @@ -36,7 +36,7 @@ Examples: $ lk -v // Check the CLI version. $ lk -h // Display the help information. -` +`; export const lfExamples = ` Examples: @@ -53,4 +53,4 @@ Examples: $ lf -v // Check the CLI version. $ lf -h // Display the help information. -` +`; diff --git a/resources/text/love.js b/resources/text/love.js index 40b1b38..8586ab2 100644 --- a/resources/text/love.js +++ b/resources/text/love.js @@ -1 +1 @@ -export const love = `Made with ❤️ by EternalHeart team.` +export const love = `Made with ❤️ by EternalHeart team.`; diff --git a/scripts/create-color-font.js b/scripts/create-color-font.js index d464df3..43c97f3 100644 --- a/scripts/create-color-font.js +++ b/scripts/create-color-font.js @@ -1,13 +1,13 @@ -import inquirer from 'inquirer' -import { createColorFont } from '#common/utils/etc/createColorFont.js' +import inquirer from 'inquirer'; +import { createColorFont } from '#common/utils/etc/createColorFont.js'; const question = [ - { - type: 'input', - name: 'font', - message: '请输入要渐变色的文本:' - } -] + { + type: 'input', + name: 'font', + message: '请输入要渐变色的文本:' + } +]; // 第一个问题 选择的模式 -const { font } = await inquirer.prompt(question, null) -createColorFont(font) +const { font } = await inquirer.prompt(question, null); +createColorFont(font); diff --git a/scripts/loading.js b/scripts/loading.js index 5399e09..feb12c9 100644 --- a/scripts/loading.js +++ b/scripts/loading.js @@ -1,4 +1,4 @@ -import ora from 'ora' +import ora from 'ora'; -const loading = ora('LP!给我加载!!!!').start() -setTimeout(() => loading.stop(), 300000) +const loading = ora('LP!给我加载!!!!').start(); +setTimeout(() => loading.stop(), 300000); diff --git a/test/create.spec.js b/test/create.spec.js index da89d7e..102a844 100644 --- a/test/create.spec.js +++ b/test/create.spec.js @@ -1,70 +1,70 @@ -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 { generateTemplateContent } from '#common/utils/question-handler/fulfillQuestion.js' +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 { generateTemplateContent } from '#common/utils/question-handler/fulfillQuestion.js'; vi.mock('fs/promises', () => { - return { - 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(') + return { + 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 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) - // 是否含有函数 - expect(isContainJsCode(content)).toBeTruthy() - // 是否含有测试用例 - expect(isContainTestCase(content)).toBeTruthy() - // 是否含有描述 - expect(content.includes('示例')).toBeTruthy() - expect(content.includes('提示')).toBeTruthy() + const content = generateTemplateContent(res); + // 是否含有函数 + expect(isContainJsCode(content)).toBeTruthy(); + // 是否含有测试用例 + expect(isContainTestCase(content)).toBeTruthy(); + // 是否含有描述 + expect(content.includes('示例')).toBeTruthy(); + expect(content.includes('提示')).toBeTruthy(); } describe('lc', () => { - // 清楚mock历史记录 - afterEach(() => { - vi.clearAllMocks() - }) - describe('with -t option', async () => { - const res = await getQuestionToday() + // 清楚mock历史记录 + afterEach(() => { + vi.clearAllMocks(); + }); + describe('with -t option', async () => { + const res = await getQuestionToday(); - it('是否正确获取了今天的题目', () => { - expect(Object.keys(res)).toEqual(mockKeys) - }) - it('是否正确的填充了今天的题目', async () => { - isValidQuestion(res) - }) - }) - describe('with -i option', async () => { - const id_25 = '25' - const res_25 = await getQuestionById(id_25) - const id_LCS_03 = 'LCS 03' - const res_LCS_03 = await getQuestionById(id_LCS_03) - it('是否正确的获取了指定id的题目 25', async () => { - expect(res_25.id).toEqual(id_25) - }) - it('是否正确填充了指定id的题目 25', async () => { - isValidQuestion(res_25) - }) - it('是否正确的获取了指定id的题目 LCS 03', async () => { - expect(res_LCS_03.id).toEqual(id_LCS_03) - }) - it('是否正确填充了指定id的题目 9', async () => { - isValidQuestion(res_LCS_03) - }) + it('是否正确获取了今天的题目', () => { + expect(Object.keys(res)).toEqual(mockKeys); + }); + it('是否正确的填充了今天的题目', async () => { + isValidQuestion(res); + }); + }); + describe('with -i option', async () => { + const id_25 = '25'; + const res_25 = await getQuestionById(id_25); + const id_LCS_03 = 'LCS 03'; + const res_LCS_03 = await getQuestionById(id_LCS_03); + it('是否正确的获取了指定id的题目 25', async () => { + expect(res_25.id).toEqual(id_25); + }); + it('是否正确填充了指定id的题目 25', async () => { + isValidQuestion(res_25); + }); + it('是否正确的获取了指定id的题目 LCS 03', async () => { + expect(res_LCS_03.id).toEqual(id_LCS_03); + }); + it('是否正确填充了指定id的题目 9', async () => { + isValidQuestion(res_LCS_03); + }); - it('是否正确的获取了指定内容的题目 主题空间', async () => { - const content = '主题空间' - const res = await getQuestionById(content) - expect(res?.id).toEqual(null) - }) - }) - // describe('with -r option', async () => { + it('是否正确的获取了指定内容的题目 主题空间', async () => { + const content = '主题空间'; + const res = await getQuestionById(content); + expect(res?.id).toEqual(null); + }); + }); + // describe('with -r option', async () => { - // }) -}) + // }) +}); 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..5edfdad 100644 --- a/test/listNode.spec.js +++ b/test/listNode.spec.js @@ -1,36 +1,36 @@ -import { expect, it } from 'vitest' -import { ListNode } from '#common/structures/ListNode' +import { expect, it } from 'vitest'; +import { ListNode } from '#common/structures/ListNode'; it('toArray 正常数组', () => { - // 创建链表 - const head = new ListNode(1) - const node1 = new ListNode(2) - const node2 = new ListNode(3) - head.next = node1 - node1.next = node2 + // 创建链表 + const head = new ListNode(1); + const node1 = new ListNode(2); + const node2 = new ListNode(3); + head.next = node1; + node1.next = node2; - const arr = ListNode.toArray(head) - expect(arr).toEqual([1, 2, 3]) -}) + const arr = ListNode.toArray(head); + expect(arr).toEqual([1, 2, 3]); +}); it('toArray undefined', () => { - const arr = ListNode.toArray(undefined) - expect(arr).toEqual([]) -}) + const arr = ListNode.toArray(undefined); + expect(arr).toEqual([]); +}); it('toArray false', () => { - const arr = ListNode.toArray(false) - expect(arr).toEqual([undefined]) -}) + const arr = ListNode.toArray(false); + expect(arr).toEqual([undefined]); +}); it('toArray 1', () => { - const arr = ListNode.toArray(1) - expect(arr).toEqual([undefined]) -}) + const arr = ListNode.toArray(1); + expect(arr).toEqual([undefined]); +}); it('parse [1,2,3]', () => { - const listNode = ListNode.parse([1, 2, 3]) - expect(listNode.val).toEqual(1) - expect(listNode.next?.val).toEqual(2) - expect(listNode.next?.next?.val).toEqual(3) -}) + const listNode = ListNode.parse([1, 2, 3]); + expect(listNode.val).toEqual(1); + expect(listNode.next?.val).toEqual(2); + expect(listNode.next?.next?.val).toEqual(3); +}); it('parse []', () => { - const listNode = ListNode.parse([]) - expect(listNode).toEqual(null) -}) + const listNode = ListNode.parse([]); + expect(listNode).toEqual(null); +}); 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..f453a2e 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'; +import { getDataStructure } from '#common/utils/question-handler/parseStructure.js'; const mockJSDOC_multiple = `/** * Definition for singly-linked list. @@ -17,7 +17,7 @@ const mockJSDOC_multiple = `/** */ var mergeInBetween = function(list1, a, b, list2) { console.log(list1.val,list1) -};` +};`; const mockJSDOC_single = `/** * Definition for singly-linked list. @@ -32,7 +32,7 @@ const mockJSDOC_single = `/** */ var sortList = function(head) { -};` +};`; const return_void = `/** * Definition for singly-linked list. * function ListNode(val, next) { @@ -46,7 +46,7 @@ const return_void = `/** */ var reorderList = function(head) { -};` +};`; const mockJSDOC_ListNodeArray = `/** * Definition for singly-linked list. @@ -75,35 +75,33 @@ var mergeKLists = function(lists) { } -};` +};`; -const array = ['ListNode', 'number', 'number', 'ListNode'] +const array = ['ListNode', 'number', 'number', 'ListNode']; it('获取入参的数据结构 多参 是数组', () => { - expect(getDataStructure(mockJSDOC_multiple)).toBeInstanceOf(Array) -}) + expect(getDataStructure(mockJSDOC_multiple)).toBeInstanceOf(Array); +}); it('获取入参的数据结构 多参 匹配值', () => { - expect(getDataStructure(mockJSDOC_multiple)).toEqual(array) -}) + expect(getDataStructure(mockJSDOC_multiple)).toEqual(array); +}); it('获取入参的数据结构 单参 是数组', () => { - expect(getDataStructure(mockJSDOC_single)).toBeInstanceOf(Array) -}) + expect(getDataStructure(mockJSDOC_single)).toBeInstanceOf(Array); +}); it('获取入参的数据结构 单参 匹配值', () => { - expect(getDataStructure(mockJSDOC_single)).toEqual(['ListNode']) -}) + expect(getDataStructure(mockJSDOC_single)).toEqual(['ListNode']); +}); it('获取入参的数据结构 单参 ListNode[]', () => { - expect(getDataStructure(mockJSDOC_ListNodeArray, 'param')).toEqual([ - 'ListNode[]' - ]) -}) + expect(getDataStructure(mockJSDOC_ListNodeArray, 'param')).toEqual(['ListNode[]']); +}); it('获取返回值的数据结构 单参 匹配值', () => { - expect(getDataStructure(mockJSDOC_single, 'return')).toEqual(['ListNode']) -}) + expect(getDataStructure(mockJSDOC_single, 'return')).toEqual(['ListNode']); +}); it('获取返回值的数据结构 多参 匹配值', () => { - expect(getDataStructure(mockJSDOC_multiple, 'return')).toEqual(['ListNode']) -}) + expect(getDataStructure(mockJSDOC_multiple, 'return')).toEqual(['ListNode']); +}); it('获取返回值的数据结构 单参 void', () => { - expect(getDataStructure(return_void, 'return')).toEqual(['void']) -}) + expect(getDataStructure(return_void, 'return')).toEqual(['void']); +}); diff --git a/test/setDataStructure.spec.js b/test/setDataStructure.spec.js index 732362f..5f91267 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'; +import { getDataStructure } from '#common/utils/question-handler/parseStructure.js'; const jsDoc = `/** * Definition for singly-linked list. @@ -50,11 +50,11 @@ const mergeLists = (lists, start, end) => { return merge(head1, head2); }; return mergeLists(lists, 0, lists.length); -};` +};`; it('测试', () => { - const param = getDataStructure(jsDoc) - const returnArray = getDataStructure(jsDoc, 'return') - expect(param).toEqual(['ListNode[]']) - expect(returnArray).toEqual(['ListNode']) -}) + const param = getDataStructure(jsDoc); + const returnArray = getDataStructure(jsDoc, 'return'); + expect(param).toEqual(['ListNode[]']); + expect(returnArray).toEqual(['ListNode']); +}); diff --git a/test/tree.spec.js b/test/tree.spec.js index 63aad82..d112acb 100644 --- a/test/tree.spec.js +++ b/test/tree.spec.js @@ -1,44 +1,34 @@ -import { expect, it } from 'vitest' -import { TreeNode } from '#common/structures/TreeNode' +import { expect, it } from 'vitest'; +import { TreeNode } from '#common/structures/TreeNode'; -const mockTree = [1, 2, 3] -const mockTree2 = [1, null, 2] -const mockTree3 = [3, 9, 20, null, null, 15, 7] +const mockTree = [1, 2, 3]; +const mockTree2 = [1, null, 2]; +const mockTree3 = [3, 9, 20, null, null, 15, 7]; it('测试树', () => { - const node = TreeNode.parse(mockTree) - const result = TreeNode.toArray(node) + const node = TreeNode.parse(mockTree); + const result = TreeNode.toArray(node); - const node2 = TreeNode.parse(mockTree2) - const result2 = TreeNode.toArray(node2) - expect(result2).toEqual(mockTree2) - expect(result).toEqual(mockTree) -}) + const node2 = TreeNode.parse(mockTree2); + const result2 = TreeNode.toArray(node2); + expect(result2).toEqual(mockTree2); + expect(result).toEqual(mockTree); +}); it('测试树 toArray特殊值', () => { - expect(TreeNode.toArray(null)).toEqual([]) -}) + expect(TreeNode.toArray(null)).toEqual([]); +}); it('测试树 parse 特殊值', () => { - expect(TreeNode.parse([])).toBeNull() -}) + 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()) -}) + expect(TreeNode.parse([0])).toEqual(new TreeNode()); +}); From e5088df0aac5a938ad3181965238fc40c7684cb5 Mon Sep 17 00:00:00 2001 From: EternalHeart <48346853+wh131462@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:50:39 +0800 Subject: [PATCH 3/4] chore: check question store before pull and init if not (#68) --- common/view/finder.view.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/common/view/finder.view.js b/common/view/finder.view.js index e99eac0..1bc0a65 100644 --- a/common/view/finder.view.js +++ b/common/view/finder.view.js @@ -8,7 +8,8 @@ import { getPlanQuestionList } from '#common/utils/question-getter/getPlanQuesti import { logger } from '#common/utils/logger/logger.js'; import { getQuestionListCodeBySlug, getQuestionListCodeByTag } from '#common/utils/question-handler/getQuestionListCodeBy.js'; import { getQuestionTagType } from '#common/utils/question-getter/getQuestionTagType.js'; -import { getAllQuestion } from '#common/utils/store/controller/allQuestion.js'; +import { getAllQuestion, setAllQuestion } from '#common/utils/store/controller/allQuestion.js'; +import { getAllQuestionList } from '#common/utils/question-getter/getAllQuestionList.js'; function handleQuestionList(list) { const questionList = []; @@ -126,8 +127,26 @@ async function selectMode(baseDir = process.cwd()) { }; const chooseTag = await select(tagQuestion); const allQuestion = await getAllQuestion(); - const tagQuestionList = await allQuestion.filter((question) => question.topicTags.some((topic) => topic.slug === chooseTag)); - + // 未发现题目 所以先自动拉取题目 + 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: [ @@ -135,7 +154,6 @@ async function selectMode(baseDir = process.cwd()) { { name: '全部拉取(不穩定)', value: 'all' } ] }); - if (createMode === 'single') { const singleMode = { type: 'list', From 0049530f792f1faba751c620f8fae06ce34f867d Mon Sep 17 00:00:00 2001 From: EternalHeart Date: Sun, 17 Mar 2024 11:51:23 +0800 Subject: [PATCH 4/4] chore: release v1.0.9-5 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a50a52b..272470e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [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 diff --git a/package.json b/package.json index 9a3139c..d187e85 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "leetcode-practice", "type": "module", - "version": "1.0.9-4", + "version": "1.0.9-5", "description": "A powerful practice platform for leetcode.Using any way you want to create questions.", "author": { "name": "EternalHeart",