create-banana 1.2.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +14 -0
- package/package.json +16 -5
- package/readme.md +25 -21
- package/.github/workflows/publish.yml +0 -37
- package/.husky/pre-commit +0 -4
- package/.prettierignore +0 -3
- package/.prettierrc +0 -14
- package/.vscode/settings.json +0 -10
- package/bin/index.js +0 -3
- package/eslint.config.js +0 -59
- package/src/CLI/input.js +0 -47
- package/src/CLI/main.js +0 -38
- package/src/CLI/output.js +0 -63
- package/src/core/featsManger.js +0 -16
- package/src/core/generator.js +0 -64
- package/src/features/base.js +0 -25
- package/src/features/eslint.js +0 -27
- package/src/features/pinia.js +0 -27
- package/src/features/prettier.js +0 -15
- package/src/features/vueRouter.js +0 -20
- package/template/Prettier/.prettierrc +0 -14
- package/utils/URL.js +0 -15
- package/utils/figletPrint.js +0 -19
- package/utils/pathExists.js +0 -39
- package/utils/rainbow.js +0 -31
- /package/{template → dist/template}/Eslint/eslint.config.js.ejs +0 -0
- /package/{template → dist/template}/Eslint/package.json +0 -0
- /package/{template → dist/template}/Eslint/prettierPkg.json +0 -0
- /package/{template → dist/template}/Prettier/package.json +0 -0
- /package/{template → dist/template}/base/ejs/App.vue.ejs +0 -0
- /package/{template → dist/template}/base/ejs/main.js.ejs +0 -0
- /package/{template → dist/template}/base/static/README.md +0 -0
- /package/{template → dist/template}/base/static/index.html +0 -0
- /package/{template → dist/template}/base/static/jsconfig.json +0 -0
- /package/{template → dist/template}/base/static/package.json +0 -0
- /package/{template → dist/template}/base/static/public/favicon.ico +0 -0
- /package/{template → dist/template}/base/static/src/assets/base.css +0 -0
- /package/{template → dist/template}/base/static/src/assets/logo.svg +0 -0
- /package/{template → dist/template}/base/static/src/assets/main.css +0 -0
- /package/{template → dist/template}/base/static/src/components/HelloWorld.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/TheWelcome.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/WelcomeItem.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/icons/IconCommunity.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/icons/IconDocumentation.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/icons/IconEcosystem.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/icons/IconSupport.vue +0 -0
- /package/{template → dist/template}/base/static/src/components/icons/IconTooling.vue +0 -0
- /package/{template → dist/template}/base/static/vite.config.js +0 -0
- /package/{template → dist/template}/pinia/counter.js +0 -0
- /package/{template → dist/template}/pinia/package.json +0 -0
- /package/{template → dist/template}/pinia/pinia-plugin-persistedstate/key.js +0 -0
- /package/{template → dist/template}/pinia/pinia-plugin-persistedstate/package.json +0 -0
- /package/{template → dist/template}/vue-router/ejs/AboutView.vue.ejs +0 -0
- /package/{template → dist/template}/vue-router/package.json +0 -0
- /package/{template → dist/template}/vue-router/static/components/TitleText.vue +0 -0
- /package/{template → dist/template}/vue-router/static/router/index.js +0 -0
- /package/{template → dist/template}/vue-router/static/views/HomeView.vue +0 -0
- /package/{template → dist/template}/vue-router/static/views/NotFound.vue +0 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import re from"path";import h from"fs-extra";import{select as B}from"@inquirer/prompts";import V from"chalk";var F=async(e,t)=>{try{h.pathExistsSync(t)&&(await B({message:`The target folder "${e}" is not empty. ${V.yellow("Overwrite")}?`,choices:[{name:"Yes",value:!0},{name:"No",value:!1}]})?(await h.remove(t),await h.mkdir(t)):(console.log("canceled!"),process.exit(0)))}catch(r){console.error(r),process.exit(1)}},v=F;import g from"fs-extra";import j from"path";import z from"ejs";var u=class{targetDir;pkg;fileMiddlewares;constructor(t){this.targetDir=t,this.pkg={},this.fileMiddlewares=[]}writePkg(t){this.pkg={...this.pkg,...t}}extendDepsPkg(t){this.pkg.dependencies={...this.pkg.dependencies,...t.dependencies}}extendDevDepsPkg(t){this.pkg.devDependencies={...this.pkg.devDependencies,...t.devDependencies}}extendScriptsPkg(t){this.pkg.scripts={...this.pkg.scripts,...t.scripts}}copy(t,r){this.fileMiddlewares.push(()=>{g.copySync(t,j.join(this.targetDir,r))})}render(t,r,n){this.fileMiddlewares.push(()=>{g.writeFileSync(j.join(this.targetDir,r),z.render(g.readFileSync(t,"utf-8"),n))})}async generate(){this.fileMiddlewares.forEach(t=>t()),g.writeFileSync(j.join(this.targetDir,"package.json"),JSON.stringify(this.pkg,null,2))}};import P from"chalk";import{input as Y,checkbox as U,select as q}from"@inquirer/prompts";var x=async()=>await Y({message:`Enter your ${P.yellow("project name")}:`,required:!0}),b=async()=>{let e=await U({message:`Please select the ${P.yellow("features")} to include:`,choices:[{name:"Eslint",value:"eslint"},{name:"Prettier",value:"prettier"},{name:"Pinia",value:"pinia"},{name:"Vue-Router",value:"vue-router"}]}),t=e.includes("eslint"),r=e.includes("prettier"),n=e.includes("pinia"),o=e.includes("vue-router"),i=!1;return n&&(i=await q({message:`Do you want to use ${P.yellow.bold("pinia-plugin-persistedstate")} for Pinia state persistence?`,choices:[{name:"Yes",value:!0},{name:"No",value:!1}]})),{useEslint:t,usePrettier:r,usePinia:n,useVueRouter:o,usePiniaPluginPersistedstate:i}};import H from"figlet";var K=async e=>{try{return await H.text(e,{font:"Big Money-se",horizontalLayout:"default",verticalLayout:"default",width:80,whitespaceBreak:!0})}catch(t){console.log("Something went wrong..."),console.dir(t)}},N=K;import Q from"chalk";function W(e,t,r){t/=100,r/=100;let n=a=>(a+e/30)%12,o=t*Math.min(r,1-r),i=a=>r-o*Math.max(-1,Math.min(n(a)-3,Math.min(9-n(a),1)));return[Math.round(255*i(0)),Math.round(255*i(8)),Math.round(255*i(4))]}function X(e){return e.split("").map((t,r)=>{let n=r/e.length*360,[o,i,a]=W(n,100,50);return Q.rgb(o,i,a)(t)}).join("")}var k=X;import m from"chalk";import D from"boxen";var d=console.log,f=[22,198,12],A=(e,{useEslint:t,usePrettier:r})=>{let n=m.rgb(...f)(`
|
|
3
|
+
cd ${e} && pnpm i && pnpm lint && pnpm dev
|
|
4
|
+
`),o=m.rgb(...f)(`
|
|
5
|
+
cd ${e} && pnpm i && pnpm format && pnpm dev
|
|
6
|
+
`),i=m.rgb(...f)(`
|
|
7
|
+
cd ${e} && pnpm i && pnpm dev
|
|
8
|
+
`),a=t?n:r?o:i;d(m.cyan(D(a,{title:"commands",titleAlignment:"center"})),`
|
|
9
|
+
`)},G=()=>{d(m.cyan(D(m.rgb(...f)(`
|
|
10
|
+
git init && git add . && git commit -m "Initial commit"
|
|
11
|
+
`),{title:"commands",titleAlignment:"center"})))},O=async()=>{d(k(await N("BANANA")))},S=async e=>{d(k(e))};import _ from"fs-extra";import{fileURLToPath as Z}from"url";var s=Z(new URL("../dist/template",import.meta.url));import c from"path";var T=(e,t)=>{let r=c.join(s,"base");e.writePkg(_.readJSONSync(c.join(r,"static","package.json"))),e.copy(c.join(r,"static"),""),e.render(c.join(r,"ejs","App.vue.ejs"),c.join("src","App.vue"),{...t}),e.render(c.join(r,"ejs","main.js.ejs"),c.join("src","main.js"),{...t})};import J from"fs-extra";import p from"path";var M=(e,t)=>{let{usePinia:r,usePiniaPluginPersistedstate:n}=t;if(!r)return;let o=p.join(s,"pinia");if(e.extendDepsPkg(J.readJSONSync(p.join(o,"package.json"))),e.copy(p.join(o,"counter.js"),p.join("src","stores","counter.js")),!n)return;let i=p.join(o,"pinia-plugin-persistedstate");e.extendDepsPkg(J.readJSONSync(p.join(i,"package.json"))),e.copy(p.join(i,"key.js"),p.join("src","stores","key.js"))};import L from"fs-extra";import y from"path";var C=(e,t)=>{let{useEslint:r,usePrettier:n}=t;if(!r)return;let o=y.join(s,"eslint"),i=L.readJSONSync(y.join(o,"package.json"));e.extendDevDepsPkg(i),e.extendScriptsPkg(i),e.render(y.join(o,"eslint.config.js.ejs"),"eslint.config.js",{usePrettier:n}),n&&e.extendDevDepsPkg(L.readJSONSync(y.join(o,"prettierPkg.json")))};import ee from"fs-extra";import w from"path";var E=(e,t)=>{let{usePrettier:r}=t;if(!r)return;let n=w.join(s,"prettier"),o=ee.readJSONSync(w.join(n,"package.json"));e.extendDevDepsPkg(o),e.extendScriptsPkg(o),e.copy(w.join(n,".prettierrc"),".prettierrc")};import te from"fs-extra";import l from"path";var R=(e,t)=>{let{useVueRouter:r,usePiniaPluginPersistedstate:n}=t;if(!r)return;let o=l.join(s,"vue-router");e.extendDepsPkg(te.readJSONSync(l.join(o,"package.json"))),e.copy(l.join(o,"static"),"src"),e.render(l.join(o,"ejs","AboutView.vue.ejs"),l.join("src","views","AboutView.vue"),{usePiniaPluginPersistedstate:n})};var $=async e=>{let t=await b();return T(e,t),M(e,t),C(e,t),E(e,t),R(e,t),t};var I=async()=>{await O();let e=await x(),t=re.join(process.cwd(),e);await v(e,t);let r=new u(t),n=await $(r);r.generate(),S(`
|
|
12
|
+
Project initialization complete. You may now execute the following commands:
|
|
13
|
+
`),A(e,n),S(`Initialize Git using the following command:
|
|
14
|
+
`),G()};await I();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-banana",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/TMname1/create-banana.git"
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"description": "TMname1's CLI tool to create customized templates",
|
|
10
10
|
"main": "index.js",
|
|
11
|
-
"bin": "./
|
|
11
|
+
"bin": "./dist/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
12
15
|
"imports": {
|
|
13
|
-
"#utils/*": "./utils/*",
|
|
14
16
|
"#src/*": "./src/*"
|
|
15
17
|
},
|
|
16
18
|
"lint-staged": {
|
|
@@ -37,7 +39,12 @@
|
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"@eslint/js": "^9.39.2",
|
|
39
41
|
"@eslint/json": "^0.14.0",
|
|
42
|
+
"@types/ejs": "^3.1.5",
|
|
43
|
+
"@types/fs-extra": "^11.0.4",
|
|
44
|
+
"@types/node": "^25.0.6",
|
|
45
|
+
"copyfiles": "^2.4.1",
|
|
40
46
|
"cz-conventional-changelog": "^3.3.0",
|
|
47
|
+
"esbuild": "^0.27.2",
|
|
41
48
|
"eslint": "^9.39.2",
|
|
42
49
|
"eslint-config-prettier": "^10.1.8",
|
|
43
50
|
"eslint-plugin-prettier": "^5.5.4",
|
|
@@ -45,7 +52,8 @@
|
|
|
45
52
|
"globals": "^16.5.0",
|
|
46
53
|
"husky": "^8.0.0",
|
|
47
54
|
"lint-staged": "^16.2.7",
|
|
48
|
-
"prettier": "3.7.4"
|
|
55
|
+
"prettier": "3.7.4",
|
|
56
|
+
"typescript": "^5.9.3"
|
|
49
57
|
},
|
|
50
58
|
"config": {
|
|
51
59
|
"commitizen": {
|
|
@@ -57,6 +65,9 @@
|
|
|
57
65
|
"commit": "cz",
|
|
58
66
|
"lint": "eslint . --fix --cache",
|
|
59
67
|
"format": "prettier --write --experimental-cli .",
|
|
60
|
-
"lint-staged": "lint-staged"
|
|
68
|
+
"lint-staged": "lint-staged",
|
|
69
|
+
"copy": "copyfiles \"template/**/*\" dist/",
|
|
70
|
+
"bundle": "node ./script/build.js",
|
|
71
|
+
"build": "tsc --noEmit && pnpm bundle && pnpm copy"
|
|
61
72
|
}
|
|
62
73
|
}
|
package/readme.md
CHANGED
|
@@ -10,36 +10,40 @@
|
|
|
10
10
|
|
|
11
11
|
```text
|
|
12
12
|
create-tm
|
|
13
|
-
├─
|
|
14
|
-
│ └─
|
|
13
|
+
├─ script
|
|
14
|
+
│ └─ build.js
|
|
15
15
|
├─ src
|
|
16
|
-
│ ├─
|
|
17
|
-
│ │ ├─
|
|
18
|
-
│ │ ├─
|
|
19
|
-
│ │
|
|
20
|
-
│
|
|
21
|
-
│ │ ├─
|
|
22
|
-
│ │
|
|
23
|
-
│ └─
|
|
24
|
-
│
|
|
25
|
-
│ ├─
|
|
26
|
-
│ ├─
|
|
27
|
-
│ ├─
|
|
28
|
-
│
|
|
16
|
+
│ ├─ app
|
|
17
|
+
│ │ ├─ CLI
|
|
18
|
+
│ │ │ ├─ input.ts
|
|
19
|
+
│ │ │ ├─ main.ts
|
|
20
|
+
│ │ │ └─ output.ts
|
|
21
|
+
│ │ ├─ core
|
|
22
|
+
│ │ │ ├─ featsManger.ts
|
|
23
|
+
│ │ │ └─ generator.ts
|
|
24
|
+
│ │ └─ features
|
|
25
|
+
│ │ ├─ base.ts
|
|
26
|
+
│ │ ├─ eslint.ts
|
|
27
|
+
│ │ ├─ pinia.ts
|
|
28
|
+
│ │ ├─ prettier.ts
|
|
29
|
+
│ │ └─ vueRouter.ts
|
|
30
|
+
│ ├─ bin
|
|
31
|
+
│ │ └─ index.ts
|
|
32
|
+
│ └─ utils
|
|
33
|
+
│ ├─ figletPrint.ts
|
|
34
|
+
│ ├─ pathExists.ts
|
|
35
|
+
│ ├─ rainbow.ts
|
|
36
|
+
│ └─ URL.ts
|
|
29
37
|
├─ template
|
|
30
38
|
│ ├─ base
|
|
31
39
|
│ ├─ eslint
|
|
32
40
|
│ ├─ pinia
|
|
33
41
|
│ ├─ prettier
|
|
34
42
|
│ └─ vue-router
|
|
35
|
-
├─ utils
|
|
36
|
-
│ ├─ figletPrint.js
|
|
37
|
-
│ ├─ pathExists.js
|
|
38
|
-
│ ├─ rainbow.js
|
|
39
|
-
│ └─ URL.js
|
|
40
43
|
├─ eslint.config.js
|
|
41
44
|
├─ LICENSE
|
|
42
45
|
├─ package.json
|
|
43
46
|
├─ pnpm-lock.yaml
|
|
44
|
-
|
|
47
|
+
├─ readme.md
|
|
48
|
+
└─ tsconfig.json
|
|
45
49
|
```
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
build:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
steps:
|
|
12
|
-
- name: Checkout code
|
|
13
|
-
uses: actions/checkout@v4
|
|
14
|
-
|
|
15
|
-
- name: Install pnpm
|
|
16
|
-
uses: pnpm/action-setup@v3
|
|
17
|
-
with:
|
|
18
|
-
version: 9.12.1 # 或者使用 'latest',建议固定一个主版本
|
|
19
|
-
|
|
20
|
-
- name: Setup Node.js
|
|
21
|
-
uses: actions/setup-node@v4
|
|
22
|
-
with:
|
|
23
|
-
node-version: '20'
|
|
24
|
-
registry-url: 'https://registry.npmjs.org'
|
|
25
|
-
cache: 'pnpm' # 开启缓存,加快后续构建速度
|
|
26
|
-
|
|
27
|
-
- name: Install dependencies
|
|
28
|
-
# 使用 pnpm --frozen-lockfile 代替 npm ci
|
|
29
|
-
run: pnpm install --frozen-lockfile
|
|
30
|
-
|
|
31
|
-
# - name: Build project (if needed)
|
|
32
|
-
# run: pnpm run build --if-present
|
|
33
|
-
|
|
34
|
-
- name: Publish to npm
|
|
35
|
-
run: pnpm publish --no-git-checks
|
|
36
|
-
env:
|
|
37
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.husky/pre-commit
DELETED
package/.prettierignore
DELETED
package/.prettierrc
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"printWidth": 80,
|
|
3
|
-
"tabWidth": 2,
|
|
4
|
-
"useTabs": false,
|
|
5
|
-
"semi": true,
|
|
6
|
-
"singleQuote": true,
|
|
7
|
-
"quoteProps": "as-needed",
|
|
8
|
-
"jsxSingleQuote": false,
|
|
9
|
-
"trailingComma": "es5",
|
|
10
|
-
"bracketSpacing": true,
|
|
11
|
-
"bracketSameLine": false,
|
|
12
|
-
"arrowParens": "always",
|
|
13
|
-
"endOfLine": "auto"
|
|
14
|
-
}
|
package/.vscode/settings.json
DELETED
package/bin/index.js
DELETED
package/eslint.config.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js';
|
|
2
|
-
import globals from 'globals';
|
|
3
|
-
import pluginVue from 'eslint-plugin-vue';
|
|
4
|
-
import json from '@eslint/json';
|
|
5
|
-
import { defineConfig, globalIgnores } from 'eslint/config';
|
|
6
|
-
|
|
7
|
-
import prettierPlugin from 'eslint-plugin-prettier';
|
|
8
|
-
import prettierConfig from 'eslint-config-prettier';
|
|
9
|
-
|
|
10
|
-
export default defineConfig([
|
|
11
|
-
{
|
|
12
|
-
files: ['**/*.{js,mjs,cjs,vue}'],
|
|
13
|
-
plugins: { js },
|
|
14
|
-
extends: ['js/recommended'],
|
|
15
|
-
languageOptions: { globals: globals.node },
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
files: ['**/*.vue'],
|
|
19
|
-
plugins: { vue: pluginVue },
|
|
20
|
-
extends: [pluginVue.configs['flat/essential']],
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
files: ['**/*.json'],
|
|
24
|
-
plugins: { json },
|
|
25
|
-
language: 'json/json',
|
|
26
|
-
extends: ['json/recommended'],
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
// 全局 Prettier 配置
|
|
30
|
-
{
|
|
31
|
-
plugins: { prettier: prettierPlugin },
|
|
32
|
-
extends: [prettierConfig],
|
|
33
|
-
rules: {
|
|
34
|
-
'prettier/prettier': ['warn'], // 不符合 prettier 风格时显示 warning
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
globalIgnores([
|
|
39
|
-
'node_modules/*',
|
|
40
|
-
'dist/*',
|
|
41
|
-
'build/*',
|
|
42
|
-
'out/*',
|
|
43
|
-
'.next/*',
|
|
44
|
-
'.nuxt/*',
|
|
45
|
-
'coverage/*',
|
|
46
|
-
'public/*',
|
|
47
|
-
'assets/*',
|
|
48
|
-
'.cache/*',
|
|
49
|
-
'.temp/*',
|
|
50
|
-
'.tmp/*',
|
|
51
|
-
'*.min.js',
|
|
52
|
-
'*.bundle.js',
|
|
53
|
-
'package-lock.json',
|
|
54
|
-
'yarn.lock',
|
|
55
|
-
'pnpm-lock.yaml',
|
|
56
|
-
'.env*',
|
|
57
|
-
'docs/.vitepress/dist/*',
|
|
58
|
-
]),
|
|
59
|
-
]);
|
package/src/CLI/input.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { input, checkbox, select } from '@inquirer/prompts';
|
|
3
|
-
|
|
4
|
-
const inputProjectName = async () => {
|
|
5
|
-
return await input({
|
|
6
|
-
message: `Enter your ${chalk.yellow('project name')}:`,
|
|
7
|
-
required: true,
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const featsSelect = async () => {
|
|
12
|
-
const feats = await checkbox({
|
|
13
|
-
message: `Please select the ${chalk.yellow('features')} to include:`,
|
|
14
|
-
choices: [
|
|
15
|
-
{ name: 'Eslint', value: 'eslint' },
|
|
16
|
-
{ name: 'Prettier', value: 'prettier' },
|
|
17
|
-
{ name: 'Pinia', value: 'pinia' },
|
|
18
|
-
{ name: 'Vue-Router', value: 'vue-router' },
|
|
19
|
-
],
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const useEslint = feats.includes('eslint');
|
|
23
|
-
const usePrettier = feats.includes('prettier');
|
|
24
|
-
const usePinia = feats.includes('pinia');
|
|
25
|
-
const useVueRouter = feats.includes('vue-router');
|
|
26
|
-
|
|
27
|
-
let usePiniaPluginPersistedstate = false;
|
|
28
|
-
if (usePinia) {
|
|
29
|
-
usePiniaPluginPersistedstate = await select({
|
|
30
|
-
message: `Do you want to use ${chalk.yellow.bold('pinia-plugin-persistedstate')} for Pinia state persistence?`,
|
|
31
|
-
choices: [
|
|
32
|
-
{ name: 'Yes', value: true },
|
|
33
|
-
{ name: 'No', value: false },
|
|
34
|
-
],
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
useEslint,
|
|
40
|
-
usePrettier,
|
|
41
|
-
usePinia,
|
|
42
|
-
useVueRouter,
|
|
43
|
-
usePiniaPluginPersistedstate,
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export { inputProjectName, featsSelect };
|
package/src/CLI/main.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import confirmPathExists from '#utils/pathExists.js';
|
|
3
|
-
import Generator from '../core/generator.js';
|
|
4
|
-
import { inputProjectName } from './input.js';
|
|
5
|
-
import {
|
|
6
|
-
outPkgCommand,
|
|
7
|
-
outGitCommand,
|
|
8
|
-
PrintBANANA,
|
|
9
|
-
rainbowPrint,
|
|
10
|
-
} from './output.js';
|
|
11
|
-
import featsManager from '../core/featsManger.js';
|
|
12
|
-
|
|
13
|
-
export default async () => {
|
|
14
|
-
await PrintBANANA();
|
|
15
|
-
|
|
16
|
-
const projectName = await inputProjectName();
|
|
17
|
-
const targetDir = path.join(process.cwd(), projectName);
|
|
18
|
-
// 确认路径存在,存在就询问是否覆盖
|
|
19
|
-
await confirmPathExists(projectName, targetDir);
|
|
20
|
-
|
|
21
|
-
// 创建文件生成器,根据选择功能生成模板
|
|
22
|
-
const files = new Generator(targetDir);
|
|
23
|
-
const featsList = await featsManager(files);
|
|
24
|
-
files.generate();
|
|
25
|
-
|
|
26
|
-
// TODO: 自动化流程
|
|
27
|
-
/** 自动化流程: 目前只生成了文件,让用户手动安装依赖。
|
|
28
|
-
建议: 在生成结束后,询问用户 "是否立即安装依赖?" 和 "是否初始化 Git 仓库?"。
|
|
29
|
-
实现: 使用 execa 或 cross-spawn 自动执行 install 和 git init 命令。
|
|
30
|
-
*/
|
|
31
|
-
rainbowPrint(
|
|
32
|
-
'\nProject initialization complete. You may now execute the following commands:\n'
|
|
33
|
-
);
|
|
34
|
-
outPkgCommand(projectName, featsList);
|
|
35
|
-
|
|
36
|
-
rainbowPrint('Initialize Git using the following command:\n');
|
|
37
|
-
outGitCommand();
|
|
38
|
-
};
|
package/src/CLI/output.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import printString from '#utils/figletPrint.js';
|
|
2
|
-
import rainbowGradient from '#utils/rainbow.js';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import boxen from 'boxen';
|
|
5
|
-
|
|
6
|
-
const log = console.log;
|
|
7
|
-
// 参考create-vue的颜色
|
|
8
|
-
const greenColor = [22, 198, 12];
|
|
9
|
-
|
|
10
|
-
const outPkgCommand = (projectName, { useEslint, usePrettier }) => {
|
|
11
|
-
const eslintStr = chalk.rgb(...greenColor)(
|
|
12
|
-
`\n cd ${projectName} && pnpm i && pnpm lint && pnpm dev \n`
|
|
13
|
-
);
|
|
14
|
-
const prettierStr = chalk.rgb(...greenColor)(
|
|
15
|
-
`\n cd ${projectName} && pnpm i && pnpm format && pnpm dev \n`
|
|
16
|
-
);
|
|
17
|
-
const noFormatStr = chalk.rgb(...greenColor)(
|
|
18
|
-
`\n cd ${projectName} && pnpm i && pnpm dev \n`
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
const outStr = useEslint
|
|
22
|
-
? eslintStr
|
|
23
|
-
: usePrettier
|
|
24
|
-
? prettierStr
|
|
25
|
-
: noFormatStr;
|
|
26
|
-
|
|
27
|
-
log(
|
|
28
|
-
chalk.cyan(
|
|
29
|
-
boxen(outStr, {
|
|
30
|
-
title: 'commands',
|
|
31
|
-
titleAlignment: 'center',
|
|
32
|
-
})
|
|
33
|
-
),
|
|
34
|
-
'\n'
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const outGitCommand = () => {
|
|
39
|
-
// TODO: 以后有commitizen再改这里
|
|
40
|
-
log(
|
|
41
|
-
chalk.cyan(
|
|
42
|
-
boxen(
|
|
43
|
-
chalk.rgb(...greenColor)(
|
|
44
|
-
'\n git init && git add . && git commit -m "Initial commit" \n'
|
|
45
|
-
),
|
|
46
|
-
{
|
|
47
|
-
title: 'commands',
|
|
48
|
-
titleAlignment: 'center',
|
|
49
|
-
}
|
|
50
|
-
)
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const PrintBANANA = async () => {
|
|
56
|
-
log(rainbowGradient(await printString('BANANA')));
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const rainbowPrint = async (str) => {
|
|
60
|
-
log(rainbowGradient(str));
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export { outPkgCommand, outGitCommand, PrintBANANA, rainbowPrint };
|
package/src/core/featsManger.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import base from '#src/features/base.js';
|
|
2
|
-
import pinia from '#src/features/pinia.js';
|
|
3
|
-
import eslint from '#src/features/eslint.js';
|
|
4
|
-
import prettier from '#src/features/prettier.js';
|
|
5
|
-
import vueRouter from '#src/features/vueRouter.js';
|
|
6
|
-
import { featsSelect } from '#src/CLI/input.js';
|
|
7
|
-
|
|
8
|
-
export default async (files) => {
|
|
9
|
-
const featsList = await featsSelect();
|
|
10
|
-
base(files, featsList);
|
|
11
|
-
pinia(files, featsList);
|
|
12
|
-
eslint(files, featsList);
|
|
13
|
-
prettier(files, featsList);
|
|
14
|
-
vueRouter(files, featsList);
|
|
15
|
-
return featsList;
|
|
16
|
-
};
|
package/src/core/generator.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import ejs from 'ejs';
|
|
4
|
-
|
|
5
|
-
export default class Generator {
|
|
6
|
-
constructor(targetDir) {
|
|
7
|
-
this.targetDir = targetDir;
|
|
8
|
-
this.pkg = {};
|
|
9
|
-
this.fileMiddlewares = [];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// package.json 方法
|
|
13
|
-
writePkg(pkg) {
|
|
14
|
-
this.pkg = { ...this.pkg, ...pkg };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
extendDepsPkg(deps) {
|
|
18
|
-
this.pkg.dependencies = { ...this.pkg.dependencies, ...deps.dependencies };
|
|
19
|
-
}
|
|
20
|
-
extendDevDepsPkg(devDeps) {
|
|
21
|
-
this.pkg.devDependencies = {
|
|
22
|
-
...this.pkg.devDependencies,
|
|
23
|
-
...devDeps.devDependencies,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
extendScriptsPkg(scripts) {
|
|
27
|
-
this.pkg.scripts = { ...this.pkg.scripts, ...scripts.scripts };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* 复制文件(夹)
|
|
32
|
-
* @param {string} source - 源文件路径
|
|
33
|
-
* @param {string} target - 目标文件路径
|
|
34
|
-
*/
|
|
35
|
-
copy(source, target) {
|
|
36
|
-
this.fileMiddlewares.push(() => {
|
|
37
|
-
fs.copySync(source, path.join(this.targetDir, target));
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 处理ejs模板文件
|
|
43
|
-
* @param {string} source - 源文件路径
|
|
44
|
-
* @param {string} target - 目标文件路径
|
|
45
|
-
* @param {object} feats - 模板数据
|
|
46
|
-
*/
|
|
47
|
-
render(source, target, feats) {
|
|
48
|
-
this.fileMiddlewares.push(() => {
|
|
49
|
-
fs.writeFileSync(
|
|
50
|
-
path.join(this.targetDir, target),
|
|
51
|
-
ejs.render(fs.readFileSync(source, 'utf-8'), feats)
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 最后调用,执行所有写入
|
|
57
|
-
async generate() {
|
|
58
|
-
this.fileMiddlewares.forEach((fileFunction) => fileFunction());
|
|
59
|
-
fs.writeFileSync(
|
|
60
|
-
path.join(this.targetDir, 'package.json'),
|
|
61
|
-
JSON.stringify(this.pkg, null, 2)
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
}
|
package/src/features/base.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { templatePath } from '#utils/URL.js';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
export default (files, feats) => {
|
|
6
|
-
const basePath = path.join(templatePath, 'base');
|
|
7
|
-
files.writePkg(
|
|
8
|
-
fs.readJSONSync(path.join(basePath, 'static', 'package.json'))
|
|
9
|
-
);
|
|
10
|
-
files.copy(path.join(basePath, 'static'), '');
|
|
11
|
-
files.render(
|
|
12
|
-
path.join(basePath, 'ejs', 'App.vue.ejs'),
|
|
13
|
-
path.join('src', 'App.vue'),
|
|
14
|
-
{
|
|
15
|
-
...feats,
|
|
16
|
-
}
|
|
17
|
-
);
|
|
18
|
-
files.render(
|
|
19
|
-
path.join(basePath, 'ejs', 'main.js.ejs'),
|
|
20
|
-
path.join('src', 'main.js'),
|
|
21
|
-
{
|
|
22
|
-
...feats,
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
};
|
package/src/features/eslint.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { templatePath } from '#utils/URL.js';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
export default (files, { useEslint, usePrettier }) => {
|
|
6
|
-
if (!useEslint) return;
|
|
7
|
-
|
|
8
|
-
const eslintPath = path.join(templatePath, 'eslint');
|
|
9
|
-
|
|
10
|
-
const pkg = fs.readJSONSync(path.join(eslintPath, 'package.json'));
|
|
11
|
-
files.extendDevDepsPkg(pkg);
|
|
12
|
-
files.extendScriptsPkg(pkg);
|
|
13
|
-
|
|
14
|
-
files.render(
|
|
15
|
-
path.join(eslintPath, 'eslint.config.js.ejs'),
|
|
16
|
-
'eslint.config.js',
|
|
17
|
-
{
|
|
18
|
-
usePrettier,
|
|
19
|
-
}
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
if (!usePrettier) return;
|
|
23
|
-
|
|
24
|
-
files.extendDevDepsPkg(
|
|
25
|
-
fs.readJSONSync(path.join(eslintPath, 'prettierPkg.json'))
|
|
26
|
-
);
|
|
27
|
-
};
|
package/src/features/pinia.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { templatePath } from '#utils/URL.js';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
export default (files, { usePinia, usePiniaPluginPersistedstate }) => {
|
|
6
|
-
if (!usePinia) return;
|
|
7
|
-
|
|
8
|
-
const piniaPath = path.join(templatePath, 'pinia');
|
|
9
|
-
|
|
10
|
-
files.extendDepsPkg(fs.readJSONSync(path.join(piniaPath, 'package.json')));
|
|
11
|
-
|
|
12
|
-
files.copy(
|
|
13
|
-
path.join(piniaPath, 'counter.js'),
|
|
14
|
-
path.join('src', 'stores', 'counter.js')
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
if (!usePiniaPluginPersistedstate) return;
|
|
18
|
-
|
|
19
|
-
const persistPath = path.join(piniaPath, 'pinia-plugin-persistedstate');
|
|
20
|
-
|
|
21
|
-
files.extendDepsPkg(fs.readJSONSync(path.join(persistPath, 'package.json')));
|
|
22
|
-
|
|
23
|
-
files.copy(
|
|
24
|
-
path.join(persistPath, 'key.js'),
|
|
25
|
-
path.join('src', 'stores', 'key.js')
|
|
26
|
-
);
|
|
27
|
-
};
|
package/src/features/prettier.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { templatePath } from '#utils/URL.js';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
export default (files, { usePrettier }) => {
|
|
6
|
-
if (!usePrettier) return;
|
|
7
|
-
|
|
8
|
-
const prettierPath = path.join(templatePath, 'prettier');
|
|
9
|
-
const pkg = fs.readJSONSync(path.join(prettierPath, 'package.json'));
|
|
10
|
-
|
|
11
|
-
files.extendDevDepsPkg(pkg);
|
|
12
|
-
files.extendScriptsPkg(pkg);
|
|
13
|
-
|
|
14
|
-
files.copy(path.join(prettierPath, '.prettierrc'), '.prettierrc');
|
|
15
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { templatePath } from '#utils/URL.js';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
export default (files, { useVueRouter, usePiniaPluginPersistedstate }) => {
|
|
6
|
-
if (!useVueRouter) return;
|
|
7
|
-
const vueRouterPath = path.join(templatePath, 'vue-router');
|
|
8
|
-
|
|
9
|
-
files.extendDepsPkg(
|
|
10
|
-
fs.readJSONSync(path.join(vueRouterPath, 'package.json'))
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
files.copy(path.join(vueRouterPath, 'static'), 'src');
|
|
14
|
-
|
|
15
|
-
files.render(
|
|
16
|
-
path.join(vueRouterPath, 'ejs', 'AboutView.vue.ejs'),
|
|
17
|
-
path.join('src', 'views', 'AboutView.vue'),
|
|
18
|
-
{ usePiniaPluginPersistedstate }
|
|
19
|
-
);
|
|
20
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"printWidth": 80,
|
|
3
|
-
"tabWidth": 2,
|
|
4
|
-
"useTabs": false,
|
|
5
|
-
"semi": true,
|
|
6
|
-
"singleQuote": true,
|
|
7
|
-
"quoteProps": "as-needed",
|
|
8
|
-
"jsxSingleQuote": false,
|
|
9
|
-
"trailingComma": "es5",
|
|
10
|
-
"bracketSpacing": true,
|
|
11
|
-
"bracketSameLine": false,
|
|
12
|
-
"arrowParens": "always",
|
|
13
|
-
"endOfLine": "auto"
|
|
14
|
-
}
|
package/utils/URL.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// 获得相对路径和模板目录路径的工具函数
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
|
|
5
|
-
// 拼接相对路径
|
|
6
|
-
export const relativePath = (fileURL, targetURL) => {
|
|
7
|
-
const __filename = fileURLToPath(fileURL);
|
|
8
|
-
const __dirname = path.dirname(__filename);
|
|
9
|
-
return path.join(__dirname, targetURL);
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// 获取模板目录路径
|
|
13
|
-
export const templatePath = fileURLToPath(
|
|
14
|
-
new URL('../template', import.meta.url)
|
|
15
|
-
);
|
package/utils/figletPrint.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// print BANANA in big money-se font using figlet
|
|
2
|
-
import figlet from 'figlet';
|
|
3
|
-
|
|
4
|
-
const printString = async (str) => {
|
|
5
|
-
try {
|
|
6
|
-
return await figlet.text(str, {
|
|
7
|
-
font: 'Big Money-se',
|
|
8
|
-
horizontalLayout: 'default',
|
|
9
|
-
verticalLayout: 'default',
|
|
10
|
-
width: 80,
|
|
11
|
-
whitespaceBreak: true,
|
|
12
|
-
});
|
|
13
|
-
} catch (err) {
|
|
14
|
-
console.log('Something went wrong...');
|
|
15
|
-
console.dir(err);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default printString;
|
package/utils/pathExists.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// 确认路径是否存在,若存在则提示是否覆盖
|
|
2
|
-
// 若选择覆盖则删除已存在的文件夹,并新建一个文件夹
|
|
3
|
-
// 若选择不覆盖则退出程序
|
|
4
|
-
import fs from 'fs-extra';
|
|
5
|
-
import { select } from '@inquirer/prompts';
|
|
6
|
-
import chalk from 'chalk';
|
|
7
|
-
|
|
8
|
-
const confirmPathExists = async (projectName, projectDir) => {
|
|
9
|
-
try {
|
|
10
|
-
// 判断文件夹是否存在
|
|
11
|
-
if (fs.pathExistsSync(projectDir)) {
|
|
12
|
-
// 如果存在就提示是否要覆盖
|
|
13
|
-
const isOverwrite = await select({
|
|
14
|
-
message: `The target folder "${projectName}" is not empty. ${chalk.yellow('Overwrite')}?`,
|
|
15
|
-
choices: [
|
|
16
|
-
{ name: 'Yes', value: true },
|
|
17
|
-
{ name: 'No', value: false },
|
|
18
|
-
],
|
|
19
|
-
});
|
|
20
|
-
if (!isOverwrite) {
|
|
21
|
-
// TODO: 放一个更友好的提示
|
|
22
|
-
// 例如:X操作取消(换英文)
|
|
23
|
-
console.log('canceled!');
|
|
24
|
-
// 退出程序
|
|
25
|
-
process.exit(0);
|
|
26
|
-
} else {
|
|
27
|
-
// 删除已存在的文件夹并新建一个文件夹
|
|
28
|
-
await fs.remove(projectDir);
|
|
29
|
-
await fs.mkdir(projectDir);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
} catch (err) {
|
|
33
|
-
// TODO: 放一个更友好的提示
|
|
34
|
-
console.error(err);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export default confirmPathExists;
|
package/utils/rainbow.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// use chalk to print text in rainbow colors
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
|
|
4
|
-
function hslToRgb(h, s, l) {
|
|
5
|
-
s /= 100;
|
|
6
|
-
l /= 100;
|
|
7
|
-
|
|
8
|
-
const k = (n) => (n + h / 30) % 12;
|
|
9
|
-
const a = s * Math.min(l, 1 - l);
|
|
10
|
-
const f = (n) =>
|
|
11
|
-
l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
12
|
-
|
|
13
|
-
return [
|
|
14
|
-
Math.round(255 * f(0)),
|
|
15
|
-
Math.round(255 * f(8)),
|
|
16
|
-
Math.round(255 * f(4)),
|
|
17
|
-
];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function rainbowGradient(text) {
|
|
21
|
-
return text
|
|
22
|
-
.split('')
|
|
23
|
-
.map((char, i) => {
|
|
24
|
-
const hue = (i / text.length) * 360;
|
|
25
|
-
const [r, g, b] = hslToRgb(hue, 100, 50);
|
|
26
|
-
return chalk.rgb(r, g, b)(char);
|
|
27
|
-
})
|
|
28
|
-
.join('');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export default rainbowGradient;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|