├── .gitignore ├── README.md ├── README.zh-CN.md ├── package.json ├── pnpm-lock.yaml └── src ├── index.ts ├── template ├── Drawer.tsx.tpl ├── Modal.tsx.tpl ├── Table.tsx.tpl ├── constant.tsx.tpl └── test.tsx.tpl └── util.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # code-generator 2 | 3 | English | [简体中文](./README.zh-CN.md) 4 | 5 | According to the template of the local code, the code file is generated in the command execution directory, and variables can be injected and variable default values can be set. 6 | 7 | ## There are problems 8 | 9 | - The template is in the form of text, so you cannot use functions such as code highlighting, prompting, error verification, etc. 10 | - Before executing the script on the command line, you must enter the directory where the generated code is located, which is a bit cumbersome. -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | # code-generator 2 | 3 | [English](./README.md) | 简体中文 4 | 5 | 根据本地代码的模版在命令执行目录下生成代码文件,可以注入变量以及设置变量默认值 6 | 7 | ## 存在的问题 8 | 9 | - 模版是文本的形式,也就无法使用代码高亮、提示、错误校验等功能 10 | - 命令行执行脚本前,必须进入生成代码所在的目录下,稍显繁琐 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code-generator", 3 | "version": "0.0.1", 4 | "description": "Generate code from the template.", 5 | "type": "module", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/nmsn/code-generator.git" 10 | }, 11 | "keywords": [ 12 | "code-generator", 13 | "node", 14 | "template" 15 | ], 16 | "author": "nmsn <136696700@qq.com>", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/nmsn/code-generator/issues" 20 | }, 21 | "homepage": "https://github.com/nmsn/code-generator#readme", 22 | "dependencies": { 23 | "chalk": "^5.2.0", 24 | "inquirer": "^9.1.4", 25 | "mustache": "^4.2.0" 26 | }, 27 | "devDependencies": { 28 | "@types/inquirer": "^9.0.3", 29 | "@types/node": "^20.1.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | dependencies: 4 | chalk: 5 | specifier: ^5.2.0 6 | version: 5.2.0 7 | inquirer: 8 | specifier: ^9.1.4 9 | version: 9.1.4 10 | mustache: 11 | specifier: ^4.2.0 12 | version: 4.2.0 13 | 14 | devDependencies: 15 | '@types/inquirer': 16 | specifier: ^9.0.3 17 | version: 9.0.3 18 | '@types/node': 19 | specifier: ^20.1.1 20 | version: 20.1.1 21 | 22 | packages: 23 | 24 | /@types/inquirer@9.0.3: 25 | resolution: {integrity: sha512-CzNkWqQftcmk2jaCWdBTf9Sm7xSw4rkI1zpU/Udw3HX5//adEZUIm9STtoRP1qgWj0CWQtJ9UTvqmO2NNjhMJw==} 26 | dependencies: 27 | '@types/through': 0.0.30 28 | rxjs: 7.8.0 29 | dev: true 30 | 31 | /@types/node@20.1.1: 32 | resolution: {integrity: sha512-uKBEevTNb+l6/aCQaKVnUModfEMjAl98lw2Si9P5y4hLu9tm6AlX2ZIoXZX6Wh9lJueYPrGPKk5WMCNHg/u6/A==} 33 | dev: true 34 | 35 | /@types/through@0.0.30: 36 | resolution: {integrity: sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==} 37 | dependencies: 38 | '@types/node': 20.1.1 39 | dev: true 40 | 41 | /ansi-escapes@6.0.0: 42 | resolution: {integrity: sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==} 43 | engines: {node: '>=14.16'} 44 | dependencies: 45 | type-fest: 3.5.1 46 | dev: false 47 | 48 | /ansi-regex@6.0.1: 49 | resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} 50 | engines: {node: '>=12'} 51 | dev: false 52 | 53 | /ansi-styles@6.2.1: 54 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 55 | engines: {node: '>=12'} 56 | dev: false 57 | 58 | /base64-js@1.5.1: 59 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 60 | dev: false 61 | 62 | /bl@5.1.0: 63 | resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} 64 | dependencies: 65 | buffer: 6.0.3 66 | inherits: 2.0.4 67 | readable-stream: 3.6.0 68 | dev: false 69 | 70 | /buffer@6.0.3: 71 | resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 72 | dependencies: 73 | base64-js: 1.5.1 74 | ieee754: 1.2.1 75 | dev: false 76 | 77 | /chalk@5.2.0: 78 | resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} 79 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 80 | dev: false 81 | 82 | /chardet@0.7.0: 83 | resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} 84 | dev: false 85 | 86 | /cli-cursor@4.0.0: 87 | resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} 88 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 89 | dependencies: 90 | restore-cursor: 4.0.0 91 | dev: false 92 | 93 | /cli-spinners@2.7.0: 94 | resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} 95 | engines: {node: '>=6'} 96 | dev: false 97 | 98 | /cli-width@4.0.0: 99 | resolution: {integrity: sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==} 100 | engines: {node: '>= 12'} 101 | dev: false 102 | 103 | /clone@1.0.4: 104 | resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} 105 | engines: {node: '>=0.8'} 106 | dev: false 107 | 108 | /defaults@1.0.4: 109 | resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} 110 | dependencies: 111 | clone: 1.0.4 112 | dev: false 113 | 114 | /eastasianwidth@0.2.0: 115 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 116 | dev: false 117 | 118 | /emoji-regex@9.2.2: 119 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 120 | dev: false 121 | 122 | /escape-string-regexp@5.0.0: 123 | resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} 124 | engines: {node: '>=12'} 125 | dev: false 126 | 127 | /external-editor@3.1.0: 128 | resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} 129 | engines: {node: '>=4'} 130 | dependencies: 131 | chardet: 0.7.0 132 | iconv-lite: 0.4.24 133 | tmp: 0.0.33 134 | dev: false 135 | 136 | /figures@5.0.0: 137 | resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} 138 | engines: {node: '>=14'} 139 | dependencies: 140 | escape-string-regexp: 5.0.0 141 | is-unicode-supported: 1.3.0 142 | dev: false 143 | 144 | /iconv-lite@0.4.24: 145 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 146 | engines: {node: '>=0.10.0'} 147 | dependencies: 148 | safer-buffer: 2.1.2 149 | dev: false 150 | 151 | /ieee754@1.2.1: 152 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 153 | dev: false 154 | 155 | /inherits@2.0.4: 156 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 157 | dev: false 158 | 159 | /inquirer@9.1.4: 160 | resolution: {integrity: sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==} 161 | engines: {node: '>=12.0.0'} 162 | dependencies: 163 | ansi-escapes: 6.0.0 164 | chalk: 5.2.0 165 | cli-cursor: 4.0.0 166 | cli-width: 4.0.0 167 | external-editor: 3.1.0 168 | figures: 5.0.0 169 | lodash: 4.17.21 170 | mute-stream: 0.0.8 171 | ora: 6.1.2 172 | run-async: 2.4.1 173 | rxjs: 7.8.0 174 | string-width: 5.1.2 175 | strip-ansi: 7.0.1 176 | through: 2.3.8 177 | wrap-ansi: 8.0.1 178 | dev: false 179 | 180 | /is-interactive@2.0.0: 181 | resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} 182 | engines: {node: '>=12'} 183 | dev: false 184 | 185 | /is-unicode-supported@1.3.0: 186 | resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} 187 | engines: {node: '>=12'} 188 | dev: false 189 | 190 | /lodash@4.17.21: 191 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 192 | dev: false 193 | 194 | /log-symbols@5.1.0: 195 | resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} 196 | engines: {node: '>=12'} 197 | dependencies: 198 | chalk: 5.2.0 199 | is-unicode-supported: 1.3.0 200 | dev: false 201 | 202 | /mimic-fn@2.1.0: 203 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} 204 | engines: {node: '>=6'} 205 | dev: false 206 | 207 | /mustache@4.2.0: 208 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} 209 | hasBin: true 210 | dev: false 211 | 212 | /mute-stream@0.0.8: 213 | resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} 214 | dev: false 215 | 216 | /onetime@5.1.2: 217 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} 218 | engines: {node: '>=6'} 219 | dependencies: 220 | mimic-fn: 2.1.0 221 | dev: false 222 | 223 | /ora@6.1.2: 224 | resolution: {integrity: sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==} 225 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 226 | dependencies: 227 | bl: 5.1.0 228 | chalk: 5.2.0 229 | cli-cursor: 4.0.0 230 | cli-spinners: 2.7.0 231 | is-interactive: 2.0.0 232 | is-unicode-supported: 1.3.0 233 | log-symbols: 5.1.0 234 | strip-ansi: 7.0.1 235 | wcwidth: 1.0.1 236 | dev: false 237 | 238 | /os-tmpdir@1.0.2: 239 | resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} 240 | engines: {node: '>=0.10.0'} 241 | dev: false 242 | 243 | /readable-stream@3.6.0: 244 | resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} 245 | engines: {node: '>= 6'} 246 | dependencies: 247 | inherits: 2.0.4 248 | string_decoder: 1.3.0 249 | util-deprecate: 1.0.2 250 | dev: false 251 | 252 | /restore-cursor@4.0.0: 253 | resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} 254 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 255 | dependencies: 256 | onetime: 5.1.2 257 | signal-exit: 3.0.7 258 | dev: false 259 | 260 | /run-async@2.4.1: 261 | resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} 262 | engines: {node: '>=0.12.0'} 263 | dev: false 264 | 265 | /rxjs@7.8.0: 266 | resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} 267 | dependencies: 268 | tslib: 2.4.1 269 | 270 | /safe-buffer@5.2.1: 271 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 272 | dev: false 273 | 274 | /safer-buffer@2.1.2: 275 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 276 | dev: false 277 | 278 | /signal-exit@3.0.7: 279 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 280 | dev: false 281 | 282 | /string-width@5.1.2: 283 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 284 | engines: {node: '>=12'} 285 | dependencies: 286 | eastasianwidth: 0.2.0 287 | emoji-regex: 9.2.2 288 | strip-ansi: 7.0.1 289 | dev: false 290 | 291 | /string_decoder@1.3.0: 292 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 293 | dependencies: 294 | safe-buffer: 5.2.1 295 | dev: false 296 | 297 | /strip-ansi@7.0.1: 298 | resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} 299 | engines: {node: '>=12'} 300 | dependencies: 301 | ansi-regex: 6.0.1 302 | dev: false 303 | 304 | /through@2.3.8: 305 | resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} 306 | dev: false 307 | 308 | /tmp@0.0.33: 309 | resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} 310 | engines: {node: '>=0.6.0'} 311 | dependencies: 312 | os-tmpdir: 1.0.2 313 | dev: false 314 | 315 | /tslib@2.4.1: 316 | resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} 317 | 318 | /type-fest@3.5.1: 319 | resolution: {integrity: sha512-70T99cpILFk2fzwuljwWxmazSphFrdOe3gRHbp6bqs71pxFBbJwFqnmkLO2lQL6aLHxHmYAnP/sL+AJWpT70jA==} 320 | engines: {node: '>=14.16'} 321 | dev: false 322 | 323 | /util-deprecate@1.0.2: 324 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 325 | dev: false 326 | 327 | /wcwidth@1.0.1: 328 | resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} 329 | dependencies: 330 | defaults: 1.0.4 331 | dev: false 332 | 333 | /wrap-ansi@8.0.1: 334 | resolution: {integrity: sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==} 335 | engines: {node: '>=12'} 336 | dependencies: 337 | ansi-styles: 6.2.1 338 | string-width: 5.1.2 339 | strip-ansi: 7.0.1 340 | dev: false 341 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { fileURLToPath } from "url"; 3 | 4 | import { getOutputFileName, getTpl, saveFile } from "./util.js"; 5 | 6 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 7 | 8 | const tplDir = path.join(__dirname, "template"); 9 | 10 | const cli = async () => { 11 | const output = await getTpl(tplDir); 12 | const fileName = await getOutputFileName(); 13 | saveFile(fileName, output); 14 | }; 15 | 16 | cli(); 17 | -------------------------------------------------------------------------------- /src/template/Drawer.tsx.tpl: -------------------------------------------------------------------------------- 1 | import { Drawer } from "antd"; 2 | import { useState } from 'react'; 3 | 4 | const {{{name}}}Drawer = () => { 5 | const [{{{cache}}}state, set{{{Cache}}}State] = useState([]); 6 | return <{{{name}}}Drawer>drawer; 7 | }; 8 | 9 | export default {{{name}}}Drawer; 10 | -------------------------------------------------------------------------------- /src/template/Modal.tsx.tpl: -------------------------------------------------------------------------------- 1 | import { Modal } from "antd"; 2 | 3 | const {{{name}}}Modal = () => { 4 | return <{{{name}}}Modal>modal; 5 | }; 6 | 7 | export default {{{name}}}Modal; 8 | -------------------------------------------------------------------------------- /src/template/Table.tsx.tpl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmsn/code-generator/1ff11d959c902d3b5ef834e3ce8db6c6ea73b4f5/src/template/Table.tsx.tpl -------------------------------------------------------------------------------- /src/template/constant.tsx.tpl: -------------------------------------------------------------------------------- 1 | export const columns = [{{{a:b}}}]; 2 | 3 | export const searchNode = []; 4 | -------------------------------------------------------------------------------- /src/template/test.tsx.tpl: -------------------------------------------------------------------------------- 1 | {{{name1}}} 2 | 3 | {{{Name2}}} 4 | 5 | {{{name3}}} 6 | {{{Name3}}} 7 | 8 | {{{name4:test}}} -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import chalk from "chalk"; 3 | import inquirer from "inquirer"; 4 | // TODO 替换 mustache 5 | import mustache from "mustache"; 6 | import process from "process"; 7 | 8 | const __curDir = process.cwd(); 9 | 10 | const colorSubText = (text: string) => { 11 | return chalk.dim.cyan(text); 12 | }; 13 | 14 | type NameType = { 15 | name: string; 16 | defaultVal: string; 17 | hasTwo?: boolean; 18 | }; 19 | 20 | export const editTemplate = async (names: NameType[]) => { 21 | const params = await inquirer.prompt( 22 | names.map(({ name, defaultVal, hasTwo }) => ({ 23 | type: "input", 24 | name: name, 25 | message: `Input variable ${name}:`, 26 | validate: (input) => { 27 | if (typeof input === "string" && !input.length) { 28 | return `Please input valid param value.${colorSubText( 29 | "(请输入有效参数)" 30 | )}`; 31 | } 32 | 33 | if (hasTwo && isFirstUpperCase(input)) { 34 | return `Please use lower case param.${colorSubText( 35 | "(请使用小写字母开头的参数)" 36 | )}`; 37 | } 38 | 39 | if (isFirstUpperCase(input) && !isFirstUpperCase(name)) { 40 | return `Please use lower case param.${colorSubText( 41 | "(请使用小写字母开头的参数)" 42 | )}`; 43 | } 44 | 45 | if (!isFirstUpperCase(input) && isFirstUpperCase(name)) { 46 | return `Please upper case param.${colorSubText( 47 | "(请使用大写字母开头的参数)" 48 | )}`; 49 | } 50 | 51 | return true; 52 | }, 53 | default: defaultVal ?? undefined, 54 | })) 55 | ); 56 | 57 | const namesWithVal = names.map((item) => ({ 58 | ...item, 59 | val: params[item.name], 60 | })); 61 | 62 | const result = {}; 63 | 64 | namesWithVal.forEach((item) => { 65 | result[item.name] = item.val; 66 | if (item.hasTwo) { 67 | result[toFirstUpperCase(item.name)] = toFirstUpperCase(item.val); 68 | } 69 | }); 70 | 71 | return result; 72 | }; 73 | 74 | export const getTpl = async (path: string) => { 75 | const files = fs.readdirSync(path); 76 | 77 | const { template: sourceTpl } = await inquirer.prompt([ 78 | { 79 | type: "list", 80 | name: "template", 81 | message: "Select the template of code:", 82 | choices: files.map((item) => ({ value: item, name: item })), 83 | }, 84 | ]); 85 | 86 | const tpl = fs.readFileSync(`${path}/${sourceTpl}`, "utf-8"); 87 | const slots = tpl.match(/(?<=\{\{\{)(\S+?)(?=\}\}\})/gm); 88 | 89 | // 使用 ':' 对属性增加默认值 90 | const filterSlots = [...new Set(slots)].map((item) => { 91 | const [name, defaultVal] = item.split(":"); 92 | 93 | const isFirstUpperCaseName = isFirstUpperCase(name); 94 | 95 | return { 96 | name, 97 | defaultVal, 98 | isFirstUpperCaseName, 99 | }; 100 | }); 101 | 102 | const slotsMap = new Map([]); 103 | 104 | filterSlots.forEach((item) => { 105 | if ( 106 | (isFirstUpperCase(item.name) && 107 | slotsMap.has(toFirstLowerCase(item.name))) || 108 | (!isFirstUpperCase(item.name) && 109 | slotsMap.has(toFirstUpperCase(item.name))) 110 | ) { 111 | slotsMap.delete(item.name); 112 | slotsMap.set(toFirstLowerCase(item.name), { 113 | name: toFirstLowerCase(item.name), 114 | defaultVal: item.defaultVal, 115 | hasTwo: true, 116 | }); 117 | } else { 118 | slotsMap.set(item.name, { 119 | name: item.name, 120 | defaultVal: item.defaultVal, 121 | }); 122 | } 123 | }); 124 | 125 | const validSlots = await editTemplate([...slotsMap.values()]); 126 | 127 | // TODO 当前识别大小写变量为不同变量,需整合视为同一变量,然后赋值后分别赋值为小写变量和大写开头变量(需考虑存在初始值的情况) 128 | const output = mustache.render( 129 | tpl.replace(/\:(\S+?)(?=\}\}\})/g, ""), 130 | validSlots 131 | ); 132 | return output; 133 | }; 134 | 135 | export const getOutputFileName = async () => { 136 | const { name } = await inquirer.prompt({ 137 | type: "input", 138 | name: "name", 139 | message: `Input output file name:`, 140 | validate: (input) => { 141 | return !!(typeof input === "string" && input.length); 142 | }, 143 | 144 | // TODO 默认文件名是否需要使用模版的名称 145 | default: "index.tsx", 146 | }); 147 | 148 | return name; 149 | }; 150 | 151 | export const saveFile = (filename: string, output: string) => { 152 | fs.writeFileSync(`${__curDir}/${filename}`, output); 153 | }; 154 | 155 | const isFirstUpperCase = (str: string) => { 156 | const pattern = /^[A-Z]/; 157 | return pattern.test(str); 158 | }; 159 | 160 | const toFirstUpperCase = (str: string) => { 161 | return str.charAt(0).toUpperCase() + str.slice(1); 162 | }; 163 | 164 | const toFirstLowerCase = (str: string) => { 165 | return str.charAt(0).toLowerCase() + str.slice(1); 166 | }; 167 | --------------------------------------------------------------------------------