@jackie_qian/create-vue-app 1.0.4 → 1.0.5

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/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # @jackie_qian/create-vue-app
2
+
3
+ 自定义 Vue3 模板生成器。
4
+
5
+ ## 快速开始
6
+
7
+ ### 方式 1:pnpm create(推荐)
8
+
9
+ ```bash
10
+ pnpm create @jackie_qian/vue-app@latest <my-app-name>
11
+ cd my-app
12
+ pnpm install
13
+ pnpm dev
14
+ ```
15
+
16
+ ### 方式 2:npx
17
+
18
+ ```bash
19
+ npx @jackie_qian/create-vue-app@latest <my-app-name>
20
+ ```
21
+
22
+ ### 方式 3:全局安装
23
+
24
+ ```bash
25
+ npm i -g @jackie_qian/create-vue-app
26
+ create-vue-app <my-app-name>
27
+ ```
28
+
29
+ ## 参数
30
+
31
+ - `--defaults`:跳过交互,使用默认选项
32
+ - `--js`:仅配合 `--defaults` 使用,生成 JS 项目(默认生成 TS)
33
+
34
+ 示例:
35
+
36
+ ```bash
37
+ pnpm create @jackie_qian/vue-app@latest --defaults my-app
38
+ pnpm create @jackie_qian/vue-app@latest --defaults --js my-app
39
+ ```
40
+
41
+ ## 说明
42
+
43
+ - 该脚手架会先调用 `create-vue@latest` 生成基础项目,然后按选择的功能进行二次改造。
44
+ - 如果遇到网络或 registry 问题,建议临时指定官方源:
45
+
46
+ ```bash
47
+ pnpm create @jackie_qian/vue-app@latest --registry=https://registry.npmjs.org/ my-app
48
+ ```
package/dist/cli.js CHANGED
@@ -139,7 +139,6 @@ export async function main() {
139
139
  if (features.has("router")) features.add("pages");
140
140
  features.add("autoImport");
141
141
  features.add("components");
142
- features.add("unocss");
143
142
  packageManager = await select({
144
143
  message:
145
144
  "Which package manager will you use? (Vue 3.6 beta requires version overrides that differ per package manager)",
@@ -181,6 +180,8 @@ export async function main() {
181
180
  path.join(targetDir, ".vscode/extensions.json"),
182
181
  renderVsCodeExtensions(language, features),
183
182
  );
183
+ await writeEslintConfig(targetDir, language, features);
184
+ await writeStylelintConfig(targetDir, features);
184
185
  if (installDeps) {
185
186
  const s2 = spinner();
186
187
  s2.start("安装依赖");
@@ -329,7 +330,7 @@ export async function main() {
329
330
  });
330
331
  await writeTextFile(mainPath, patched);
331
332
  }
332
- await writeEslintConfig(targetDir, features);
333
+ await writeEslintConfig(targetDir, language, features);
333
334
  await writeStylelintConfig(targetDir, features);
334
335
  if (installDeps) {
335
336
  const s2 = spinner();
package/dist/scaffold.js CHANGED
@@ -11,10 +11,13 @@ import {
11
11
  } from "./utils/util.js";
12
12
  import {
13
13
  renderEnv,
14
+ renderEslintAutoImportGlobalsJson,
15
+ renderEslintConfig,
14
16
  renderJsConfig,
15
17
  renderMainJs,
16
18
  renderRouter,
17
19
  renderStore,
20
+ renderStylelintConfig,
18
21
  renderViteConfig,
19
22
  } from "./templates/index.js";
20
23
  export function getExampleTemplateDir() {
@@ -258,95 +261,26 @@ export async function applyExampleTemplateJs(targetDir, projectName, features) {
258
261
  if (!features.has("sassEmbedded"))
259
262
  await removePath(path.join(targetDir, "src/assets/styles"));
260
263
  }
261
- export async function writeEslintConfig(targetDir, features) {
264
+ export async function writeEslintConfig(targetDir, language, features) {
262
265
  if (!features.has("eslintAntfu")) return;
263
- const withAutoImportGlobals = features.has("autoImport");
264
- const autoImportLine = withAutoImportGlobals
265
- ? `import autoImportGlobals from './.eslintrc-auto-import.json' with { type: 'json' }\n\n`
266
- : "";
267
- const autoImportConfig = withAutoImportGlobals
268
- ? `,
269
- {
270
- languageOptions: {
271
- globals: autoImportGlobals.globals
272
- }
273
- }`
274
- : "";
266
+ if (
267
+ language === "js" &&
268
+ (features.has("vant") || features.has("elementPlus"))
269
+ )
270
+ await writeFileEnsureDir(
271
+ path.join(targetDir, ".eslintrc-auto-import.json"),
272
+ renderEslintAutoImportGlobalsJson(),
273
+ );
275
274
  await writeFileEnsureDir(
276
275
  path.join(targetDir, "eslint.config.js"),
277
- `import antfu from '@antfu/eslint-config'
278
- ${autoImportLine}export default antfu(
279
- {
280
- type: 'app',
281
- ignores: [
282
- 'public',
283
- 'dist',
284
- 'node_modules'
285
- ]
286
- }${autoImportConfig}
287
- )
288
- `,
276
+ renderEslintConfig(language, features),
289
277
  );
290
278
  }
291
279
  export async function writeStylelintConfig(targetDir, features) {
292
280
  if (!features.has("stylelint")) return;
293
281
  await writeFileEnsureDir(
294
282
  path.join(targetDir, "stylelint.config.js"),
295
- `export default {
296
- extends: [
297
- 'stylelint-config-standard-scss',
298
- 'stylelint-config-standard-vue/scss',
299
- 'stylelint-config-recess-order',
300
- '@stylistic/stylelint-config'
301
- ],
302
- plugins: [
303
- 'stylelint-scss'
304
- ],
305
- rules: {
306
- 'at-rule-no-unknown': null,
307
- 'no-descending-specificity': null,
308
- 'property-no-unknown': null,
309
- 'font-family-no-missing-generic-family-keyword': null,
310
- 'selector-class-pattern': null,
311
- 'function-no-unknown': [
312
- true,
313
- {
314
- ignoreFunctions: [
315
- 'v-bind',
316
- 'map-get',
317
- 'lighten',
318
- 'darken'
319
- ]
320
- }
321
- ],
322
- 'selector-pseudo-element-no-unknown': [
323
- true,
324
- {
325
- ignorePseudoElements: [
326
- '/^view-transition/'
327
- ]
328
- }
329
- ],
330
- 'scss/double-slash-comment-empty-line-before': null,
331
- 'scss/no-global-function-names': null,
332
- '@stylistic/max-line-length': null,
333
- '@stylistic/block-closing-brace-newline-after': [
334
- 'always',
335
- {
336
- ignoreAtRules: [
337
- 'if',
338
- 'else'
339
- ]
340
- }
341
- ]
342
- },
343
- allowEmptyInput: true,
344
- ignoreFiles: [
345
- 'node_modules/**/*',
346
- 'dist*/**/*'
347
- ]
348
- }
349
- `,
283
+ renderStylelintConfig(),
350
284
  );
351
285
  }
352
286
  export async function patchMainFile(mainPath, patched) {
@@ -3,11 +3,16 @@ export { renderAppWithRouter } from "./renderAppWithRouter.js";
3
3
  export { renderEditorConfig } from "./renderEditorConfig.js";
4
4
  export { renderEnv } from "./renderEnv.js";
5
5
  export { renderHomeView } from "./renderHomeView.js";
6
+ export {
7
+ renderEslintAutoImportGlobalsJson,
8
+ renderEslintConfig,
9
+ } from "./renderEslintConfig.js";
6
10
  export { renderJsConfig } from "./renderJsConfig.js";
7
11
  export { renderMainJs } from "./renderMainJs.js";
8
12
  export { renderPagesIndex } from "./renderPagesIndex.js";
9
13
  export { renderRouter } from "./renderRouter.js";
10
14
  export { renderStore } from "./renderStore.js";
15
+ export { renderStylelintConfig } from "./renderStylelintConfig.js";
11
16
  export { renderUnoConfig } from "./renderUnoConfig.js";
12
17
  export {
13
18
  renderVsCodeExtensions,
@@ -0,0 +1,174 @@
1
+ export function renderEslintAutoImportGlobalsJson() {
2
+ return `{
3
+ "globals": {}
4
+ }
5
+ `;
6
+ }
7
+ export function shouldRenderEslintAutoImportGlobals(language, features) {
8
+ return (
9
+ language === "js" && (features.has("vant") || features.has("elementPlus"))
10
+ );
11
+ }
12
+ export function renderEslintConfig(language, features) {
13
+ const withAutoImportGlobals = shouldRenderEslintAutoImportGlobals(
14
+ language,
15
+ features,
16
+ );
17
+ const autoImportLine = withAutoImportGlobals
18
+ ? `import autoImportGlobals from './.eslintrc-auto-import.json' with { type: 'json' }\n\n`
19
+ : "\n";
20
+ const unocssLine = features.has("unocss") ? ` unocss: true,\n` : "";
21
+ const autoImportConfig = withAutoImportGlobals
22
+ ? ` {
23
+ languageOptions: {
24
+ globals: autoImportGlobals.globals
25
+ }
26
+ },
27
+ `
28
+ : "";
29
+ return `import antfu from '@antfu/eslint-config'
30
+ ${autoImportLine}export default antfu(
31
+ {
32
+ ${unocssLine} type: 'app',
33
+ ignores: [
34
+ 'public',
35
+ 'dist',
36
+ 'node_modules'
37
+ ]
38
+ },
39
+ ${autoImportConfig} {
40
+ rules: {
41
+ // 强制数组方法的回调函数中有 return 语句
42
+ 'array-callback-return': 2,
43
+ // 强制在数组括号内使用一致的空格
44
+ 'style/array-bracket-spacing': 0,
45
+ // 要求箭头函数的参数使用圆括号。'as-needed' 表示只有在必要时才使用圆括号
46
+ 'style/arrow-parens': ['off', 'as-needed'],
47
+ // 要求箭头函数的箭头前后有空格
48
+ 'style/arrow-spacing': [
49
+ 'error',
50
+ {
51
+ before: true,
52
+ after: true
53
+ }
54
+ ],
55
+ // 强制在代码块中开括号前和闭括号后有空格
56
+ 'style/block-spacing': ['error', 'always'],
57
+ // 强制在代码块中使用一致的大括号风格
58
+ 'style/brace-style': ['error', '1tbs'],
59
+ // 禁止使用尾随逗号
60
+ 'style/comma-dangle': [
61
+ 'error',
62
+ {
63
+ arrays: 'never',
64
+ objects: 'never',
65
+ imports: 'never',
66
+ exports: 'never',
67
+ functions: 'never'
68
+ }
69
+ ],
70
+ // 强制在逗号前后使用一致的空格
71
+ 'style/comma-spacing': [
72
+ 'error',
73
+ {
74
+ before: false,
75
+ after: true
76
+ }
77
+ ],
78
+ // 禁止在计算的属性的方括号内使用空格
79
+ 'style/computed-property-spacing': ['error', 'never'],
80
+ // 禁止在箭头函数体之前出现换行
81
+ 'style/implicit-arrow-linebreak': ['error', 'beside'],
82
+ // 强制在对象字面量的属性中键和值之间使用一致的间距
83
+ 'style/key-spacing': [
84
+ 'error',
85
+ {
86
+ beforeColon: false,
87
+ afterColon: true
88
+ }
89
+ ],
90
+ // 强制在关键字前后使用一致的空格
91
+ 'style/keyword-spacing': [
92
+ 'error',
93
+ {
94
+ before: true,
95
+ after: true
96
+ }
97
+ ],
98
+ // 未声明的变量会被警告
99
+ 'style/no-undef': 0,
100
+ // 强制使用一致的换行风格
101
+ 'style/linebreak-style': 0,
102
+ // 禁用稀疏数组
103
+ 'style/no-sparse-arrays': 0,
104
+ // 禁止数字字面量中使用前导和尾随小数点
105
+ 'style/no-floating-decimal': 'error',
106
+ // 禁止使用多个空格
107
+ 'style/no-multi-spaces': 'error',
108
+ // 禁止空格和 tab 的混合缩进
109
+ 'style/no-mixed-spaces-and-tabs': 0,
110
+ // 禁止出现多行空行
111
+ 'style/no-multiple-empty-lines': [
112
+ 'warn',
113
+ {
114
+ max: 2,
115
+ maxEOF: 0
116
+ }
117
+ ],
118
+ // 强制在大括号中使用一致的空格
119
+ 'style/object-curly-spacing': ['error', 'always'],
120
+ // 强制操作符周围有换行符
121
+ 'style/operator-linebreak': ['error', 'after'],
122
+ // 要求对象字面量属性名称使用引号,只在需要的时候
123
+ 'style/quote-props': ['error', 'as-needed'],
124
+ // 强制使用单引号
125
+ 'style/quotes': ['error', 'single'],
126
+ // 禁止使用分号
127
+ 'style/semi': ['error', 'never'],
128
+ // 强制在代码块前有空格
129
+ 'style/space-before-blocks': ['error', 'always'],
130
+ // 要求操作符周围有空格
131
+ 'style/space-infix-ops': 'error',
132
+ // 强制在 switch 的冒号左右有空格
133
+ 'style/switch-colon-spacing': [
134
+ 'error',
135
+ {
136
+ before: false,
137
+ after: true
138
+ }
139
+ ],
140
+ // 禁止直接使用 new
141
+ 'no-new': 0,
142
+ // 禁止使用 var
143
+ 'no-var': 2,
144
+ // 禁止存在debugger
145
+ 'no-debugger': 1,
146
+ // 禁止存在console
147
+ 'no-console': 1,
148
+ // 是否禁止存在无法到达的代码
149
+ 'no-unreachable': 1,
150
+ // 禁止未使用过的变量
151
+ 'no-unused-vars': 1,
152
+ // 要求模板字符串中花括号内有空格
153
+ 'style/template-curly-spacing': ['error', 'always']
154
+ }
155
+ },
156
+ {
157
+ files: ['src/**/*.vue'],
158
+ rules: {
159
+ // 强制 .vue 文件中的顺序
160
+ 'vue/block-order': [
161
+ 'error',
162
+ {
163
+ order: ['route', 'template', 'script', 'style']
164
+ }
165
+ ],
166
+ // 是否可以直接修改prop
167
+ 'vue/no-mutating-props': 0,
168
+ // 强制组件名称为多个单词
169
+ 'vue/multi-word-component-names': 0
170
+ }
171
+ }
172
+ )
173
+ `;
174
+ }
@@ -0,0 +1,54 @@
1
+ export function renderStylelintConfig() {
2
+ return `export default {
3
+ extends: [
4
+ 'stylelint-config-standard-scss',
5
+ 'stylelint-config-standard-vue/scss',
6
+ 'stylelint-config-recess-order',
7
+ '@stylistic/stylelint-config'
8
+ ],
9
+ plugins: [
10
+ 'stylelint-scss'
11
+ ],
12
+ rules: {
13
+ 'at-rule-no-unknown': null,
14
+ 'no-descending-specificity': null,
15
+ 'property-no-unknown': null,
16
+ 'font-family-no-missing-generic-family-keyword': null,
17
+ 'selector-class-pattern': null,
18
+ 'function-no-unknown': [
19
+ true,
20
+ {
21
+ ignoreFunctions: [
22
+ 'v-bind',
23
+ 'map-get',
24
+ 'lighten',
25
+ 'darken'
26
+ ]
27
+ }
28
+ ],
29
+ 'selector-pseudo-element-no-unknown': [
30
+ true,
31
+ {
32
+ ignorePseudoElements: [
33
+ '/^view-transition/'
34
+ ]
35
+ }
36
+ ],
37
+ 'scss/double-slash-comment-empty-line-before': null,
38
+ 'scss/no-global-function-names': null,
39
+ '@stylistic/max-line-length': null,
40
+ '@stylistic/block-closing-brace-newline-after': [
41
+ 'always',
42
+ {
43
+ ignoreAtRules: ['if', 'else']
44
+ }
45
+ ]
46
+ },
47
+ allowEmptyInput: true,
48
+ ignoreFiles: [
49
+ 'node_modules/**/*',
50
+ 'dist*/**/*'
51
+ ]
52
+ }
53
+ `;
54
+ }
@@ -2,6 +2,7 @@ export const FEATURES_OPTIONS = [
2
2
  { value: "router", label: "Router (SPA 开发)" },
3
3
  { value: "pinia", label: "Pinia (状态管理)" },
4
4
  { value: "piniaPersist", label: "Pinia-plugin-persistedstate (状态持久化)" },
5
+ { value: "unocss", label: "UnoCSS (原子CSS引擎)" },
5
6
  { value: "sassEmbedded", label: "SassEmbedded" },
6
7
  { value: "eslintAntfu", label: "ESLint (Antfu风格)" },
7
8
  { value: "stylelint", label: "Stylelint" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackie_qian/create-vue-app",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "main": "dist/index.js",