@luxkit/cli 1.1.3 → 1.1.41
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 +101 -46
- package/README_ZH.md +242 -0
- package/dist/index.js +249 -32
- package/dist/skills/lux/references/custom-preset-setting.md +136 -13
- package/dist/skills/lux/skill.md +34 -13
- package/package.json +12 -3
- package/README_Zh.md +0 -189
package/dist/index.js
CHANGED
|
@@ -113,14 +113,25 @@ trim_trailing_whitespace = false
|
|
|
113
113
|
"@stylistic/stylelint-plugin",
|
|
114
114
|
"postcss-html",
|
|
115
115
|
"postcss-scss",
|
|
116
|
-
"cspell"
|
|
116
|
+
"cspell",
|
|
117
|
+
"husky",
|
|
118
|
+
"lint-staged"
|
|
117
119
|
]
|
|
118
120
|
},
|
|
119
121
|
scripts: {
|
|
120
122
|
lint: 'eslint . --cache --cache-location node_modules/.cache/eslint && cspell --cache --cache-location node_modules/.cache/cspell --gitignore "src/**/*" && vue-tsc --noEmit && stylelint "src/**/*.{css,scss,vue}" --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
121
123
|
"lint:fix": 'eslint . --cache --cache-location node_modules/.cache/eslint --fix && stylelint "src/**/*.{css,scss,vue}" --fix --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
122
|
-
format: 'prettier --write "src/**/*.{ts,js,json,vue,css,scss}"'
|
|
123
|
-
|
|
124
|
+
format: 'prettier --write "src/**/*.{ts,js,json,vue,css,scss}"',
|
|
125
|
+
"lint-staged": "lint-staged"
|
|
126
|
+
},
|
|
127
|
+
lintStaged: () => JSON.stringify(
|
|
128
|
+
{
|
|
129
|
+
"*.{ts,js,vue}": ["eslint --fix", "prettier --write"],
|
|
130
|
+
"*.{css,scss,vue}": ["stylelint --fix", "prettier --write"]
|
|
131
|
+
},
|
|
132
|
+
null,
|
|
133
|
+
2
|
|
134
|
+
) + "\n"
|
|
124
135
|
};
|
|
125
136
|
|
|
126
137
|
// src/presets/fmt/nest.ts
|
|
@@ -176,13 +187,21 @@ trim_trailing_whitespace = true
|
|
|
176
187
|
trim_trailing_whitespace = false
|
|
177
188
|
`,
|
|
178
189
|
dependencies: {
|
|
179
|
-
dev: ["prettier", "cspell"]
|
|
190
|
+
dev: ["prettier", "cspell", "husky", "lint-staged"]
|
|
180
191
|
},
|
|
181
192
|
scripts: {
|
|
182
193
|
lint: 'eslint "{src,apps,libs,test}/**/*.ts" --cache --cache-location node_modules/.cache/eslint && cspell --cache --cache-location node_modules/.cache/cspell --gitignore "src/**/*" && tsc --noEmit',
|
|
183
194
|
"lint:fix": 'eslint "{src,apps,libs,test}/**/*.ts" --cache --cache-location node_modules/.cache/eslint --fix',
|
|
184
|
-
format: 'prettier --write "src/**/*.{ts,js,json}"'
|
|
185
|
-
|
|
195
|
+
format: 'prettier --write "src/**/*.{ts,js,json}"',
|
|
196
|
+
"lint-staged": "lint-staged"
|
|
197
|
+
},
|
|
198
|
+
lintStaged: () => JSON.stringify(
|
|
199
|
+
{
|
|
200
|
+
"*.{ts,js}": ["eslint --fix", "prettier --write"]
|
|
201
|
+
},
|
|
202
|
+
null,
|
|
203
|
+
2
|
|
204
|
+
) + "\n"
|
|
186
205
|
};
|
|
187
206
|
|
|
188
207
|
// src/presets/fmt/node.ts
|
|
@@ -287,14 +306,24 @@ trim_trailing_whitespace = false
|
|
|
287
306
|
"eslint-plugin-prettier",
|
|
288
307
|
"eslint-config-prettier",
|
|
289
308
|
"prettier",
|
|
290
|
-
"cspell"
|
|
309
|
+
"cspell",
|
|
310
|
+
"husky",
|
|
311
|
+
"lint-staged"
|
|
291
312
|
]
|
|
292
313
|
},
|
|
293
314
|
scripts: {
|
|
294
315
|
lint: 'eslint . --cache --cache-location node_modules/.cache/eslint && cspell --cache --cache-location node_modules/.cache/cspell --gitignore "src/**/*" && tsc --noEmit',
|
|
295
316
|
"lint:fix": "eslint . --cache --cache-location node_modules/.cache/eslint --fix",
|
|
296
|
-
format: 'prettier --write "src/**/*.{ts,js,json}"'
|
|
297
|
-
|
|
317
|
+
format: 'prettier --write "src/**/*.{ts,js,json}"',
|
|
318
|
+
"lint-staged": "lint-staged"
|
|
319
|
+
},
|
|
320
|
+
lintStaged: () => JSON.stringify(
|
|
321
|
+
{
|
|
322
|
+
"*.{ts,js}": ["eslint --fix", "prettier --write"]
|
|
323
|
+
},
|
|
324
|
+
null,
|
|
325
|
+
2
|
|
326
|
+
) + "\n"
|
|
298
327
|
};
|
|
299
328
|
|
|
300
329
|
// src/presets/fmt/uniapp.ts
|
|
@@ -400,14 +429,25 @@ trim_trailing_whitespace = false
|
|
|
400
429
|
"@stylistic/stylelint-plugin",
|
|
401
430
|
"postcss-html",
|
|
402
431
|
"postcss-scss",
|
|
403
|
-
"cspell"
|
|
432
|
+
"cspell",
|
|
433
|
+
"husky",
|
|
434
|
+
"lint-staged"
|
|
404
435
|
]
|
|
405
436
|
},
|
|
406
437
|
scripts: {
|
|
407
438
|
lint: 'eslint . --cache --cache-location node_modules/.cache/eslint && cspell --cache --cache-location node_modules/.cache/cspell --gitignore "src/**/*" && vue-tsc --noEmit && stylelint "src/**/*.{css,scss,vue}" --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
408
439
|
"lint:fix": 'eslint . --cache --cache-location node_modules/.cache/eslint --fix && stylelint "src/**/*.{css,scss,vue}" --fix --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
409
|
-
format: 'prettier --write "src/**/*.{ts,js,json,vue,css,scss}"'
|
|
410
|
-
|
|
440
|
+
format: 'prettier --write "src/**/*.{ts,js,json,vue,css,scss}"',
|
|
441
|
+
"lint-staged": "lint-staged"
|
|
442
|
+
},
|
|
443
|
+
lintStaged: () => JSON.stringify(
|
|
444
|
+
{
|
|
445
|
+
"*.{ts,js,vue}": ["eslint --fix", "prettier --write"],
|
|
446
|
+
"*.{css,scss,vue}": ["stylelint --fix", "prettier --write"]
|
|
447
|
+
},
|
|
448
|
+
null,
|
|
449
|
+
2
|
|
450
|
+
) + "\n"
|
|
411
451
|
};
|
|
412
452
|
|
|
413
453
|
// src/presets/fmt/web-react.ts
|
|
@@ -520,14 +560,25 @@ trim_trailing_whitespace = false
|
|
|
520
560
|
"stylelint-scss",
|
|
521
561
|
"@stylistic/stylelint-plugin",
|
|
522
562
|
"postcss-scss",
|
|
523
|
-
"cspell"
|
|
563
|
+
"cspell",
|
|
564
|
+
"husky",
|
|
565
|
+
"lint-staged"
|
|
524
566
|
]
|
|
525
567
|
},
|
|
526
568
|
scripts: {
|
|
527
569
|
lint: 'eslint . --cache --cache-location node_modules/.cache/eslint && cspell --cache --cache-location node_modules/.cache/cspell --gitignore "src/**/*" && tsc --noEmit && stylelint "src/**/*.{css,scss}" --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
528
570
|
"lint:fix": 'eslint . --cache --cache-location node_modules/.cache/eslint --fix && stylelint "src/**/*.{css,scss}" --fix --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
529
|
-
format: 'prettier --write "src/**/*.{ts,js,json,jsx,tsx,css,scss}"'
|
|
530
|
-
|
|
571
|
+
format: 'prettier --write "src/**/*.{ts,js,json,jsx,tsx,css,scss}"',
|
|
572
|
+
"lint-staged": "lint-staged"
|
|
573
|
+
},
|
|
574
|
+
lintStaged: () => JSON.stringify(
|
|
575
|
+
{
|
|
576
|
+
"*.{ts,tsx,js,jsx}": ["eslint --fix", "prettier --write"],
|
|
577
|
+
"*.{css,scss}": ["stylelint --fix", "prettier --write"]
|
|
578
|
+
},
|
|
579
|
+
null,
|
|
580
|
+
2
|
|
581
|
+
) + "\n"
|
|
531
582
|
};
|
|
532
583
|
|
|
533
584
|
// src/presets/fmt/web-vue.ts
|
|
@@ -631,14 +682,25 @@ trim_trailing_whitespace = false
|
|
|
631
682
|
"@stylistic/stylelint-plugin",
|
|
632
683
|
"postcss-html",
|
|
633
684
|
"postcss-scss",
|
|
634
|
-
"cspell"
|
|
685
|
+
"cspell",
|
|
686
|
+
"husky",
|
|
687
|
+
"lint-staged"
|
|
635
688
|
]
|
|
636
689
|
},
|
|
637
690
|
scripts: {
|
|
638
691
|
lint: 'eslint . --cache --cache-location node_modules/.cache/eslint && cspell --cache --cache-location node_modules/.cache/cspell --gitignore "src/**/*" && vue-tsc --noEmit && stylelint "src/**/*.{css,scss,vue}" --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
639
692
|
"lint:fix": 'eslint . --cache --cache-location node_modules/.cache/eslint --fix && stylelint "src/**/*.{css,scss,vue}" --fix --cache --cache-strategy content --cache-location node_modules/.cache/stylelint/',
|
|
640
|
-
format: 'prettier --write "src/**/*.{ts,js,json,vue,css,scss}"'
|
|
641
|
-
|
|
693
|
+
format: 'prettier --write "src/**/*.{ts,js,json,vue,css,scss}"',
|
|
694
|
+
"lint-staged": "lint-staged"
|
|
695
|
+
},
|
|
696
|
+
lintStaged: () => JSON.stringify(
|
|
697
|
+
{
|
|
698
|
+
"*.{ts,js,vue}": ["eslint --fix", "prettier --write"],
|
|
699
|
+
"*.{css,scss,vue}": ["stylelint --fix", "prettier --write"]
|
|
700
|
+
},
|
|
701
|
+
null,
|
|
702
|
+
2
|
|
703
|
+
) + "\n"
|
|
642
704
|
};
|
|
643
705
|
|
|
644
706
|
// src/presets/fmt/index.ts
|
|
@@ -776,7 +838,8 @@ var CONFIG_FILES = [
|
|
|
776
838
|
{ filename: "stylelint.config.mjs", getContent: (p) => p.stylelint?.() },
|
|
777
839
|
{ filename: ".stylelintignore", getContent: (p) => p.stylelintIgnore?.() },
|
|
778
840
|
{ filename: "cspell.json", getContent: (p) => p.cspell?.() },
|
|
779
|
-
{ filename: ".editorconfig", getContent: (p) => p.editorconfig?.() }
|
|
841
|
+
{ filename: ".editorconfig", getContent: (p) => p.editorconfig?.() },
|
|
842
|
+
{ filename: ".lintstagedrc.json", getContent: (p) => p.lintStaged?.() }
|
|
780
843
|
];
|
|
781
844
|
function generateConfigFile(preset, filename, content, opts) {
|
|
782
845
|
const filepath = path2.join(opts.cwd, filename);
|
|
@@ -799,6 +862,8 @@ function generateAllFmt(preset, opts) {
|
|
|
799
862
|
for (const { filename, getContent } of CONFIG_FILES) {
|
|
800
863
|
if (opts.noStylelint && filename.includes("stylelint")) continue;
|
|
801
864
|
if (opts.noEditorconfig && filename === ".editorconfig") continue;
|
|
865
|
+
if (opts.noCspell && filename.includes("cspell")) continue;
|
|
866
|
+
if (opts.noLintStaged && filename === ".lintstagedrc.json") continue;
|
|
802
867
|
const content = getContent(preset);
|
|
803
868
|
if (content === void 0) continue;
|
|
804
869
|
const action = generateConfigFile(preset, filename, content, opts);
|
|
@@ -991,10 +1056,13 @@ var CONFIG_GETTERS = [
|
|
|
991
1056
|
{ filename: "stylelint.config.mjs", getContent: (p) => p.stylelint?.() },
|
|
992
1057
|
{ filename: ".stylelintignore", getContent: (p) => p.stylelintIgnore?.() },
|
|
993
1058
|
{ filename: "cspell.json", getContent: (p) => p.cspell?.() },
|
|
994
|
-
{ filename: ".editorconfig", getContent: (p) => p.editorconfig?.() }
|
|
1059
|
+
{ filename: ".editorconfig", getContent: (p) => p.editorconfig?.() },
|
|
1060
|
+
{ filename: ".lintstagedrc.json", getContent: (p) => p.lintStaged?.() }
|
|
995
1061
|
];
|
|
996
1062
|
var STYLELINT_FILES = /* @__PURE__ */ new Set(["stylelint.config.mjs", ".stylelintignore"]);
|
|
997
1063
|
var EDITORCONFIG_FILE = ".editorconfig";
|
|
1064
|
+
var CSPELL_FILE = "cspell.json";
|
|
1065
|
+
var LINTSTAGED_FILE = ".lintstagedrc.json";
|
|
998
1066
|
var STYLELINT_SETTINGS_PREFIXES = [
|
|
999
1067
|
"stylelint.",
|
|
1000
1068
|
"css.validate",
|
|
@@ -1011,6 +1079,8 @@ var STYLELINT_DEPS = /* @__PURE__ */ new Set([
|
|
|
1011
1079
|
"postcss-scss"
|
|
1012
1080
|
]);
|
|
1013
1081
|
var STYLELINT_EXTENSION = "stylelint.vscode-stylelint";
|
|
1082
|
+
var HUSKY_DEPS = /* @__PURE__ */ new Set(["husky"]);
|
|
1083
|
+
var LINTSTAGED_DEPS = /* @__PURE__ */ new Set(["lint-staged"]);
|
|
1014
1084
|
function getLuxDir() {
|
|
1015
1085
|
return process.env.LUX_HOME || path4.join(os.homedir(), ".lux");
|
|
1016
1086
|
}
|
|
@@ -1129,6 +1199,8 @@ function applyLocalFmtPreset(cwd, presetName, opts) {
|
|
|
1129
1199
|
for (const filename of entries) {
|
|
1130
1200
|
if (opts.noStylelint && STYLELINT_FILES.has(filename)) continue;
|
|
1131
1201
|
if (opts.noEditorconfig && filename === EDITORCONFIG_FILE) continue;
|
|
1202
|
+
if (opts.noCspell && filename === CSPELL_FILE) continue;
|
|
1203
|
+
if (opts.noLintStaged && filename === LINTSTAGED_FILE) continue;
|
|
1132
1204
|
const destPath = path4.join(cwd, filename);
|
|
1133
1205
|
const exists = fileExists(destPath);
|
|
1134
1206
|
if (exists && !opts.force) {
|
|
@@ -1249,6 +1321,9 @@ function mergeTemplateIntoProject(templatePkg, projectPkg, pm, opts, result) {
|
|
|
1249
1321
|
for (const [dep, version] of Object.entries(templatePkg.devDependencies)) {
|
|
1250
1322
|
if (opts.noStylelint && STYLELINT_DEPS.has(dep)) continue;
|
|
1251
1323
|
if (opts.noEditorconfig && dep.includes("editorconfig")) continue;
|
|
1324
|
+
if (opts.noCspell && dep === "cspell") continue;
|
|
1325
|
+
if (opts.noHusky && HUSKY_DEPS.has(dep)) continue;
|
|
1326
|
+
if (opts.noLintStaged && LINTSTAGED_DEPS.has(dep)) continue;
|
|
1252
1327
|
if (existingDeps[dep] === void 0 && version !== "<latest>") {
|
|
1253
1328
|
newDeps[dep] = version;
|
|
1254
1329
|
}
|
|
@@ -1261,7 +1336,9 @@ function mergeTemplateIntoProject(templatePkg, projectPkg, pm, opts, result) {
|
|
|
1261
1336
|
const filteredScripts = filterScripts(
|
|
1262
1337
|
templatePkg.scripts,
|
|
1263
1338
|
opts.noStylelint,
|
|
1264
|
-
opts.noEditorconfig
|
|
1339
|
+
opts.noEditorconfig,
|
|
1340
|
+
opts.noCspell,
|
|
1341
|
+
opts.noLintStaged
|
|
1265
1342
|
);
|
|
1266
1343
|
for (const [key, value] of Object.entries(filteredScripts)) {
|
|
1267
1344
|
const resolved = value.replace(/<pm>/g, prefix);
|
|
@@ -1299,15 +1376,21 @@ function filterStylelintSettings(settings) {
|
|
|
1299
1376
|
}
|
|
1300
1377
|
return filtered;
|
|
1301
1378
|
}
|
|
1302
|
-
function filterScripts(scripts, noStylelint, noEditorconfig) {
|
|
1379
|
+
function filterScripts(scripts, noStylelint, noEditorconfig, noCspell, noLintStaged = false) {
|
|
1303
1380
|
const filtered = {};
|
|
1304
1381
|
for (const [key, value] of Object.entries(scripts)) {
|
|
1305
1382
|
if (noStylelint && key.includes("stylelint")) continue;
|
|
1306
1383
|
if (noEditorconfig && key.includes("editorconfig")) continue;
|
|
1384
|
+
if (noCspell && key.includes("cspell")) continue;
|
|
1385
|
+
if (noLintStaged && key.includes("lint-staged")) continue;
|
|
1307
1386
|
let resolved = value;
|
|
1308
1387
|
if (noStylelint) {
|
|
1309
1388
|
resolved = resolved.replace(/\s*&&\s*stylelint\s+"[^"]*".*/g, "");
|
|
1310
1389
|
}
|
|
1390
|
+
if (noCspell) {
|
|
1391
|
+
resolved = resolved.replace(/\s*&&\s*cspell\s+[^&]*/g, "");
|
|
1392
|
+
resolved = resolved.replace(/(\S)&&/g, "$1 &&");
|
|
1393
|
+
}
|
|
1311
1394
|
filtered[key] = resolved;
|
|
1312
1395
|
}
|
|
1313
1396
|
return filtered;
|
|
@@ -1322,9 +1405,15 @@ function detectPresetCapabilities(presetName) {
|
|
|
1322
1405
|
const hasStylelintDep = pkg?.devDependencies ? Object.keys(pkg.devDependencies).some((d) => isNotStylelintDep(d) === false) : false;
|
|
1323
1406
|
const hasEditorconfigFile = entries.includes(EDITORCONFIG_FILE);
|
|
1324
1407
|
const hasEditorconfigDep = pkg?.devDependencies ? Object.keys(pkg.devDependencies).some((d) => !isNotEditorconfigDep(d)) : false;
|
|
1408
|
+
const hasCspellFile = entries.includes(CSPELL_FILE);
|
|
1409
|
+
const hasCspellDep = pkg?.devDependencies ? Object.keys(pkg.devDependencies).some((d) => d === "cspell") : false;
|
|
1410
|
+
const hasLintStagedFile = entries.includes(LINTSTAGED_FILE);
|
|
1411
|
+
const hasLintStagedDep = pkg?.devDependencies ? Object.keys(pkg.devDependencies).some((d) => isNotLintStagedDep(d) === false) : false;
|
|
1325
1412
|
return {
|
|
1326
1413
|
hasStylelint: hasStylelintFile || hasStylelintDep,
|
|
1327
|
-
hasEditorconfig: hasEditorconfigFile || hasEditorconfigDep
|
|
1414
|
+
hasEditorconfig: hasEditorconfigFile || hasEditorconfigDep,
|
|
1415
|
+
hasCspell: hasCspellFile || hasCspellDep,
|
|
1416
|
+
hasLintStaged: hasLintStagedFile || hasLintStagedDep
|
|
1328
1417
|
};
|
|
1329
1418
|
}
|
|
1330
1419
|
function isNotStylelintDep(dep) {
|
|
@@ -1335,6 +1424,9 @@ function isNotStylelintDep(dep) {
|
|
|
1335
1424
|
function isNotEditorconfigDep(dep) {
|
|
1336
1425
|
return !dep.includes("editorconfig");
|
|
1337
1426
|
}
|
|
1427
|
+
function isNotLintStagedDep(dep) {
|
|
1428
|
+
return dep !== "lint-staged";
|
|
1429
|
+
}
|
|
1338
1430
|
function resolveLocalDeps(deps) {
|
|
1339
1431
|
const packages = [];
|
|
1340
1432
|
for (const [name, version] of Object.entries(deps)) {
|
|
@@ -1356,9 +1448,18 @@ function isNotStylelintDep2(dep) {
|
|
|
1356
1448
|
function isNotEditorconfigDep2(dep) {
|
|
1357
1449
|
return !dep.includes("editorconfig");
|
|
1358
1450
|
}
|
|
1451
|
+
function isNotCspellDep(dep) {
|
|
1452
|
+
return dep !== "cspell";
|
|
1453
|
+
}
|
|
1454
|
+
function isNotHuskyDep(dep) {
|
|
1455
|
+
return dep !== "husky";
|
|
1456
|
+
}
|
|
1457
|
+
function isNotLintStagedDep2(dep) {
|
|
1458
|
+
return dep !== "lint-staged";
|
|
1459
|
+
}
|
|
1359
1460
|
function registerFmtCommand(program2) {
|
|
1360
1461
|
const fmt = program2.command("fmt").description("Initialize formatting config with preset");
|
|
1361
|
-
fmt.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--no-install", "Skip dependency installation").option("--dry-run", "Preview without writing files").option("--stylelint", "Include Stylelint config generation").option("--editorconfig", "Include EditorConfig config generation").option("--reset", "Reset local preset and re-materialize from built-in").action(
|
|
1462
|
+
fmt.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--no-install", "Skip dependency installation").option("--dry-run", "Preview without writing files").option("--stylelint", "Include Stylelint config generation").option("--editorconfig", "Include EditorConfig config generation").option("--cspell", "Include CSpell config generation").option("--husky", "Initialize husky for Git hooks").option("--lint-staged", "Set up lint-staged (implies --husky)").option("--reset", "Reset local preset and re-materialize from built-in").action(
|
|
1362
1463
|
async (presetName, options) => {
|
|
1363
1464
|
const builtinPreset = FMT_PRESETS.find((p) => p.name === presetName);
|
|
1364
1465
|
const isBuiltin = builtinPreset !== void 0;
|
|
@@ -1424,12 +1525,27 @@ async function executeLocalPath(cwd, presetName, options) {
|
|
|
1424
1525
|
"--editorconfig has no effect: this custom preset has no editorconfig config or dependencies"
|
|
1425
1526
|
);
|
|
1426
1527
|
}
|
|
1528
|
+
if (options.cspell && !caps.hasCspell) {
|
|
1529
|
+
logger.warn(
|
|
1530
|
+
"--cspell has no effect: this custom preset has no cspell config or dependencies"
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
if (options.lintStaged && !caps.hasLintStaged) {
|
|
1534
|
+
logger.warn(
|
|
1535
|
+
"--lint-staged has no effect: this custom preset has no lint-staged config or dependencies"
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1538
|
+
const noHusky = options.husky !== true && options.lintStaged !== true;
|
|
1539
|
+
const noLintStaged = options.lintStaged !== true;
|
|
1427
1540
|
const opts = {
|
|
1428
1541
|
cwd,
|
|
1429
1542
|
force: options.force ?? false,
|
|
1430
1543
|
dryRun: options.dryRun ?? false,
|
|
1431
1544
|
noStylelint: options.stylelint !== true,
|
|
1432
|
-
noEditorconfig: options.editorconfig !== true
|
|
1545
|
+
noEditorconfig: options.editorconfig !== true,
|
|
1546
|
+
noCspell: options.cspell !== true,
|
|
1547
|
+
noHusky,
|
|
1548
|
+
noLintStaged
|
|
1433
1549
|
};
|
|
1434
1550
|
let result;
|
|
1435
1551
|
try {
|
|
@@ -1460,7 +1576,10 @@ async function executeLocalPath(cwd, presetName, options) {
|
|
|
1460
1576
|
const depsToInstall = filterDeps(
|
|
1461
1577
|
Object.keys(templatePkg.devDependencies),
|
|
1462
1578
|
opts.noStylelint,
|
|
1463
|
-
opts.noEditorconfig
|
|
1579
|
+
opts.noEditorconfig,
|
|
1580
|
+
opts.noCspell,
|
|
1581
|
+
opts.noHusky,
|
|
1582
|
+
opts.noLintStaged
|
|
1464
1583
|
);
|
|
1465
1584
|
const projectPkgPath = path5.join(cwd, "package.json");
|
|
1466
1585
|
const projectPkg = readJson(projectPkgPath);
|
|
@@ -1470,6 +1589,9 @@ async function executeLocalPath(cwd, presetName, options) {
|
|
|
1470
1589
|
if (missing.length === 0) return;
|
|
1471
1590
|
if (opts.dryRun) {
|
|
1472
1591
|
logger.log(`[dry-run] Would add to package.json: ${missing.join(", ")}`);
|
|
1592
|
+
if (!opts.noHusky) {
|
|
1593
|
+
await initHusky(cwd, pm, opts);
|
|
1594
|
+
}
|
|
1473
1595
|
return;
|
|
1474
1596
|
}
|
|
1475
1597
|
if (options.install === false) {
|
|
@@ -1488,6 +1610,9 @@ async function executeLocalPath(cwd, presetName, options) {
|
|
|
1488
1610
|
const message = error instanceof Error ? error.message : String(error);
|
|
1489
1611
|
logger.warn(`Failed to fetch versions: ${message}. You can add dependencies manually.`);
|
|
1490
1612
|
}
|
|
1613
|
+
if (!opts.noHusky) {
|
|
1614
|
+
await initHusky(cwd, pm, opts);
|
|
1615
|
+
}
|
|
1491
1616
|
return;
|
|
1492
1617
|
}
|
|
1493
1618
|
try {
|
|
@@ -1503,15 +1628,23 @@ async function executeLocalPath(cwd, presetName, options) {
|
|
|
1503
1628
|
const message = error instanceof Error ? error.message : String(error);
|
|
1504
1629
|
logger.warn(`Dependency installation failed: ${message}. You can install manually.`);
|
|
1505
1630
|
}
|
|
1631
|
+
if (!opts.noHusky) {
|
|
1632
|
+
await initHusky(cwd, pm, opts);
|
|
1633
|
+
}
|
|
1506
1634
|
}
|
|
1507
1635
|
async function executeBuiltinPath(cwd, presetName, preset, options) {
|
|
1508
1636
|
const pm = fileExists(path5.join(cwd, "package.json")) ? detectPackageManager(cwd) : void 0;
|
|
1637
|
+
const noHusky = options.husky !== true && options.lintStaged !== true;
|
|
1638
|
+
const noLintStaged = options.lintStaged !== true;
|
|
1509
1639
|
const opts = {
|
|
1510
1640
|
cwd,
|
|
1511
1641
|
force: options.force ?? false,
|
|
1512
1642
|
dryRun: options.dryRun ?? false,
|
|
1513
1643
|
noStylelint: options.stylelint !== true,
|
|
1514
1644
|
noEditorconfig: options.editorconfig !== true,
|
|
1645
|
+
noCspell: options.cspell !== true,
|
|
1646
|
+
noHusky,
|
|
1647
|
+
noLintStaged,
|
|
1515
1648
|
lockfile: pm ? getLockfileName(pm) : void 0
|
|
1516
1649
|
};
|
|
1517
1650
|
const result = generateAllFmt(preset, opts);
|
|
@@ -1528,15 +1661,27 @@ async function executeBuiltinPath(cwd, presetName, preset, options) {
|
|
|
1528
1661
|
warnMissingPackageJson(preset, options.install !== false);
|
|
1529
1662
|
return;
|
|
1530
1663
|
}
|
|
1531
|
-
const scripts = preset.scripts ? filterScripts(
|
|
1664
|
+
const scripts = preset.scripts ? filterScripts(
|
|
1665
|
+
preset.scripts,
|
|
1666
|
+
opts.noStylelint,
|
|
1667
|
+
opts.noEditorconfig,
|
|
1668
|
+
opts.noCspell,
|
|
1669
|
+
opts.noLintStaged
|
|
1670
|
+
) : void 0;
|
|
1532
1671
|
if (scripts) {
|
|
1533
1672
|
await injectScripts(scripts, opts, pm);
|
|
1534
1673
|
}
|
|
1535
1674
|
if (!preset.dependencies?.dev) return;
|
|
1536
1675
|
const devDeps = opts.noStylelint ? preset.dependencies.dev.filter(isNotStylelintDep2) : preset.dependencies.dev;
|
|
1537
|
-
const
|
|
1676
|
+
const noEditorconfigDeps = opts.noEditorconfig ? devDeps.filter(isNotEditorconfigDep2) : devDeps;
|
|
1677
|
+
const noCspellDeps = opts.noCspell ? noEditorconfigDeps.filter(isNotCspellDep) : noEditorconfigDeps;
|
|
1678
|
+
const noHuskyDeps = opts.noHusky ? noCspellDeps.filter(isNotHuskyDep) : noCspellDeps;
|
|
1679
|
+
const finalDeps = opts.noLintStaged ? noHuskyDeps.filter(isNotLintStagedDep2) : noHuskyDeps;
|
|
1538
1680
|
if (opts.dryRun) {
|
|
1539
1681
|
logger.log(`[dry-run] Would add to package.json: ${finalDeps.join(", ")}`);
|
|
1682
|
+
if (!opts.noHusky) {
|
|
1683
|
+
await initHusky(cwd, pm, opts);
|
|
1684
|
+
}
|
|
1540
1685
|
return;
|
|
1541
1686
|
}
|
|
1542
1687
|
if (options.install === false) {
|
|
@@ -1551,6 +1696,9 @@ async function executeBuiltinPath(cwd, presetName, preset, options) {
|
|
|
1551
1696
|
const message = error instanceof Error ? error.message : String(error);
|
|
1552
1697
|
logger.warn(`Failed to fetch versions: ${message}. You can add dependencies manually.`);
|
|
1553
1698
|
}
|
|
1699
|
+
if (!opts.noHusky) {
|
|
1700
|
+
await initHusky(cwd, pm, opts);
|
|
1701
|
+
}
|
|
1554
1702
|
return;
|
|
1555
1703
|
}
|
|
1556
1704
|
try {
|
|
@@ -1561,11 +1709,17 @@ async function executeBuiltinPath(cwd, presetName, preset, options) {
|
|
|
1561
1709
|
const message = error instanceof Error ? error.message : String(error);
|
|
1562
1710
|
logger.warn(`Dependency installation failed: ${message}. You can install manually.`);
|
|
1563
1711
|
}
|
|
1712
|
+
if (!opts.noHusky) {
|
|
1713
|
+
await initHusky(cwd, pm, opts);
|
|
1714
|
+
}
|
|
1564
1715
|
}
|
|
1565
|
-
function filterDeps(deps, noStylelint, noEditorconfig) {
|
|
1716
|
+
function filterDeps(deps, noStylelint, noEditorconfig, noCspell, noHusky, noLintStaged) {
|
|
1566
1717
|
let filtered = deps;
|
|
1567
1718
|
if (noStylelint) filtered = filtered.filter(isNotStylelintDep2);
|
|
1568
1719
|
if (noEditorconfig) filtered = filtered.filter(isNotEditorconfigDep2);
|
|
1720
|
+
if (noCspell) filtered = filtered.filter(isNotCspellDep);
|
|
1721
|
+
if (noHusky) filtered = filtered.filter(isNotHuskyDep);
|
|
1722
|
+
if (noLintStaged) filtered = filtered.filter(isNotLintStagedDep2);
|
|
1569
1723
|
return filtered;
|
|
1570
1724
|
}
|
|
1571
1725
|
function logGenerationResult(result, dryRun) {
|
|
@@ -1628,6 +1782,8 @@ function summarizeFiles(filenames) {
|
|
|
1628
1782
|
else if (name.includes("stylelint")) categories.add("stylelint");
|
|
1629
1783
|
else if (name.includes("cspell")) categories.add("cspell");
|
|
1630
1784
|
else if (name.includes("editorconfig")) categories.add("editorconfig");
|
|
1785
|
+
else if (name.includes("husky")) categories.add("husky");
|
|
1786
|
+
else if (name.includes("lintstagedrc")) categories.add("lint-staged");
|
|
1631
1787
|
}
|
|
1632
1788
|
return [...categories].join(", ");
|
|
1633
1789
|
}
|
|
@@ -1666,6 +1822,58 @@ async function injectScripts(scripts, opts, pm) {
|
|
|
1666
1822
|
);
|
|
1667
1823
|
}
|
|
1668
1824
|
}
|
|
1825
|
+
async function initHusky(cwd, pm, opts) {
|
|
1826
|
+
const pkgPath = path5.join(cwd, "package.json");
|
|
1827
|
+
const pkg = readJson(pkgPath);
|
|
1828
|
+
if (!pkg) {
|
|
1829
|
+
logger.warn("package.json not found, skipping husky setup");
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
const prefix = getRunPrefix(pm);
|
|
1833
|
+
const isYarn = pm === "yarn";
|
|
1834
|
+
const initScriptName = isYarn ? "postinstall" : "prepare";
|
|
1835
|
+
const hookCommand = opts.noLintStaged ? `${prefix} lint` : `${prefix} lint-staged`;
|
|
1836
|
+
const huskyDir = path5.join(cwd, ".husky");
|
|
1837
|
+
const preCommitPath = path5.join(huskyDir, "pre-commit");
|
|
1838
|
+
if (opts.dryRun) {
|
|
1839
|
+
logger.log(`[dry-run] Would create .husky/pre-commit with: ${hookCommand}`);
|
|
1840
|
+
logger.log(`[dry-run] Would inject "${initScriptName}": "husky" script`);
|
|
1841
|
+
logger.log(`[dry-run] Would run ${prefix} ${initScriptName}`);
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
if (fileExists(preCommitPath) && !opts.force) {
|
|
1845
|
+
logger.log("Skipped .husky/pre-commit (already exists)");
|
|
1846
|
+
} else {
|
|
1847
|
+
ensureDir(huskyDir);
|
|
1848
|
+
writeFile(preCommitPath, `${hookCommand}
|
|
1849
|
+
`);
|
|
1850
|
+
fs3.chmodSync(preCommitPath, 493);
|
|
1851
|
+
}
|
|
1852
|
+
const scripts = pkg.scripts ?? {};
|
|
1853
|
+
if (scripts[initScriptName] !== void 0 && !opts.force) {
|
|
1854
|
+
logger.log(`Skipped script "${initScriptName}" (already exists)`);
|
|
1855
|
+
} else {
|
|
1856
|
+
scripts[initScriptName] = "husky";
|
|
1857
|
+
pkg.scripts = scripts;
|
|
1858
|
+
writeJson(pkgPath, pkg);
|
|
1859
|
+
logger.log(`Injected "${initScriptName}" script for husky`);
|
|
1860
|
+
}
|
|
1861
|
+
logger.log(`Running ${prefix} ${initScriptName} to initialize git hooks...`);
|
|
1862
|
+
try {
|
|
1863
|
+
const args = isYarn ? ["postinstall"] : ["run", initScriptName];
|
|
1864
|
+
const { exitCode } = await execFileNoThrow(pm, args, { cwd });
|
|
1865
|
+
if (exitCode === 0) {
|
|
1866
|
+
logger.success("Husky initialized successfully");
|
|
1867
|
+
} else {
|
|
1868
|
+
logger.warn(`Husky init script exited with code ${exitCode}`);
|
|
1869
|
+
}
|
|
1870
|
+
} catch (error) {
|
|
1871
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1872
|
+
logger.warn(
|
|
1873
|
+
`Husky init failed: ${message}. You can run "${prefix} ${initScriptName}" manually.`
|
|
1874
|
+
);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1669
1877
|
|
|
1670
1878
|
// src/commands/init.ts
|
|
1671
1879
|
import { select, isCancel, cancel, outro } from "@clack/prompts";
|
|
@@ -2524,7 +2732,10 @@ function materializeAllPresets() {
|
|
|
2524
2732
|
force: false,
|
|
2525
2733
|
dryRun: false,
|
|
2526
2734
|
noStylelint: false,
|
|
2527
|
-
noEditorconfig: false
|
|
2735
|
+
noEditorconfig: false,
|
|
2736
|
+
noCspell: false,
|
|
2737
|
+
noHusky: false,
|
|
2738
|
+
noLintStaged: false
|
|
2528
2739
|
};
|
|
2529
2740
|
for (const preset of FMT_PRESETS) {
|
|
2530
2741
|
materializeFmtPreset(preset.name, preset, opts);
|
|
@@ -2786,7 +2997,10 @@ function executeVscodeLocalPath(cwd, presetName, options) {
|
|
|
2786
2997
|
force: options.force ?? false,
|
|
2787
2998
|
dryRun: options.dryRun ?? false,
|
|
2788
2999
|
noStylelint: options.stylelint !== true,
|
|
2789
|
-
noEditorconfig: false
|
|
3000
|
+
noEditorconfig: false,
|
|
3001
|
+
noCspell: false,
|
|
3002
|
+
noHusky: true,
|
|
3003
|
+
noLintStaged: true
|
|
2790
3004
|
};
|
|
2791
3005
|
const result = applyLocalVscodePreset(cwd, presetName, opts);
|
|
2792
3006
|
const files = [...result.created, ...result.overwritten];
|
|
@@ -2806,7 +3020,10 @@ function executeVscodeBuiltinPath(cwd, presetName, preset, options) {
|
|
|
2806
3020
|
force: options.force ?? false,
|
|
2807
3021
|
dryRun: options.dryRun ?? false,
|
|
2808
3022
|
noStylelint: options.stylelint !== true,
|
|
2809
|
-
noEditorconfig: false
|
|
3023
|
+
noEditorconfig: false,
|
|
3024
|
+
noCspell: false,
|
|
3025
|
+
noHusky: true,
|
|
3026
|
+
noLintStaged: true
|
|
2810
3027
|
};
|
|
2811
3028
|
const result = generateAllVscode(preset, opts);
|
|
2812
3029
|
const files = [...result.created, ...result.overwritten];
|