From 7fff3b72a265360495e57a2c0e0d20b8c352a05b Mon Sep 17 00:00:00 2001 From: ZLY201 <951711127@qq.com> Date: Thu, 8 Feb 2024 13:53:26 +0800 Subject: [PATCH] chore: add new problem script --- .github/CONTRIBUTING.md | 2 + config/problems.json | 7 +- package.json | 3 + src/modules/Question/Description.tsx | 33 +++----- src/utils/problems.ts | 5 +- tools/addNewProblem.ts | 117 +++++++++++++++++++++++++++ tsconfig.json | 2 +- yarn.lock | 26 ++++++ 8 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 tools/addNewProblem.ts diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 469bd1e..2a8c599 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -49,6 +49,8 @@ Please follow the commit specification. See [`.commitlintrc.json`](https://githu ### Commonly used NPM scripts ```bash +# add new problem +$ yarn new # run project in development mode $ yarn dev # build all dist files diff --git a/config/problems.json b/config/problems.json index 26a0acf..f09a261 100644 --- a/config/problems.json +++ b/config/problems.json @@ -3,19 +3,22 @@ "key": "HelloWorld", "subject": "Basic Tutorial", "subjectKey": "BasicTutorial", - "title": "Hello, world!" + "title": "Hello, world!", + "author": "ZLY201" }, { "key": "EverydayTypes", "subject": "Basic Tutorial", "subjectKey": "BasicTutorial", - "title": "EveryDay Types" + "title": "EveryDay Types", + "author": "ZLY201" }, { "key": "TransposeMatrix", "subject": "Difficulties", "subjectKey": "Difficulties", "title": "Transpose Matrix", + "author": "ZLY201", "cases": [ { "source": "[[1, 2]]", diff --git a/package.json b/package.json index ed1363a..3306391 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "clean": "rm -rf dist", "dev": "rspack serve --watch --mode=development", "build": "yarn clean && rspack build --mode=production", + "new": "ts-node tools/addNewProblem.ts", "lint": "eslint --fix --color --cache --quiet .", "prepare": "husky install" }, @@ -56,6 +57,7 @@ "@types/event-emitter": "^0.3.4", "@types/lodash.debounce": "^4.0.7", "@types/node": "^20.8.9", + "@types/prompts": "^2.4.9", "@types/react": "^17.0.67", "@types/react-copy-to-clipboard": "^5.0.6", "@types/react-dom": "^17.0.21", @@ -80,6 +82,7 @@ "lint-staged": "^14.0.1", "monaco-editor": "^0.44.0", "prettier": "^3.0.3", + "prompts": "^2.4.2", "style-loader": "^3.3.3", "ts-node": "^10.9.1", "typescript": "^5.2.2" diff --git a/src/modules/Question/Description.tsx b/src/modules/Question/Description.tsx index 5265f4c..37ac3eb 100644 --- a/src/modules/Question/Description.tsx +++ b/src/modules/Question/Description.tsx @@ -3,7 +3,6 @@ import { Skeleton } from '@arco-design/web-react'; import debounce from 'lodash.debounce'; import Markdown from '@src/components/Markdown'; import Context from '@src/utils/context'; -import linkJson from '@config/links.json'; import { getProblemDocs, NULL_CASE, @@ -24,15 +23,7 @@ const Description = function () { setting: { theme, language }, }, ] = useContext(Context); - const { - key, - title, - contributor: { name, link } = { - name: 'ZLY201', - link: linkJson['github-zly201'], - }, - cases = [NULL_CASE], - } = currentProblem; + const { key, title, author, cases = [NULL_CASE] } = currentProblem; const [desc, setDesc] = useState(''); const [state, setState] = useState(false); const [loading, setLoading] = useState(true); @@ -107,16 +98,18 @@ const Description = function () { -
- - Provided By @{name} - -
+ {author && ( +
+ + Provided By @{author} + +
+ )} ); }; diff --git a/src/utils/problems.ts b/src/utils/problems.ts index 5a35771..10b6c0a 100644 --- a/src/utils/problems.ts +++ b/src/utils/problems.ts @@ -12,10 +12,7 @@ export type Problem = { subject: string; subjectKey: string; title: string; - contributor?: { - name: string; - link: string; - }; + author?: string; keywords?: string[]; cases?: { source: string; diff --git a/tools/addNewProblem.ts b/tools/addNewProblem.ts new file mode 100644 index 0000000..1768f2f --- /dev/null +++ b/tools/addNewProblem.ts @@ -0,0 +1,117 @@ +import fs from 'fs'; +import path from 'path'; +import prompts from 'prompts'; +import chalk from 'chalk'; +import problemJson from '../config/problems.json'; + +const PROBLEMS_PATH = path.resolve(__dirname, '../problems'); +const NEW_TYPE_TAG = 'new problem type'; +const HELLO_WORLD_PATH = path.resolve( + PROBLEMS_PATH, + 'basic-tutorial/1-hello-world', +); +const PROBLEM_JSON_PATH = path.resolve(__dirname, '../config/problems.json'); + +function handleStringWithDivider(source: string, divider: string = '') { + return source + .split('-') + .map(str => `${str[0].toUpperCase()}${str.slice(1)}`) + .join(divider); +} + +async function main() { + const types: string[] = []; + const typeFiles = fs.readdirSync(PROBLEMS_PATH); + typeFiles.forEach(function (item) { + const stat = fs.lstatSync(path.resolve(PROBLEMS_PATH, item)); + if (stat.isDirectory() === true) { + types.push(item); + } + }); + const typesChoices: prompts.Choice[] = types.map(type => ({ + title: type, + value: type, + })); + typesChoices.push({ + title: NEW_TYPE_TAG, + value: NEW_TYPE_TAG, + description: 'Add a new problem type', + }); + let { problemType } = await prompts({ + type: 'select', + name: 'problemType', + message: 'What type of problem do you want to create?', + choices: typesChoices, + }); + if (problemType === NEW_TYPE_TAG) { + const { newTypeName } = await prompts({ + type: 'text', + name: 'newTypeName', + initial: 'template-type', + message: 'What is the name of the new type?', + validate: value => + value === NEW_TYPE_TAG || types.includes(value) + ? 'This type already exists!' + : Boolean(value), + }); + fs.mkdirSync(path.resolve(PROBLEMS_PATH, newTypeName)); + problemType = newTypeName; + } + const problemDirPath = path.resolve(PROBLEMS_PATH, problemType); + const problemsFiles = fs.readdirSync(problemDirPath); + const problemNumber = + problemsFiles.filter(function (item) { + const stat = fs.lstatSync(path.resolve(problemDirPath, item)); + return stat.isDirectory(); + }).length + 1; + const { newProblemName } = await prompts({ + type: 'text', + name: 'newProblemName', + message: 'What is the name of the new problem?', + initial: 'template-problem', + validate: value => + value === NEW_TYPE_TAG || + problemsFiles.includes(`${problemNumber}-${value}`) + ? 'This problem already exists!' + : Boolean(value), + }); + const { githubName } = await prompts({ + type: 'text', + name: 'githubName', + message: 'Your github name to thanks:', + }); + const newProblemPath = path.resolve( + problemDirPath, + `${problemNumber}-${newProblemName}`, + ); + fs.cpSync(HELLO_WORLD_PATH, newProblemPath, { recursive: true }); + problemJson.push({ + key: handleStringWithDivider(newProblemName), + subject: handleStringWithDivider(problemType, ' '), + subjectKey: handleStringWithDivider(problemType), + title: handleStringWithDivider(newProblemName, ' '), + author: githubName, + cases: [], + }); + fs.writeFileSync( + PROBLEM_JSON_PATH, + JSON.stringify(problemJson, undefined, 2), + { + encoding: 'utf-8', + }, + ); + console.log( + `The new problem ${chalk.underline.green( + `${problemType}:${newProblemName}`, + )} has been created at ${chalk.underline.blue( + `problems/${problemNumber}-${newProblemName}`, + )}.`, + ); + console.log( + `Please go ${chalk.blue.underline( + 'config/problems.json', + )} to edit the config of this new problem.`, + ); +} + +main(); diff --git a/tsconfig.json b/tsconfig.json index 0b04036..47cda71 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -42,7 +42,7 @@ ], "ts-node": { "compilerOptions": { - "module": "commonjs" + "module": "CommonJS" } } } diff --git a/yarn.lock b/yarn.lock index 4bdbd7c..ab6a683 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1925,6 +1925,14 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz#291c243e4b94dbfbc0c0ee26b7666f1d5c030e2c" integrity sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg== +"@types/prompts@^2.4.9": + version "2.4.9" + resolved "https://registry.yarnpkg.com/@types/prompts/-/prompts-2.4.9.tgz#8775a31e40ad227af511aa0d7f19a044ccbd371e" + integrity sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA== + dependencies: + "@types/node" "*" + kleur "^3.0.3" + "@types/prop-types@*": version "15.7.9" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d" @@ -5151,6 +5159,11 @@ kind-of@^6.0.3: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + kleur@^4.0.3: version "4.1.5" resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" @@ -6556,6 +6569,14 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -7267,6 +7288,11 @@ sirv@^1.0.7: mrmime "^1.0.0" totalist "^1.0.0" +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"