@luxkit/cli 1.0.5 → 1.0.7

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.
Files changed (3) hide show
  1. package/README.md +9 -9
  2. package/dist/index.js +170 -144
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -28,9 +28,9 @@
28
28
 
29
29
  | Feature | Description |
30
30
  | :------------------------- | :----------------------------------------------------------------------------- |
31
- | 🎯 **One Command Setup** | `lux fmt web` generates all linting & formatting configs instantly |
32
- | 🔧 **5 Fmt Presets** | `web` · `electron` · `uniapp` · `node` · `nest` — each with curated rules |
33
- | 🖥️ **6 VSCode Presets** | `web` · `electron` · `uniapp` · `node` · `nest` · `go` — settings + extensions |
31
+ | 🎯 **One Command Setup** | `lux fmt web-vue` generates all linting & formatting configs instantly |
32
+ | 🔧 **5 Fmt Presets** | `web-vue` · `electron-vue` · `uniapp` · `node` · `nest` — each with curated rules |
33
+ | 🖥️ **6 VSCode Presets** | `web-vue` · `electron-vue` · `uniapp` · `node` · `nest` · `go` — settings + extensions |
34
34
  | 🔀 **Smart Merge** | Preset wins for linting keys; user wins for personal preferences |
35
35
  | 🛡️ **Conflict Resolution** | `neverOverwrite` / `forceOverwrite` lists + `--force` flag |
36
36
  | 📦 **Auto Install** | Detects bun / pnpm / yarn / npm and installs devDependencies |
@@ -51,10 +51,10 @@ npm install -g @luxkit/cli
51
51
  bun add -g @luxkit/cli
52
52
 
53
53
  # Initialize formatting configs
54
- lux fmt web # Generate ESLint, Prettier, Stylelint, CSpell, EditorConfig
54
+ lux fmt web-vue # Generate ESLint, Prettier, Stylelint, CSpell, EditorConfig
55
55
 
56
56
  # Initialize VSCode settings
57
- lux vscode web # Generate .vscode/settings.json + extensions.json
57
+ lux vscode web-vue # Generate .vscode/settings.json + extensions.json
58
58
 
59
59
  # List available presets
60
60
  lux fmt list
@@ -86,8 +86,8 @@ lux vscode list
86
86
 
87
87
  | Preset | Fmt | VSCode | Stack |
88
88
  | :--------- | :-: | :----: | :--------------------------- |
89
- | `web` | ✅ | ✅ | Vue / React / TS / CSS |
90
- | `electron` | ✅ | ✅ | Electron + Web stack |
89
+ | `web-vue` | ✅ | ✅ | Vue / React / TS / CSS |
90
+ | `electron-vue` | ✅ | ✅ | Electron + Web stack |
91
91
  | `uniapp` | ✅ | ✅ | UniApp / WeChat Mini Program |
92
92
  | `node` | ✅ | ✅ | Node.js backend |
93
93
  | `nest` | ✅ | ✅ | NestJS backend |
@@ -110,7 +110,7 @@ lux fmt <preset> [options]
110
110
  ### How It Works
111
111
 
112
112
  ```
113
- lux fmt web
113
+ lux fmt web-vue
114
114
 
115
115
 
116
116
  Parse CLI args ──► Resolve preset (fuzzy match on typo)
@@ -154,7 +154,7 @@ cd lux
154
154
  bun install
155
155
 
156
156
  bun link # Register `lux` globally for testing
157
- lux fmt web # Test it on any project
157
+ lux fmt web-vue # Test it on any project
158
158
 
159
159
  bun test # Run tests
160
160
  bun build # Build to dist/
package/dist/index.js CHANGED
@@ -6,9 +6,9 @@ import { program } from "commander";
6
6
  // src/commands/fmt.ts
7
7
  import path4 from "path";
8
8
 
9
- // src/presets/fmt/electron.ts
10
- var electronFmt = {
11
- name: "electron",
9
+ // src/presets/fmt/electron-vue.ts
10
+ var electronVueFmt = {
11
+ name: "electron-vue",
12
12
  description: "Vue 3 + Electron desktop app",
13
13
  eslint: () => `import withVue from '@vue/eslint-config-typescript'
14
14
  import withPrettier from '@vue/eslint-config-prettier/skip-formatting'
@@ -156,7 +156,6 @@ dist/
156
156
  build/
157
157
  coverage/
158
158
  `,
159
- // No stylelint for NestJS
160
159
  cspell: () => JSON.stringify(
161
160
  {
162
161
  $schema: "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
@@ -240,7 +239,7 @@ export default defineConfig(
240
239
  trailingComma: "all",
241
240
  singleQuote: true,
242
241
  printWidth: 100,
243
- tabWidth: 3,
242
+ tabWidth: 2,
244
243
  useTabs: false,
245
244
  quoteProps: "as-needed",
246
245
  jsxSingleQuote: true,
@@ -278,7 +277,7 @@ coverage/
278
277
  [*]
279
278
  charset = utf-8
280
279
  indent_style = space
281
- indent_size = 3
280
+ indent_size = 2
282
281
  end_of_line = lf
283
282
  insert_final_newline = true
284
283
  trim_trailing_whitespace = true
@@ -432,9 +431,9 @@ trim_trailing_whitespace = false
432
431
  }
433
432
  };
434
433
 
435
- // src/presets/fmt/web.ts
436
- var webFmt = {
437
- name: "web",
434
+ // src/presets/fmt/web-vue.ts
435
+ var webVueFmt = {
436
+ name: "web-vue",
438
437
  description: "Vue 3 Web frontend (Vite + Vue + TypeScript)",
439
438
  eslint: () => `import withVue from '@vue/eslint-config-typescript'
440
439
  import withPrettier from '@vue/eslint-config-prettier/skip-formatting'
@@ -552,7 +551,7 @@ trim_trailing_whitespace = false
552
551
  };
553
552
 
554
553
  // src/presets/fmt/index.ts
555
- var FMT_PRESETS = [webFmt, electronFmt, uniappFmt, nodeFmt, nestFmt];
554
+ var FMT_PRESETS = [webVueFmt, electronVueFmt, uniappFmt, nodeFmt, nestFmt];
556
555
 
557
556
  // src/utils/logger.ts
558
557
  import chalk from "chalk";
@@ -700,6 +699,7 @@ function generateConfigFile(preset, filename, content, opts) {
700
699
  function generateAllFmt(preset, opts) {
701
700
  const result = { created: [], overwritten: [], skipped: [] };
702
701
  for (const { filename, getContent } of CONFIG_FILES) {
702
+ if (opts.noStylelint && filename.includes("stylelint")) continue;
703
703
  const content = getContent(preset);
704
704
  if (content === void 0) continue;
705
705
  const action = generateConfigFile(preset, filename, content, opts);
@@ -783,7 +783,7 @@ async function installDevDeps(packages, cwd, pm) {
783
783
  // src/commands/fmt.ts
784
784
  function registerFmtCommand(program2) {
785
785
  const fmt = program2.command("fmt").description("Initialize formatting config with preset");
786
- fmt.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--no-install", "Skip dependency installation").option("--dry-run", "Preview without writing files").action(
786
+ fmt.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--no-install", "Skip dependency installation").option("--dry-run", "Preview without writing files").option("--no-stylelint", "Skip Stylelint config generation").action(
787
787
  async (presetName, options) => {
788
788
  const preset = resolvePreset(FMT_PRESETS, presetName);
789
789
  if (!preset) return;
@@ -793,6 +793,7 @@ function registerFmtCommand(program2) {
793
793
  cwd,
794
794
  force: options.force ?? false,
795
795
  dryRun: options.dryRun ?? false,
796
+ noStylelint: options.stylelint === false,
796
797
  lockfile: pm ? getLockfileName(pm) : void 0
797
798
  };
798
799
  const result = generateAllFmt(preset, opts);
@@ -938,13 +939,14 @@ function getEnvConfig() {
938
939
  const eqIndex = trimmed.indexOf("=");
939
940
  if (eqIndex === -1) continue;
940
941
  const key = trimmed.slice(0, eqIndex).trim();
941
- const value = trimmed.slice(eqIndex + 1).trim();
942
+ const raw = trimmed.slice(eqIndex + 1).trim();
943
+ const value = raw.replace(/^["']|["']$/g, "");
942
944
  if (key) result[key] = value;
943
945
  }
944
946
  return result;
945
947
  }
946
948
  function setEnvConfig(data) {
947
- const lines = Object.entries(data).filter(([, v]) => v !== "").map(([k, v]) => `${k}=${v}`);
949
+ const lines = Object.entries(data).filter(([, v]) => v !== "").map(([k, v]) => `${k}="${v}"`);
948
950
  writeFile(getEnvConfigPath(), lines.join("\n") + "\n");
949
951
  }
950
952
  function clearEnvConfig() {
@@ -963,7 +965,7 @@ function handleShowEnv() {
963
965
  return;
964
966
  }
965
967
  for (const [key, value] of entries) {
966
- logger.log(`${key}=${value}`);
968
+ logger.log(`${key}="${value}"`);
967
969
  }
968
970
  }
969
971
  function registerShowCommand(program2) {
@@ -1062,12 +1064,12 @@ function registerUpdateCommand(program2) {
1062
1064
  });
1063
1065
  }
1064
1066
 
1065
- // src/presets/vscode/web.ts
1066
- var webVscode = {
1067
- name: "web",
1067
+ // src/presets/vscode/web-vue.ts
1068
+ var webVueVscode = {
1069
+ name: "web-vue",
1068
1070
  description: "VSCode config for Vue 3 Web",
1069
1071
  settings: () => ({
1070
- // ===== 编辑器爱好设置 =====
1072
+ // ===== Editor Preferences =====
1071
1073
  "editor.tabSize": 2,
1072
1074
  "editor.detectIndentation": false,
1073
1075
  "editor.insertSpaces": true,
@@ -1080,26 +1082,25 @@ var webVscode = {
1080
1082
  "source.fixAll.stylelint": "explicit",
1081
1083
  "source.organizeImports": "never"
1082
1084
  },
1083
- // 光标与动画
1085
+ // Cursor & Animation
1084
1086
  "editor.cursorBlinking": "expand",
1085
1087
  "editor.cursorSmoothCaretAnimation": "on",
1086
1088
  "editor.largeFileOptimizations": true,
1087
- // 代码辅助
1089
+ // Code Assistance
1088
1090
  "editor.inlineSuggest.enabled": true,
1089
1091
  "editor.suggestSelection": "recentlyUsedByPrefix",
1090
1092
  "editor.acceptSuggestionOnEnter": "smart",
1091
1093
  "editor.bracketPairColorization.enabled": true,
1092
1094
  "editor.autoClosingBrackets": "beforeWhitespace",
1093
1095
  "editor.autoClosingOvertype": "always",
1094
- // ===== TypeScript 专项优化 =====
1096
+ // ===== TypeScript =====
1095
1097
  "js/ts.inlayHints.enumMemberValues.enabled": true,
1096
1098
  "js/ts.preferences.preferTypeOnlyAutoImports": true,
1097
1099
  "js/ts.preferences.includePackageJsonAutoImports": "on",
1098
1100
  "js/ts.preferences.importModuleSpecifier": "relative",
1099
1101
  "js/ts.suggest.autoImports": true,
1100
1102
  "js/ts.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"],
1101
- "js/ts.tsdk.path": "node_modules/typescript/lib",
1102
- // ===== 语言特定格式化 =====
1103
+ // ===== Language-specific Formatting =====
1103
1104
  "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1104
1105
  "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1105
1106
  "[scss]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
@@ -1113,18 +1114,22 @@ var webVscode = {
1113
1114
  },
1114
1115
  "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1115
1116
  "[vue]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1116
- // ===== 终端配置 =====
1117
+ // ===== Terminal =====
1117
1118
  "terminal.integrated.cursorBlinking": true,
1118
1119
  "terminal.integrated.tabs.enabled": true,
1119
1120
  "terminal.integrated.scrollback": 1e4,
1120
- // ===== 文件排除 =====
1121
+ // ===== File Exclusion =====
1121
1122
  "files.watcherExclude": {
1122
1123
  "**/.git/objects/**": true,
1123
1124
  "**/.git/subtree-cache/**": true,
1124
1125
  "**/.vscode/**": true,
1125
1126
  "**/node_modules/**": true,
1126
1127
  "**/tmp/**": true,
1127
- "**/dist/**": true
1128
+ "**/dist/**": true,
1129
+ "**/pnpm-lock.yaml": true,
1130
+ "**/package-lock.json": true,
1131
+ "**/bun.lock": true,
1132
+ "**/yarn.lock": true
1128
1133
  },
1129
1134
  "search.exclude": {
1130
1135
  "**/node_modules": true,
@@ -1135,13 +1140,16 @@ var webVscode = {
1135
1140
  "**/.vscode": false,
1136
1141
  "**/tmp": true,
1137
1142
  node_modules: true,
1138
- "**/pnpm-lock.yaml": true
1143
+ "**/pnpm-lock.yaml": true,
1144
+ "**/package-lock.json": true,
1145
+ "**/bun.lock": true,
1146
+ "**/yarn.lock": true
1139
1147
  },
1140
- // ===== 文件嵌套(美观优化)=====
1148
+ // ===== File Nesting =====
1141
1149
  "explorer.fileNesting.enabled": true,
1142
1150
  "explorer.fileNesting.expand": false,
1143
1151
  "explorer.fileNesting.patterns": {
1144
- "package.json": "pnpm-lock.yaml, .gitignore, .browserslistrc, .npmrc, cspell.json",
1152
+ "package.json": "pnpm-lock.yaml,yarn.lock,bun.lock, .gitignore, .browserslistrc, .npmrc, cspell.json,README.md, LICENSE*,.editorconfig",
1145
1153
  "eslint.config.mjs": ".prettierignore, .prettierrc, .prettierrc.json, .editorconfig",
1146
1154
  "tsconfig.json": "tsconfig.*.json",
1147
1155
  "tailwind.config.js": "postcss.config.js",
@@ -1163,7 +1171,6 @@ var webVscode = {
1163
1171
  ],
1164
1172
  // ===== Stylelint =====
1165
1173
  "stylelint.enable": true,
1166
- "stylelint.packageManager": "pnpm",
1167
1174
  "stylelint.validate": ["css", "scss", "vue"],
1168
1175
  "stylelint.customSyntax": "postcss-html",
1169
1176
  "stylelint.snippet": ["css", "scss", "vue"],
@@ -1171,9 +1178,7 @@ var webVscode = {
1171
1178
  "less.validate": false,
1172
1179
  "scss.validate": false,
1173
1180
  // ===== CSpell =====
1174
- "cSpell.language": "en",
1175
- // ===== 包管理器 =====
1176
- "npm.packageManager": "pnpm"
1181
+ "cSpell.language": "en"
1177
1182
  }),
1178
1183
  extensions: () => [
1179
1184
  "vue.volar",
@@ -1182,21 +1187,16 @@ var webVscode = {
1182
1187
  "stylelint.vscode-stylelint",
1183
1188
  "mrmlnc.vscode-scss",
1184
1189
  "streetsidesoftware.code-spell-checker",
1185
- "yoavbls.pretty-ts-errors",
1186
- "editorconfig.editorconfig",
1187
- "aaron-bond.better-comments",
1188
- "usernamehw.errorlens",
1189
- "christian-kohler.path-intellisense",
1190
- "vscode-icons-team.vscode-icons"
1190
+ "editorconfig.editorconfig"
1191
1191
  ]
1192
1192
  };
1193
1193
 
1194
1194
  // src/presets/vscode/electron.ts
1195
- var electronVscode = {
1196
- name: "electron",
1195
+ var electronVueVscode = {
1196
+ name: "electron-vue",
1197
1197
  description: "VSCode config for Vue 3 + Electron",
1198
1198
  settings: () => ({
1199
- // ===== 编辑器爱好设置 =====
1199
+ // ===== Editor Preferences =====
1200
1200
  "editor.tabSize": 2,
1201
1201
  "editor.detectIndentation": false,
1202
1202
  "editor.insertSpaces": true,
@@ -1218,7 +1218,7 @@ var electronVscode = {
1218
1218
  "editor.bracketPairColorization.enabled": true,
1219
1219
  "editor.autoClosingBrackets": "beforeWhitespace",
1220
1220
  "editor.autoClosingOvertype": "always",
1221
- // ===== TypeScript 专项优化 =====
1221
+ // ===== TypeScript =====
1222
1222
  "js/ts.inlayHints.enumMemberValues.enabled": true,
1223
1223
  "js/ts.preferences.preferTypeOnlyAutoImports": true,
1224
1224
  "js/ts.preferences.includePackageJsonAutoImports": "on",
@@ -1226,7 +1226,7 @@ var electronVscode = {
1226
1226
  "js/ts.suggest.autoImports": true,
1227
1227
  "js/ts.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"],
1228
1228
  "js/ts.tsdk.path": "node_modules/typescript/lib",
1229
- // ===== 语言特定格式化 =====
1229
+ // ===== Language-specific Formatting =====
1230
1230
  "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1231
1231
  "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1232
1232
  "[scss]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
@@ -1240,11 +1240,11 @@ var electronVscode = {
1240
1240
  },
1241
1241
  "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1242
1242
  "[vue]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1243
- // ===== 终端配置 =====
1243
+ // ===== Terminal =====
1244
1244
  "terminal.integrated.cursorBlinking": true,
1245
1245
  "terminal.integrated.tabs.enabled": true,
1246
1246
  "terminal.integrated.scrollback": 1e4,
1247
- // ===== 文件排除 =====
1247
+ // ===== File Exclusion =====
1248
1248
  "files.watcherExclude": {
1249
1249
  "**/.git/objects/**": true,
1250
1250
  "**/.git/subtree-cache/**": true,
@@ -1253,7 +1253,11 @@ var electronVscode = {
1253
1253
  "**/tmp/**": true,
1254
1254
  "**/dist/**": true,
1255
1255
  "**/release/**": true,
1256
- "**/out/**": true
1256
+ "**/out/**": true,
1257
+ "**/pnpm-lock.yaml": true,
1258
+ "**/package-lock.json": true,
1259
+ "**/bun.lock": true,
1260
+ "**/yarn.lock": true
1257
1261
  },
1258
1262
  "search.exclude": {
1259
1263
  "**/node_modules": true,
@@ -1266,14 +1270,17 @@ var electronVscode = {
1266
1270
  "**/.vscode": false,
1267
1271
  "**/tmp": true,
1268
1272
  node_modules: true,
1269
- "**/pnpm-lock.yaml": true
1273
+ "**/pnpm-lock.yaml": true,
1274
+ "**/package-lock.json": true,
1275
+ "**/bun.lock": true,
1276
+ "**/yarn.lock": true
1270
1277
  },
1271
- // ===== 文件嵌套 =====
1278
+ // ===== File Nesting =====
1272
1279
  "explorer.fileNesting.enabled": true,
1273
1280
  "explorer.fileNesting.expand": false,
1274
1281
  "explorer.fileNesting.patterns": {
1275
- "package.json": "pnpm-lock.yaml, .gitignore, .browserslistrc, .npmrc, cspell.json",
1276
- "eslint.config.mjs": ".prettierignore, .prettierrc.json, .editorconfig",
1282
+ "package.json": "pnpm-lock.yaml,yarn.lock,bun.lock, .gitignore, .browserslistrc, .npmrc, cspell.json,README.md, LICENSE*,.editorconfig",
1283
+ "eslint.config.mjs": ".prettierignore, .prettierrc, .prettierrc.json, .editorconfig",
1277
1284
  "tsconfig.json": "tsconfig.*.json",
1278
1285
  "tailwind.config.js": "postcss.config.js",
1279
1286
  "vite.config.{js,ts}": "vite.*.{js,ts}",
@@ -1305,7 +1312,7 @@ var electronVscode = {
1305
1312
  "scss.validate": false,
1306
1313
  // ===== CSpell =====
1307
1314
  "cSpell.language": "en",
1308
- // ===== 包管理器 =====
1315
+ // ===== Package Manager =====
1309
1316
  "npm.packageManager": "pnpm"
1310
1317
  }),
1311
1318
  extensions: () => [
@@ -1315,12 +1322,7 @@ var electronVscode = {
1315
1322
  "stylelint.vscode-stylelint",
1316
1323
  "mrmlnc.vscode-scss",
1317
1324
  "streetsidesoftware.code-spell-checker",
1318
- "yoavbls.pretty-ts-errors",
1319
- "editorconfig.editorconfig",
1320
- "aaron-bond.better-comments",
1321
- "usernamehw.errorlens",
1322
- "christian-kohler.path-intellisense",
1323
- "vscode-icons-team.vscode-icons"
1325
+ "editorconfig.editorconfig"
1324
1326
  ]
1325
1327
  };
1326
1328
 
@@ -1329,7 +1331,7 @@ var uniappVscode = {
1329
1331
  name: "uniapp",
1330
1332
  description: "VSCode config for UniApp",
1331
1333
  settings: () => ({
1332
- // ===== 编辑器爱好设置 =====
1334
+ // ===== Editor Preferences =====
1333
1335
  "editor.tabSize": 2,
1334
1336
  "editor.detectIndentation": false,
1335
1337
  "editor.insertSpaces": true,
@@ -1351,7 +1353,7 @@ var uniappVscode = {
1351
1353
  "editor.bracketPairColorization.enabled": true,
1352
1354
  "editor.autoClosingBrackets": "beforeWhitespace",
1353
1355
  "editor.autoClosingOvertype": "always",
1354
- // ===== TypeScript 专项优化 =====
1356
+ // ===== TypeScript =====
1355
1357
  "js/ts.inlayHints.enumMemberValues.enabled": true,
1356
1358
  "js/ts.preferences.preferTypeOnlyAutoImports": true,
1357
1359
  "js/ts.preferences.includePackageJsonAutoImports": "on",
@@ -1359,7 +1361,7 @@ var uniappVscode = {
1359
1361
  "js/ts.suggest.autoImports": true,
1360
1362
  "js/ts.tsserver.exclude": ["**/node_modules", "**/dist", "**/unpackage"],
1361
1363
  "js/ts.tsdk.path": "node_modules/typescript/lib",
1362
- // ===== 语言特定格式化 =====
1364
+ // ===== Language-specific Formatting =====
1363
1365
  "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1364
1366
  "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1365
1367
  "[scss]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
@@ -1373,18 +1375,22 @@ var uniappVscode = {
1373
1375
  },
1374
1376
  "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1375
1377
  "[vue]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1376
- // ===== 终端配置 =====
1378
+ // ===== Terminal =====
1377
1379
  "terminal.integrated.cursorBlinking": true,
1378
1380
  "terminal.integrated.tabs.enabled": true,
1379
1381
  "terminal.integrated.scrollback": 1e4,
1380
- // ===== 文件排除 =====
1382
+ // ===== File Exclusion =====
1381
1383
  "files.watcherExclude": {
1382
1384
  "**/.git/objects/**": true,
1383
1385
  "**/.git/subtree-cache/**": true,
1384
1386
  "**/node_modules/**": true,
1385
1387
  "**/tmp/**": true,
1386
1388
  "**/dist/**": true,
1387
- "**/unpackage/**": true
1389
+ "**/unpackage/**": true,
1390
+ "**/pnpm-lock.yaml": true,
1391
+ "**/package-lock.json": true,
1392
+ "**/bun.lock": true,
1393
+ "**/yarn.lock": true
1388
1394
  },
1389
1395
  "search.exclude": {
1390
1396
  "**/node_modules": true,
@@ -1393,14 +1399,17 @@ var uniappVscode = {
1393
1399
  "**/unpackage": true,
1394
1400
  "**/.git": true,
1395
1401
  "**/tmp": true,
1396
- "**/pnpm-lock.yaml": true
1402
+ "**/pnpm-lock.yaml": true,
1403
+ "**/package-lock.json": true,
1404
+ "**/bun.lock": true,
1405
+ "**/yarn.lock": true
1397
1406
  },
1398
- // ===== 文件嵌套 =====
1407
+ // ===== File Nesting =====
1399
1408
  "explorer.fileNesting.enabled": true,
1400
1409
  "explorer.fileNesting.expand": false,
1401
1410
  "explorer.fileNesting.patterns": {
1402
- "package.json": "pnpm-lock.yaml, .gitignore, manifest.json, pages.json",
1403
- "eslint.config.mjs": ".prettierignore, .prettierrc.json",
1411
+ "package.json": "pnpm-lock.yaml,yarn.lock,bun.lock, .gitignore, manifest.json, pages.json,cspell.json,README.md, LICENSE*,.editorconfig",
1412
+ "eslint.config.mjs": ".prettierignore, .prettierrc, .prettierrc.json, .editorconfig",
1404
1413
  "tsconfig.json": "tsconfig.*.json",
1405
1414
  ".env": ".env.*"
1406
1415
  },
@@ -1419,7 +1428,6 @@ var uniappVscode = {
1419
1428
  ],
1420
1429
  // ===== Stylelint =====
1421
1430
  "stylelint.enable": true,
1422
- "stylelint.packageManager": "pnpm",
1423
1431
  "stylelint.validate": ["css", "scss", "vue"],
1424
1432
  "stylelint.customSyntax": "postcss-html",
1425
1433
  "stylelint.snippet": ["css", "scss", "vue"],
@@ -1427,9 +1435,7 @@ var uniappVscode = {
1427
1435
  "less.validate": false,
1428
1436
  "scss.validate": false,
1429
1437
  // ===== CSpell =====
1430
- "cSpell.language": "en",
1431
- // ===== 包管理器 =====
1432
- "npm.packageManager": "pnpm"
1438
+ "cSpell.language": "en"
1433
1439
  }),
1434
1440
  extensions: () => [
1435
1441
  "vue.volar",
@@ -1438,12 +1444,7 @@ var uniappVscode = {
1438
1444
  "stylelint.vscode-stylelint",
1439
1445
  "mrmlnc.vscode-scss",
1440
1446
  "streetsidesoftware.code-spell-checker",
1441
- "yoavbls.pretty-ts-errors",
1442
- "editorconfig.editorconfig",
1443
- "aaron-bond.better-comments",
1444
- "usernamehw.errorlens",
1445
- "christian-kohler.path-intellisense",
1446
- "vscode-icons-team.vscode-icons"
1447
+ "editorconfig.editorconfig"
1447
1448
  ]
1448
1449
  };
1449
1450
 
@@ -1452,8 +1453,8 @@ var nodeVscode = {
1452
1453
  name: "node",
1453
1454
  description: "VSCode config for Node.js",
1454
1455
  settings: () => ({
1455
- // ===== 编辑器爱好设置 =====
1456
- "editor.tabSize": 3,
1456
+ // ===== Editor Preferences =====
1457
+ "editor.tabSize": 2,
1457
1458
  "editor.detectIndentation": false,
1458
1459
  "editor.insertSpaces": true,
1459
1460
  "editor.renderWhitespace": "selection",
@@ -1473,15 +1474,14 @@ var nodeVscode = {
1473
1474
  "editor.bracketPairColorization.enabled": true,
1474
1475
  "editor.autoClosingBrackets": "beforeWhitespace",
1475
1476
  "editor.autoClosingOvertype": "always",
1476
- // ===== TypeScript 专项优化 =====
1477
+ // ===== TypeScript =====
1477
1478
  "js/ts.inlayHints.enumMemberValues.enabled": true,
1478
1479
  "js/ts.preferences.preferTypeOnlyAutoImports": true,
1479
1480
  "js/ts.preferences.includePackageJsonAutoImports": "on",
1480
1481
  "js/ts.preferences.importModuleSpecifier": "relative",
1481
1482
  "js/ts.suggest.autoImports": true,
1482
1483
  "js/ts.tsserver.exclude": ["**/node_modules", "**/dist"],
1483
- "js/ts.tsdk.path": "node_modules/typescript/lib",
1484
- // ===== 语言特定格式化 =====
1484
+ // ===== Language-specific Formatting =====
1485
1485
  "[typescript]": {
1486
1486
  "editor.defaultFormatter": "esbenp.prettier-vscode",
1487
1487
  "editor.formatOnSave": true
@@ -1491,17 +1491,21 @@ var nodeVscode = {
1491
1491
  "editor.formatOnSave": true
1492
1492
  },
1493
1493
  "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1494
- // ===== 终端配置 =====
1494
+ // ===== Terminal =====
1495
1495
  "terminal.integrated.cursorBlinking": true,
1496
1496
  "terminal.integrated.tabs.enabled": true,
1497
1497
  "terminal.integrated.scrollback": 1e4,
1498
- // ===== 文件排除 =====
1498
+ // ===== File Exclusion =====
1499
1499
  "files.watcherExclude": {
1500
1500
  "**/.git/objects/**": true,
1501
1501
  "**/.git/subtree-cache/**": true,
1502
1502
  "**/node_modules/**": true,
1503
1503
  "**/tmp/**": true,
1504
- "**/dist/**": true
1504
+ "**/dist/**": true,
1505
+ "**/pnpm-lock.yaml": true,
1506
+ "**/package-lock.json": true,
1507
+ "**/bun.lock": true,
1508
+ "**/yarn.lock": true
1505
1509
  },
1506
1510
  "search.exclude": {
1507
1511
  "**/node_modules": true,
@@ -1510,13 +1514,16 @@ var nodeVscode = {
1510
1514
  "**/.git": true,
1511
1515
  "**/tmp": true,
1512
1516
  node_modules: true,
1513
- "**/bun.lock": true
1517
+ "**/pnpm-lock.yaml": true,
1518
+ "**/package-lock.json": true,
1519
+ "**/bun.lock": true,
1520
+ "**/yarn.lock": true
1514
1521
  },
1515
- // ===== 文件嵌套 =====
1522
+ // ===== File Nesting =====
1516
1523
  "explorer.fileNesting.enabled": true,
1517
1524
  "explorer.fileNesting.expand": false,
1518
1525
  "explorer.fileNesting.patterns": {
1519
- "package.json": "bun.lock, .gitignore, .npmrc, cspell.json",
1526
+ "package.json": "pnpm-lock.yaml,yarn.lock,bun.lock, .gitignore, .npmrc, cspell.json,README.md,LICENSE*,.editorconfig",
1520
1527
  "eslint.config.mjs": ".prettierignore, .prettierrc.json, .editorconfig,.prettierrc",
1521
1528
  "tsconfig.json": "tsconfig.*.json",
1522
1529
  ".env": ".env.*"
@@ -1524,20 +1531,13 @@ var nodeVscode = {
1524
1531
  // ===== ESLint =====
1525
1532
  "eslint.validate": ["javascript", "typescript", "json", "jsonc", "json5"],
1526
1533
  // ===== CSpell =====
1527
- "cSpell.language": "en",
1528
- // ===== 包管理器 =====
1529
- "npm.packageManager": "bun"
1534
+ "cSpell.language": "en"
1530
1535
  }),
1531
1536
  extensions: () => [
1532
1537
  "dbaeumer.vscode-eslint",
1533
1538
  "esbenp.prettier-vscode",
1534
1539
  "streetsidesoftware.code-spell-checker",
1535
- "yoavbls.pretty-ts-errors",
1536
- "editorconfig.editorconfig",
1537
- "aaron-bond.better-comments",
1538
- "usernamehw.errorlens",
1539
- "christian-kohler.path-intellisense",
1540
- "vscode-icons-team.vscode-icons"
1540
+ "editorconfig.editorconfig"
1541
1541
  ]
1542
1542
  };
1543
1543
 
@@ -1546,7 +1546,7 @@ var nestVscode = {
1546
1546
  name: "nest",
1547
1547
  description: "VSCode config for NestJS",
1548
1548
  settings: () => ({
1549
- // ===== 编辑器爱好设置 =====
1549
+ // ===== Editor Preferences =====
1550
1550
  "editor.tabSize": 2,
1551
1551
  "editor.detectIndentation": false,
1552
1552
  "editor.insertSpaces": true,
@@ -1564,7 +1564,7 @@ var nestVscode = {
1564
1564
  "editor.bracketPairColorization.enabled": true,
1565
1565
  "editor.autoClosingBrackets": "beforeWhitespace",
1566
1566
  "editor.autoClosingOvertype": "always",
1567
- // ===== TypeScript 专项优化 =====
1567
+ // ===== TypeScript =====
1568
1568
  "js/ts.inlayHints.enumMemberValues.enabled": true,
1569
1569
  "js/ts.preferences.preferTypeOnlyAutoImports": true,
1570
1570
  "js/ts.preferences.includePackageJsonAutoImports": "on",
@@ -1572,7 +1572,7 @@ var nestVscode = {
1572
1572
  "js/ts.suggest.autoImports": true,
1573
1573
  "js/ts.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"],
1574
1574
  "js/ts.tsdk.path": "node_modules/typescript/lib",
1575
- // ===== 语言特定格式化 =====
1575
+ // ===== Language-specific Formatting =====
1576
1576
  "[typescript]": {
1577
1577
  "editor.defaultFormatter": "esbenp.prettier-vscode",
1578
1578
  "editor.formatOnSave": true
@@ -1582,17 +1582,21 @@ var nestVscode = {
1582
1582
  "editor.formatOnSave": true
1583
1583
  },
1584
1584
  "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
1585
- // ===== 终端配置 =====
1585
+ // ===== Terminal =====
1586
1586
  "terminal.integrated.cursorBlinking": true,
1587
1587
  "terminal.integrated.tabs.enabled": true,
1588
1588
  "terminal.integrated.scrollback": 1e4,
1589
- // ===== 文件排除 =====
1589
+ // ===== File Exclusion =====
1590
1590
  "files.watcherExclude": {
1591
1591
  "**/.git/objects/**": true,
1592
1592
  "**/.git/subtree-cache/**": true,
1593
1593
  "**/node_modules/**": true,
1594
1594
  "**/tmp/**": true,
1595
- "**/dist/**": true
1595
+ "**/dist/**": true,
1596
+ "**/pnpm-lock.yaml": true,
1597
+ "**/package-lock.json": true,
1598
+ "**/bun.lock": true,
1599
+ "**/yarn.lock": true
1596
1600
  },
1597
1601
  "search.exclude": {
1598
1602
  "**/node_modules": true,
@@ -1600,14 +1604,17 @@ var nestVscode = {
1600
1604
  "**/dist": true,
1601
1605
  "**/.git": true,
1602
1606
  "**/tmp": true,
1603
- "**/pnpm-lock.yaml": true
1607
+ "**/pnpm-lock.yaml": true,
1608
+ "**/package-lock.json": true,
1609
+ "**/bun.lock": true,
1610
+ "**/yarn.lock": true
1604
1611
  },
1605
- // ===== 文件嵌套 =====
1612
+ // ===== File Nesting =====
1606
1613
  "explorer.fileNesting.enabled": true,
1607
1614
  "explorer.fileNesting.expand": false,
1608
1615
  "explorer.fileNesting.patterns": {
1609
- "package.json": "pnpm-lock.yaml, .gitignore, .npmrc, nest-cli.json",
1610
- "eslint.config.mjs": ".prettierignore, .prettierrc.json, .editorconfig",
1616
+ "package.json": "pnpm-lock.yaml,yarn.lock,bun.lock, .gitignore, .npmrc, nest-cli.json,cspell.json,README.md, LICENSE*,.editorconfig",
1617
+ "eslint.config.mjs": ".prettierignore, .prettierrc, .prettierrc.json, .editorconfig",
1611
1618
  "tsconfig.json": "tsconfig.*.json",
1612
1619
  ".env": ".env.*",
1613
1620
  "*.controller.ts": "$(capture).controller.spec.ts",
@@ -1635,13 +1642,7 @@ var nestVscode = {
1635
1642
  "dbaeumer.vscode-eslint",
1636
1643
  "esbenp.prettier-vscode",
1637
1644
  "streetsidesoftware.code-spell-checker",
1638
- "yoavbls.pretty-ts-errors",
1639
- "editorconfig.editorconfig",
1640
- "firsttris.vscode-jest-runner",
1641
- "aaron-bond.better-comments",
1642
- "usernamehw.errorlens",
1643
- "christian-kohler.path-intellisense",
1644
- "vscode-icons-team.vscode-icons"
1645
+ "editorconfig.editorconfig"
1645
1646
  ]
1646
1647
  };
1647
1648
 
@@ -1680,8 +1681,8 @@ var goVscode = {
1680
1681
 
1681
1682
  // src/presets/vscode/index.ts
1682
1683
  var VSCODE_PRESETS = [
1683
- webVscode,
1684
- electronVscode,
1684
+ webVueVscode,
1685
+ electronVueVscode,
1685
1686
  uniappVscode,
1686
1687
  nodeVscode,
1687
1688
  nestVscode,
@@ -1734,13 +1735,21 @@ function isPlainObject(val) {
1734
1735
  }
1735
1736
 
1736
1737
  // src/generators/vscode.ts
1738
+ var STYLELINT_SETTINGS_PREFIXES = [
1739
+ "stylelint.",
1740
+ "css.validate",
1741
+ "less.validate",
1742
+ "scss.validate"
1743
+ ];
1744
+ var STYLELINT_EXTENSION = "stylelint.vscode-stylelint";
1737
1745
  function generateVscodeSettings(preset, opts) {
1738
1746
  const settingsPath = `${opts.cwd}/.vscode/settings.json`;
1739
1747
  if (opts.dryRun) {
1740
1748
  const existingSettings2 = readJson(settingsPath);
1741
1749
  return existingSettings2 ? "overwritten" : "created";
1742
1750
  }
1743
- const presetSettings = preset.settings();
1751
+ const rawSettings = preset.settings();
1752
+ const presetSettings = opts.noStylelint ? filterStylelintSettings(rawSettings) : rawSettings;
1744
1753
  const existingSettings = readJson(settingsPath);
1745
1754
  if (existingSettings) {
1746
1755
  const backupPath = `${settingsPath}.bak`;
@@ -1757,7 +1766,8 @@ function generateVscodeSettings(preset, opts) {
1757
1766
  }
1758
1767
  function generateVscodeExtensions(preset, opts) {
1759
1768
  if (opts.dryRun) return "created";
1760
- writeJson(`${opts.cwd}/.vscode/extensions.json`, { recommendations: preset.extensions() });
1769
+ const extensions = opts.noStylelint ? preset.extensions().filter((ext) => ext !== STYLELINT_EXTENSION) : preset.extensions();
1770
+ writeJson(`${opts.cwd}/.vscode/extensions.json`, { recommendations: extensions });
1761
1771
  return "created";
1762
1772
  }
1763
1773
  function generateAllVscode(preset, opts) {
@@ -1769,31 +1779,47 @@ function generateAllVscode(preset, opts) {
1769
1779
  if (extAction === "created") result.created.push(".vscode/extensions.json");
1770
1780
  return result;
1771
1781
  }
1782
+ function filterStylelintSettings(settings) {
1783
+ const filtered = Object.fromEntries(
1784
+ Object.entries(settings).filter(
1785
+ ([key]) => !STYLELINT_SETTINGS_PREFIXES.some((prefix) => key.startsWith(prefix))
1786
+ )
1787
+ );
1788
+ if (typeof filtered["editor.codeActionsOnSave"] === "object" && filtered["editor.codeActionsOnSave"] !== null) {
1789
+ const actions = { ...filtered["editor.codeActionsOnSave"] };
1790
+ delete actions["source.fixAll.stylelint"];
1791
+ filtered["editor.codeActionsOnSave"] = actions;
1792
+ }
1793
+ return filtered;
1794
+ }
1772
1795
 
1773
1796
  // src/commands/vscode.ts
1774
1797
  function registerVscodeCommand(program2) {
1775
1798
  const vscode = program2.command("vscode").description("Initialize VSCode config with preset");
1776
- vscode.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--dry-run", "Preview without writing files").action(async (presetName, options) => {
1777
- const preset = resolvePreset(VSCODE_PRESETS, presetName);
1778
- if (!preset) return;
1779
- const cwd = process.cwd();
1780
- const opts = {
1781
- cwd,
1782
- force: options.force ?? false,
1783
- dryRun: options.dryRun ?? false
1784
- };
1785
- const result = generateAllVscode(preset, opts);
1786
- const files = [...result.created, ...result.overwritten];
1787
- if (files.length === 0) {
1788
- logger.warn("No files generated");
1789
- return;
1790
- }
1791
- if (opts.dryRun) {
1792
- logger.log(`[dry-run] Would create ${files.join(", ")}`);
1793
- return;
1799
+ vscode.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--dry-run", "Preview without writing files").option("--no-stylelint", "Skip Stylelint settings and extension").action(
1800
+ async (presetName, options) => {
1801
+ const preset = resolvePreset(VSCODE_PRESETS, presetName);
1802
+ if (!preset) return;
1803
+ const cwd = process.cwd();
1804
+ const opts = {
1805
+ cwd,
1806
+ force: options.force ?? false,
1807
+ dryRun: options.dryRun ?? false,
1808
+ noStylelint: options.stylelint === false
1809
+ };
1810
+ const result = generateAllVscode(preset, opts);
1811
+ const files = [...result.created, ...result.overwritten];
1812
+ if (files.length === 0) {
1813
+ logger.warn("No files generated");
1814
+ return;
1815
+ }
1816
+ if (opts.dryRun) {
1817
+ logger.log(`[dry-run] Would create ${files.join(", ")}`);
1818
+ return;
1819
+ }
1820
+ logger.log(`Created ${files.join(", ")}`);
1794
1821
  }
1795
- logger.log(`Created ${files.join(", ")}`);
1796
- });
1822
+ );
1797
1823
  vscode.command("list").description("List available vscode presets").action(() => {
1798
1824
  for (const p of VSCODE_PRESETS) {
1799
1825
  console.log(`${p.name.padEnd(12)} ${p.description}`);
@@ -1805,14 +1831,14 @@ function registerVscodeCommand(program2) {
1805
1831
  import { spawnSync } from "child_process";
1806
1832
  var ALLOWED_KEYS = ["https_proxy", "http_proxy", "all_proxy"];
1807
1833
  function buildCommands(shell, env) {
1808
- const entries = Object.entries(env).map(([k, v]) => `${k}=${v}`);
1834
+ const entries = Object.entries(env);
1809
1835
  if (shell === "cmd") {
1810
- return entries.map((e) => `set ${e}`).join(" && ");
1836
+ return entries.map(([k, v]) => `set ${k}=${v}`).join(" && ");
1811
1837
  }
1812
1838
  if (shell === "bash") {
1813
- return entries.map((e) => `export ${e}`).join(" && ");
1839
+ return entries.map(([k, v]) => `export ${k}="${v}"`).join(" && ");
1814
1840
  }
1815
- return entries.map((e) => `$env:${e}`).join(" ; ");
1841
+ return entries.map(([k, v]) => `$env:${k}="${v}"`).join(" ; ");
1816
1842
  }
1817
1843
  function copyToClipboard(text) {
1818
1844
  const result = spawnSync("clip", [], { input: text, stdio: ["pipe", "ignore", "ignore"] });
@@ -1856,7 +1882,7 @@ function handleSet(args) {
1856
1882
  }
1857
1883
  const eqIndex = arg.indexOf("=");
1858
1884
  const key = arg.slice(0, eqIndex);
1859
- const value = arg.slice(eqIndex + 1);
1885
+ const value = arg.slice(eqIndex + 1).replace(/^["']|["']$/g, "");
1860
1886
  if (!isValidKey(key)) {
1861
1887
  logger.error(`Invalid key: "${key}". Allowed keys: ${ALLOWED_KEYS.join(", ")}`);
1862
1888
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxkit/cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "One-click project formatting & VSCode config CLI",
5
5
  "type": "module",
6
6
  "bin": {