@luxkit/cli 1.1.0 → 1.1.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/README.md +7 -0
- package/dist/index.js +583 -131
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ lux fmt <preset> [options]
|
|
|
111
111
|
--dry-run Preview without writing files
|
|
112
112
|
--stylelint Include Stylelint config generation (opt-in)
|
|
113
113
|
--editorconfig Include EditorConfig config generation (opt-in)
|
|
114
|
+
--reset Reset local preset and re-create from built-in defaults
|
|
114
115
|
```
|
|
115
116
|
|
|
116
117
|
<br />
|
|
@@ -124,6 +125,12 @@ lux fmt web-vue
|
|
|
124
125
|
Parse CLI args ──► Resolve preset (fuzzy match on typo)
|
|
125
126
|
│
|
|
126
127
|
▼
|
|
128
|
+
Local preset exists in ~/.lux/preset/?
|
|
129
|
+
│
|
|
130
|
+
├── Yes ──► Copy files from local preset (editable, survives updates)
|
|
131
|
+
└── No ──► Generate from built-in ──► Save to ~/.lux/preset/ for reuse
|
|
132
|
+
│
|
|
133
|
+
▼
|
|
127
134
|
For each config file:
|
|
128
135
|
│
|
|
129
136
|
├── File not found? ──► Create
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
import { program } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/fmt.ts
|
|
7
|
-
import
|
|
7
|
+
import fs3 from "fs";
|
|
8
|
+
import path5 from "path";
|
|
8
9
|
|
|
9
10
|
// src/presets/fmt/electron-vue.ts
|
|
10
11
|
var electronVueFmt = {
|
|
@@ -979,6 +980,347 @@ async function installDevDeps(packages, cwd, pm) {
|
|
|
979
980
|
}
|
|
980
981
|
}
|
|
981
982
|
|
|
983
|
+
// src/core/local-preset.ts
|
|
984
|
+
import fs2 from "fs";
|
|
985
|
+
import os from "os";
|
|
986
|
+
import path4 from "path";
|
|
987
|
+
|
|
988
|
+
// src/core/merge-settings.ts
|
|
989
|
+
var USER_PRIORITY_KEYS = /* @__PURE__ */ new Set([
|
|
990
|
+
// Cursor/animation
|
|
991
|
+
"editor.cursorBlinking",
|
|
992
|
+
"editor.cursorSmoothCaretAnimation",
|
|
993
|
+
"editor.renderWhitespace",
|
|
994
|
+
"editor.guides.indentation",
|
|
995
|
+
"editor.largeFileOptimizations",
|
|
996
|
+
// Theme/appearance
|
|
997
|
+
"workbench.iconTheme",
|
|
998
|
+
"workbench.colorTheme",
|
|
999
|
+
// Suggestions
|
|
1000
|
+
"editor.inlineSuggest.enabled",
|
|
1001
|
+
"editor.suggestSelection",
|
|
1002
|
+
"editor.acceptSuggestionOnEnter",
|
|
1003
|
+
"editor.bracketPairColorization.enabled",
|
|
1004
|
+
"editor.autoClosingBrackets",
|
|
1005
|
+
"editor.autoClosingOvertype"
|
|
1006
|
+
]);
|
|
1007
|
+
function mergeVscodeSettings(preset, existing) {
|
|
1008
|
+
const result = { ...existing };
|
|
1009
|
+
for (const [key, presetVal] of Object.entries(preset)) {
|
|
1010
|
+
const existingVal = existing[key];
|
|
1011
|
+
if (existingVal === void 0) {
|
|
1012
|
+
result[key] = presetVal;
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
if (USER_PRIORITY_KEYS.has(key)) {
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
if (isPlainObject(presetVal) && isPlainObject(existingVal)) {
|
|
1019
|
+
result[key] = mergeVscodeSettings(
|
|
1020
|
+
presetVal,
|
|
1021
|
+
existingVal
|
|
1022
|
+
);
|
|
1023
|
+
continue;
|
|
1024
|
+
}
|
|
1025
|
+
result[key] = presetVal;
|
|
1026
|
+
}
|
|
1027
|
+
return result;
|
|
1028
|
+
}
|
|
1029
|
+
function isPlainObject(val) {
|
|
1030
|
+
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// src/core/local-preset.ts
|
|
1034
|
+
var CONFIG_GETTERS = [
|
|
1035
|
+
{ filename: "eslint.config.mjs", getContent: (p) => p.eslint?.() },
|
|
1036
|
+
{ filename: ".prettierrc", getContent: (p) => p.prettier?.() },
|
|
1037
|
+
{ filename: ".prettierignore", getContent: (p) => p.prettierIgnore?.() },
|
|
1038
|
+
{ filename: "stylelint.config.mjs", getContent: (p) => p.stylelint?.() },
|
|
1039
|
+
{ filename: ".stylelintignore", getContent: (p) => p.stylelintIgnore?.() },
|
|
1040
|
+
{ filename: "cspell.json", getContent: (p) => p.cspell?.() },
|
|
1041
|
+
{ filename: ".editorconfig", getContent: (p) => p.editorconfig?.() }
|
|
1042
|
+
];
|
|
1043
|
+
var STYLELINT_FILES = /* @__PURE__ */ new Set(["stylelint.config.mjs", ".stylelintignore"]);
|
|
1044
|
+
var EDITORCONFIG_FILE = ".editorconfig";
|
|
1045
|
+
var STYLELINT_SETTINGS_PREFIXES = [
|
|
1046
|
+
"stylelint.",
|
|
1047
|
+
"css.validate",
|
|
1048
|
+
"less.validate",
|
|
1049
|
+
"scss.validate"
|
|
1050
|
+
];
|
|
1051
|
+
var STYLELINT_DEPS = /* @__PURE__ */ new Set([
|
|
1052
|
+
"stylelint",
|
|
1053
|
+
"stylelint-config-standard-scss",
|
|
1054
|
+
"stylelint-order",
|
|
1055
|
+
"stylelint-scss",
|
|
1056
|
+
"@stylistic/stylelint-plugin",
|
|
1057
|
+
"postcss-html",
|
|
1058
|
+
"postcss-scss"
|
|
1059
|
+
]);
|
|
1060
|
+
var STYLELINT_EXTENSION = "stylelint.vscode-stylelint";
|
|
1061
|
+
function getLuxDir() {
|
|
1062
|
+
return process.env.LUX_HOME || path4.join(os.homedir(), ".lux");
|
|
1063
|
+
}
|
|
1064
|
+
function getLocalPresetDir(type, presetName) {
|
|
1065
|
+
if (!isValidPresetName(presetName)) {
|
|
1066
|
+
throw new Error(`Invalid preset name: "${presetName}"`);
|
|
1067
|
+
}
|
|
1068
|
+
return path4.join(getLuxDir(), "preset", type, presetName);
|
|
1069
|
+
}
|
|
1070
|
+
function isValidPresetName(name) {
|
|
1071
|
+
return name.length > 0 && !name.includes("/") && !name.includes("\\") && !name.includes("..");
|
|
1072
|
+
}
|
|
1073
|
+
function localPresetExists(type, presetName) {
|
|
1074
|
+
const dir = getLocalPresetDir(type, presetName);
|
|
1075
|
+
return fs2.existsSync(dir);
|
|
1076
|
+
}
|
|
1077
|
+
function resetLocalPreset(type, presetName) {
|
|
1078
|
+
const dir = getLocalPresetDir(type, presetName);
|
|
1079
|
+
if (fs2.existsSync(dir)) {
|
|
1080
|
+
fs2.rmSync(dir, { recursive: true, force: true });
|
|
1081
|
+
logger.log(`Reset local preset: ${dir}`);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
function materializeFmtPreset(presetName, preset, opts) {
|
|
1085
|
+
if (opts.dryRun) {
|
|
1086
|
+
logger.log("[dry-run] Would materialize local preset to ~/.lux/preset/fmt/" + presetName);
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
const presetDir = getLocalPresetDir("fmt", presetName);
|
|
1090
|
+
ensureDir(presetDir);
|
|
1091
|
+
for (const { filename, getContent } of CONFIG_GETTERS) {
|
|
1092
|
+
const content = getContent(preset);
|
|
1093
|
+
if (content === void 0) continue;
|
|
1094
|
+
const resolved = opts.lockfile ? content.replace(/<lockfile>/g, opts.lockfile) : content.replace(/<lockfile>\n?/g, "");
|
|
1095
|
+
writeFile(path4.join(presetDir, filename), resolved);
|
|
1096
|
+
}
|
|
1097
|
+
const templatePkg = buildTemplatePackageJson(preset);
|
|
1098
|
+
writeJson(path4.join(presetDir, "package.json"), templatePkg);
|
|
1099
|
+
logger.log(`Local preset created at ${presetDir}`);
|
|
1100
|
+
}
|
|
1101
|
+
function materializeVscodePreset(cwd, presetName) {
|
|
1102
|
+
const presetDir = getLocalPresetDir("vscode", presetName);
|
|
1103
|
+
ensureDir(presetDir);
|
|
1104
|
+
const settingsSrc = path4.join(cwd, ".vscode", "settings.json");
|
|
1105
|
+
if (fileExists(settingsSrc)) {
|
|
1106
|
+
const content = fs2.readFileSync(settingsSrc, "utf-8");
|
|
1107
|
+
writeFile(path4.join(presetDir, "settings.json"), content);
|
|
1108
|
+
}
|
|
1109
|
+
const extensionsSrc = path4.join(cwd, ".vscode", "extensions.json");
|
|
1110
|
+
if (fileExists(extensionsSrc)) {
|
|
1111
|
+
const content = fs2.readFileSync(extensionsSrc, "utf-8");
|
|
1112
|
+
writeFile(path4.join(presetDir, "extensions.json"), content);
|
|
1113
|
+
}
|
|
1114
|
+
logger.log(`Local preset created at ${presetDir}`);
|
|
1115
|
+
}
|
|
1116
|
+
var InvalidPackageJsonError = class extends Error {
|
|
1117
|
+
constructor(filePath) {
|
|
1118
|
+
super(`package.json exists but is not valid JSON: ${filePath}`);
|
|
1119
|
+
this.filePath = filePath;
|
|
1120
|
+
}
|
|
1121
|
+
filePath;
|
|
1122
|
+
};
|
|
1123
|
+
function applyLocalFmtPreset(cwd, presetName, opts) {
|
|
1124
|
+
const result = {
|
|
1125
|
+
created: [],
|
|
1126
|
+
overwritten: [],
|
|
1127
|
+
skipped: [],
|
|
1128
|
+
scriptsAdded: 0,
|
|
1129
|
+
scriptsSkipped: 0
|
|
1130
|
+
};
|
|
1131
|
+
const presetDir = getLocalPresetDir("fmt", presetName);
|
|
1132
|
+
if (!fs2.existsSync(presetDir)) {
|
|
1133
|
+
logger.warn(`Local preset not found at ${presetDir}`);
|
|
1134
|
+
return result;
|
|
1135
|
+
}
|
|
1136
|
+
const projectPkgPath = path4.join(cwd, "package.json");
|
|
1137
|
+
if (fileExists(projectPkgPath)) {
|
|
1138
|
+
try {
|
|
1139
|
+
JSON.parse(fs2.readFileSync(projectPkgPath, "utf-8"));
|
|
1140
|
+
} catch {
|
|
1141
|
+
throw new InvalidPackageJsonError(projectPkgPath);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
const entries = fs2.readdirSync(presetDir).filter((name) => name !== "package.json" && fs2.statSync(path4.join(presetDir, name)).isFile());
|
|
1145
|
+
for (const filename of entries) {
|
|
1146
|
+
if (opts.noStylelint && STYLELINT_FILES.has(filename)) continue;
|
|
1147
|
+
if (opts.noEditorconfig && filename === EDITORCONFIG_FILE) continue;
|
|
1148
|
+
const destPath = path4.join(cwd, filename);
|
|
1149
|
+
const exists = fileExists(destPath);
|
|
1150
|
+
if (exists && !opts.force) {
|
|
1151
|
+
result.skipped.push(filename);
|
|
1152
|
+
if (opts.dryRun) {
|
|
1153
|
+
logger.log(`[dry-run] Skipped ${filename} (already exists)`);
|
|
1154
|
+
}
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1157
|
+
if (opts.dryRun) {
|
|
1158
|
+
(exists ? result.overwritten : result.created).push(filename);
|
|
1159
|
+
logger.log(`[dry-run] Would copy ${filename} from local preset`);
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
const content = fs2.readFileSync(path4.join(presetDir, filename), "utf-8");
|
|
1163
|
+
writeFile(destPath, content);
|
|
1164
|
+
(exists ? result.overwritten : result.created).push(filename);
|
|
1165
|
+
}
|
|
1166
|
+
const templatePkg = readJson(path4.join(presetDir, "package.json"));
|
|
1167
|
+
const projectPkg = readJson(projectPkgPath);
|
|
1168
|
+
if (templatePkg && projectPkg) {
|
|
1169
|
+
const pm = fileExists(path4.join(cwd, "package.json")) ? detectPackageManager(cwd) : void 0;
|
|
1170
|
+
const merged = mergeTemplateIntoProject(templatePkg, projectPkg, pm, opts, result);
|
|
1171
|
+
if (!opts.dryRun) {
|
|
1172
|
+
writeJson(projectPkgPath, merged);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return result;
|
|
1176
|
+
}
|
|
1177
|
+
function applyLocalVscodePreset(cwd, presetName, opts) {
|
|
1178
|
+
const result = {
|
|
1179
|
+
created: [],
|
|
1180
|
+
overwritten: [],
|
|
1181
|
+
skipped: [],
|
|
1182
|
+
scriptsAdded: 0,
|
|
1183
|
+
scriptsSkipped: 0
|
|
1184
|
+
};
|
|
1185
|
+
const presetDir = getLocalPresetDir("vscode", presetName);
|
|
1186
|
+
if (!fs2.existsSync(presetDir)) {
|
|
1187
|
+
logger.warn(`Local preset not found at ${presetDir}`);
|
|
1188
|
+
return result;
|
|
1189
|
+
}
|
|
1190
|
+
const settingsSrc = path4.join(presetDir, "settings.json");
|
|
1191
|
+
if (fileExists(settingsSrc)) {
|
|
1192
|
+
const presetSettings = readJson(settingsSrc);
|
|
1193
|
+
const filteredSettings = opts.noStylelint ? filterStylelintSettings(presetSettings ?? {}) : presetSettings;
|
|
1194
|
+
if (filteredSettings) {
|
|
1195
|
+
const settingsDest = path4.join(cwd, ".vscode", "settings.json");
|
|
1196
|
+
const existingSettings = readJson(settingsDest);
|
|
1197
|
+
if (existingSettings) {
|
|
1198
|
+
if (opts.dryRun) {
|
|
1199
|
+
result.overwritten.push(".vscode/settings.json");
|
|
1200
|
+
logger.log("[dry-run] Would merge .vscode/settings.json from local preset");
|
|
1201
|
+
} else {
|
|
1202
|
+
const merged = mergeVscodeSettings(filteredSettings, existingSettings);
|
|
1203
|
+
writeJson(settingsDest, merged);
|
|
1204
|
+
result.overwritten.push(".vscode/settings.json");
|
|
1205
|
+
}
|
|
1206
|
+
} else {
|
|
1207
|
+
if (opts.dryRun) {
|
|
1208
|
+
result.created.push(".vscode/settings.json");
|
|
1209
|
+
logger.log("[dry-run] Would create .vscode/settings.json from local preset");
|
|
1210
|
+
} else {
|
|
1211
|
+
writeJson(settingsDest, filteredSettings);
|
|
1212
|
+
result.created.push(".vscode/settings.json");
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
const extensionsSrc = path4.join(presetDir, "extensions.json");
|
|
1218
|
+
if (fileExists(extensionsSrc)) {
|
|
1219
|
+
const extensionsData = readJson(extensionsSrc);
|
|
1220
|
+
if (extensionsData) {
|
|
1221
|
+
let presetRecommendations = extensionsData.recommendations ?? [];
|
|
1222
|
+
if (opts.noStylelint) {
|
|
1223
|
+
presetRecommendations = presetRecommendations.filter((ext) => ext !== STYLELINT_EXTENSION);
|
|
1224
|
+
}
|
|
1225
|
+
if (opts.dryRun) {
|
|
1226
|
+
result.created.push(".vscode/extensions.json");
|
|
1227
|
+
logger.log("[dry-run] Would create .vscode/extensions.json from local preset");
|
|
1228
|
+
} else {
|
|
1229
|
+
const extensionsDest = path4.join(cwd, ".vscode", "extensions.json");
|
|
1230
|
+
const existingExtensions = readJson(extensionsDest);
|
|
1231
|
+
const existingRecommendations = existingExtensions?.recommendations ?? [];
|
|
1232
|
+
const merged = [.../* @__PURE__ */ new Set([...existingRecommendations, ...presetRecommendations])];
|
|
1233
|
+
writeJson(extensionsDest, { recommendations: merged });
|
|
1234
|
+
result.created.push(".vscode/extensions.json");
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
return result;
|
|
1239
|
+
}
|
|
1240
|
+
function buildTemplatePackageJson(preset) {
|
|
1241
|
+
const deps = {};
|
|
1242
|
+
if (preset.dependencies?.dev) {
|
|
1243
|
+
for (const dep of preset.dependencies.dev) {
|
|
1244
|
+
deps[dep] = "<latest>";
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
const scripts = preset.scripts ? { ...preset.scripts } : void 0;
|
|
1248
|
+
const result = {};
|
|
1249
|
+
if (Object.keys(deps).length > 0) {
|
|
1250
|
+
result.devDependencies = deps;
|
|
1251
|
+
}
|
|
1252
|
+
if (scripts && Object.keys(scripts).length > 0) {
|
|
1253
|
+
result.scripts = scripts;
|
|
1254
|
+
}
|
|
1255
|
+
return result;
|
|
1256
|
+
}
|
|
1257
|
+
function mergeTemplateIntoProject(templatePkg, projectPkg, pm, opts, result) {
|
|
1258
|
+
const merged = { ...projectPkg };
|
|
1259
|
+
const prefix = pm ? getRunPrefix(pm) : "";
|
|
1260
|
+
if (templatePkg.devDependencies) {
|
|
1261
|
+
const existingDeps = merged.devDependencies ?? {};
|
|
1262
|
+
const newDeps = { ...existingDeps };
|
|
1263
|
+
for (const [dep, version] of Object.entries(templatePkg.devDependencies)) {
|
|
1264
|
+
if (opts.noStylelint && STYLELINT_DEPS.has(dep)) continue;
|
|
1265
|
+
if (opts.noEditorconfig && dep.includes("editorconfig")) continue;
|
|
1266
|
+
if (existingDeps[dep] === void 0 && version !== "<latest>") {
|
|
1267
|
+
newDeps[dep] = version;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
merged.devDependencies = newDeps;
|
|
1271
|
+
}
|
|
1272
|
+
if (templatePkg.scripts) {
|
|
1273
|
+
const existingScripts = merged.scripts ?? {};
|
|
1274
|
+
const newScripts = { ...existingScripts };
|
|
1275
|
+
for (const [key, value] of Object.entries(templatePkg.scripts)) {
|
|
1276
|
+
if (opts.noStylelint && key.startsWith("stylelint")) continue;
|
|
1277
|
+
const resolved = value.replace(/<pm>/g, prefix);
|
|
1278
|
+
if (existingScripts[key] !== void 0 && !opts.force) {
|
|
1279
|
+
result.scriptsSkipped++;
|
|
1280
|
+
if (opts.dryRun) {
|
|
1281
|
+
logger.log(`[dry-run] Skipped script "${key}" (already exists)`);
|
|
1282
|
+
} else {
|
|
1283
|
+
logger.log(`Skipped script "${key}" (already exists)`);
|
|
1284
|
+
}
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
if (opts.dryRun) {
|
|
1288
|
+
result.scriptsAdded++;
|
|
1289
|
+
logger.log(`[dry-run] Would add script "${key}"`);
|
|
1290
|
+
continue;
|
|
1291
|
+
}
|
|
1292
|
+
newScripts[key] = resolved;
|
|
1293
|
+
result.scriptsAdded++;
|
|
1294
|
+
}
|
|
1295
|
+
merged.scripts = newScripts;
|
|
1296
|
+
}
|
|
1297
|
+
return merged;
|
|
1298
|
+
}
|
|
1299
|
+
function filterStylelintSettings(settings) {
|
|
1300
|
+
const filtered = Object.fromEntries(
|
|
1301
|
+
Object.entries(settings).filter(
|
|
1302
|
+
([key]) => !STYLELINT_SETTINGS_PREFIXES.some((prefix) => key.startsWith(prefix))
|
|
1303
|
+
)
|
|
1304
|
+
);
|
|
1305
|
+
if (typeof filtered["editor.codeActionsOnSave"] === "object" && filtered["editor.codeActionsOnSave"] !== null) {
|
|
1306
|
+
const actions = { ...filtered["editor.codeActionsOnSave"] };
|
|
1307
|
+
delete actions["source.fixAll.stylelint"];
|
|
1308
|
+
filtered["editor.codeActionsOnSave"] = actions;
|
|
1309
|
+
}
|
|
1310
|
+
return filtered;
|
|
1311
|
+
}
|
|
1312
|
+
function resolveLocalDeps(deps) {
|
|
1313
|
+
const packages = [];
|
|
1314
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
1315
|
+
if (version === "<latest>") {
|
|
1316
|
+
packages.push(name);
|
|
1317
|
+
} else {
|
|
1318
|
+
packages.push(`${name}@${version}`);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
return packages;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
982
1324
|
// src/commands/fmt.ts
|
|
983
1325
|
function filterStylelintScripts(scripts) {
|
|
984
1326
|
const filtered = {};
|
|
@@ -998,58 +1340,30 @@ function isNotEditorconfigDep(dep) {
|
|
|
998
1340
|
}
|
|
999
1341
|
function registerFmtCommand(program2) {
|
|
1000
1342
|
const fmt = program2.command("fmt").description("Initialize formatting config with preset");
|
|
1001
|
-
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").action(
|
|
1343
|
+
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(
|
|
1002
1344
|
async (presetName, options) => {
|
|
1003
1345
|
const preset = resolvePreset(FMT_PRESETS, presetName);
|
|
1004
1346
|
if (!preset) return;
|
|
1005
1347
|
const cwd = process.cwd();
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
const result = generateAllFmt(preset, opts);
|
|
1016
|
-
const allFiles = [...result.created, ...result.overwritten];
|
|
1017
|
-
if (allFiles.length === 0 && result.skipped.length === 0) {
|
|
1018
|
-
logger.warn("No files to generate for this preset");
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
logGenerationResult(result, opts.dryRun);
|
|
1022
|
-
if (!pm) {
|
|
1023
|
-
warnMissingPackageJson(preset, options.install !== false);
|
|
1024
|
-
return;
|
|
1025
|
-
}
|
|
1026
|
-
const scripts = opts.noStylelint && preset.scripts ? filterStylelintScripts(preset.scripts) : preset.scripts;
|
|
1027
|
-
if (scripts) {
|
|
1028
|
-
await injectScripts(scripts, opts, pm);
|
|
1029
|
-
}
|
|
1030
|
-
if (!preset.dependencies?.dev) return;
|
|
1031
|
-
const devDeps = opts.noStylelint ? preset.dependencies.dev.filter(isNotStylelintDep) : preset.dependencies.dev;
|
|
1032
|
-
const finalDeps = opts.noEditorconfig ? devDeps.filter(isNotEditorconfigDep) : devDeps;
|
|
1033
|
-
if (options.install === false) {
|
|
1034
|
-
const added = await addDepsToManifest(finalDeps, cwd);
|
|
1035
|
-
if (added.length > 0) {
|
|
1036
|
-
logger.success(`Added to package.json (skipped install): ${added.join(", ")}`);
|
|
1037
|
-
} else {
|
|
1038
|
-
logger.log("All dependencies already in package.json");
|
|
1348
|
+
const pkgPath = path5.join(cwd, "package.json");
|
|
1349
|
+
if (fileExists(pkgPath)) {
|
|
1350
|
+
try {
|
|
1351
|
+
JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
|
|
1352
|
+
} catch {
|
|
1353
|
+
logger.error(
|
|
1354
|
+
"package.json exists but is not valid JSON. Fix it first, then re-run this command."
|
|
1355
|
+
);
|
|
1356
|
+
return;
|
|
1039
1357
|
}
|
|
1040
|
-
return;
|
|
1041
1358
|
}
|
|
1042
|
-
if (
|
|
1043
|
-
|
|
1044
|
-
return;
|
|
1359
|
+
if (options.reset) {
|
|
1360
|
+
resetLocalPreset("fmt", presetName);
|
|
1045
1361
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
await
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1052
|
-
logger.warn(`Dependency installation failed: ${message}. You can install manually.`);
|
|
1362
|
+
const useLocal = localPresetExists("fmt", presetName);
|
|
1363
|
+
if (useLocal) {
|
|
1364
|
+
await executeLocalPath(cwd, presetName, options);
|
|
1365
|
+
} else {
|
|
1366
|
+
await executeBuiltinPath(cwd, presetName, preset, options);
|
|
1053
1367
|
}
|
|
1054
1368
|
}
|
|
1055
1369
|
);
|
|
@@ -1059,6 +1373,139 @@ function registerFmtCommand(program2) {
|
|
|
1059
1373
|
}
|
|
1060
1374
|
});
|
|
1061
1375
|
}
|
|
1376
|
+
async function executeLocalPath(cwd, presetName, options) {
|
|
1377
|
+
logger.log("Using local custom preset");
|
|
1378
|
+
const opts = {
|
|
1379
|
+
cwd,
|
|
1380
|
+
force: options.force ?? false,
|
|
1381
|
+
dryRun: options.dryRun ?? false,
|
|
1382
|
+
noStylelint: options.stylelint !== true,
|
|
1383
|
+
noEditorconfig: options.editorconfig !== true
|
|
1384
|
+
};
|
|
1385
|
+
let result;
|
|
1386
|
+
try {
|
|
1387
|
+
result = applyLocalFmtPreset(cwd, presetName, opts);
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
if (error instanceof InvalidPackageJsonError) {
|
|
1390
|
+
logger.error(
|
|
1391
|
+
"package.json exists but is not valid JSON. Fix it first, then re-run this command."
|
|
1392
|
+
);
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
throw error;
|
|
1396
|
+
}
|
|
1397
|
+
const allFiles = [...result.created, ...result.overwritten];
|
|
1398
|
+
if (allFiles.length > 0 || result.skipped.length > 0) {
|
|
1399
|
+
logApplyResult(result);
|
|
1400
|
+
}
|
|
1401
|
+
if (result.scriptsAdded > 0 || result.scriptsSkipped > 0) {
|
|
1402
|
+
logger.log(
|
|
1403
|
+
`Added ${result.scriptsAdded} script${result.scriptsAdded > 1 ? "s" : ""} to package.json${result.scriptsSkipped > 0 ? ` (${result.scriptsSkipped} skipped)` : ""}`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
const pm = fileExists(path5.join(cwd, "package.json")) ? detectPackageManager(cwd) : void 0;
|
|
1407
|
+
if (!pm) return;
|
|
1408
|
+
const templatePkgPath = path5.join(getLocalPresetDir("fmt", presetName), "package.json");
|
|
1409
|
+
const templatePkg = readJson(templatePkgPath);
|
|
1410
|
+
if (!templatePkg?.devDependencies) return;
|
|
1411
|
+
const depsToInstall = filterDeps(
|
|
1412
|
+
Object.keys(templatePkg.devDependencies),
|
|
1413
|
+
opts.noStylelint,
|
|
1414
|
+
opts.noEditorconfig
|
|
1415
|
+
);
|
|
1416
|
+
const projectPkgPath = path5.join(cwd, "package.json");
|
|
1417
|
+
const projectPkg = readJson(projectPkgPath);
|
|
1418
|
+
if (!projectPkg) return;
|
|
1419
|
+
const existingDeps = projectPkg.devDependencies ?? {};
|
|
1420
|
+
const missing = depsToInstall.filter((dep) => !existingDeps[dep]);
|
|
1421
|
+
if (missing.length === 0) return;
|
|
1422
|
+
if (options.install === false) {
|
|
1423
|
+
const resolved = resolveLocalDeps(templatePkg.devDependencies);
|
|
1424
|
+
const added = await addDepsToManifest(resolved, cwd);
|
|
1425
|
+
if (added.length > 0) {
|
|
1426
|
+
logger.success(`Added to package.json (skipped install): ${added.join(", ")}`);
|
|
1427
|
+
} else {
|
|
1428
|
+
logger.log("All dependencies already in package.json");
|
|
1429
|
+
}
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
if (opts.dryRun) {
|
|
1433
|
+
logger.log(`[dry-run] Would install: ${missing.join(", ")}`);
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
try {
|
|
1437
|
+
logger.log(`Installing dependencies with ${pm}...`);
|
|
1438
|
+
const resolved = resolveLocalDeps(
|
|
1439
|
+
Object.fromEntries(
|
|
1440
|
+
Object.entries(templatePkg.devDependencies).filter(([k]) => missing.includes(k))
|
|
1441
|
+
)
|
|
1442
|
+
);
|
|
1443
|
+
await installDevDeps(resolved, cwd, pm);
|
|
1444
|
+
logger.success("Dependencies installed successfully");
|
|
1445
|
+
} catch (error) {
|
|
1446
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1447
|
+
logger.warn(`Dependency installation failed: ${message}. You can install manually.`);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
async function executeBuiltinPath(cwd, presetName, preset, options) {
|
|
1451
|
+
const pm = fileExists(path5.join(cwd, "package.json")) ? detectPackageManager(cwd) : void 0;
|
|
1452
|
+
const opts = {
|
|
1453
|
+
cwd,
|
|
1454
|
+
force: options.force ?? false,
|
|
1455
|
+
dryRun: options.dryRun ?? false,
|
|
1456
|
+
noStylelint: options.stylelint !== true,
|
|
1457
|
+
noEditorconfig: options.editorconfig !== true,
|
|
1458
|
+
lockfile: pm ? getLockfileName(pm) : void 0
|
|
1459
|
+
};
|
|
1460
|
+
const result = generateAllFmt(preset, opts);
|
|
1461
|
+
const allFiles = [...result.created, ...result.overwritten];
|
|
1462
|
+
if (allFiles.length === 0 && result.skipped.length === 0) {
|
|
1463
|
+
logger.warn("No files to generate for this preset");
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
logGenerationResult(result, opts.dryRun);
|
|
1467
|
+
if (!opts.dryRun) {
|
|
1468
|
+
materializeFmtPreset(presetName, preset, opts);
|
|
1469
|
+
}
|
|
1470
|
+
if (!pm) {
|
|
1471
|
+
warnMissingPackageJson(preset, options.install !== false);
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
const scripts = opts.noStylelint && preset.scripts ? filterStylelintScripts(preset.scripts) : preset.scripts;
|
|
1475
|
+
if (scripts) {
|
|
1476
|
+
await injectScripts(scripts, opts, pm);
|
|
1477
|
+
}
|
|
1478
|
+
if (!preset.dependencies?.dev) return;
|
|
1479
|
+
const devDeps = opts.noStylelint ? preset.dependencies.dev.filter(isNotStylelintDep) : preset.dependencies.dev;
|
|
1480
|
+
const finalDeps = opts.noEditorconfig ? devDeps.filter(isNotEditorconfigDep) : devDeps;
|
|
1481
|
+
if (options.install === false) {
|
|
1482
|
+
const added = await addDepsToManifest(finalDeps, cwd);
|
|
1483
|
+
if (added.length > 0) {
|
|
1484
|
+
logger.success(`Added to package.json (skipped install): ${added.join(", ")}`);
|
|
1485
|
+
} else {
|
|
1486
|
+
logger.log("All dependencies already in package.json");
|
|
1487
|
+
}
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
if (opts.dryRun) {
|
|
1491
|
+
logger.log(`[dry-run] Would install: ${finalDeps.join(", ")}`);
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
try {
|
|
1495
|
+
logger.log(`Installing dependencies with ${pm}...`);
|
|
1496
|
+
await installDevDeps(finalDeps, cwd, pm);
|
|
1497
|
+
logger.success("Dependencies installed successfully");
|
|
1498
|
+
} catch (error) {
|
|
1499
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1500
|
+
logger.warn(`Dependency installation failed: ${message}. You can install manually.`);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
function filterDeps(deps, noStylelint, noEditorconfig) {
|
|
1504
|
+
let filtered = deps;
|
|
1505
|
+
if (noStylelint) filtered = filtered.filter(isNotStylelintDep);
|
|
1506
|
+
if (noEditorconfig) filtered = filtered.filter(isNotEditorconfigDep);
|
|
1507
|
+
return filtered;
|
|
1508
|
+
}
|
|
1062
1509
|
function logGenerationResult(result, dryRun) {
|
|
1063
1510
|
const files = [...result.created, ...result.overwritten];
|
|
1064
1511
|
if (dryRun) {
|
|
@@ -1086,6 +1533,23 @@ function logGenerationResult(result, dryRun) {
|
|
|
1086
1533
|
);
|
|
1087
1534
|
}
|
|
1088
1535
|
}
|
|
1536
|
+
function logApplyResult(result) {
|
|
1537
|
+
if (result.created.length > 0) {
|
|
1538
|
+
logger.log(
|
|
1539
|
+
`Created ${summarizeFiles(result.created)} config ${result.created.length} file${result.created.length > 1 ? "s" : ""} from local preset`
|
|
1540
|
+
);
|
|
1541
|
+
}
|
|
1542
|
+
if (result.overwritten.length > 0) {
|
|
1543
|
+
logger.log(
|
|
1544
|
+
`Overwritten ${summarizeFiles(result.overwritten)} config ${result.overwritten.length} file${result.overwritten.length > 1 ? "s" : ""} from local preset`
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
if (result.skipped.length > 0) {
|
|
1548
|
+
logger.log(
|
|
1549
|
+
`Skipped ${result.skipped.length} file${result.skipped.length > 1 ? "s" : ""} (already exists)`
|
|
1550
|
+
);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1089
1553
|
function warnMissingPackageJson(preset, installEnabled) {
|
|
1090
1554
|
const tasks = [];
|
|
1091
1555
|
if (preset.scripts) tasks.push("script injection");
|
|
@@ -1106,7 +1570,7 @@ function summarizeFiles(filenames) {
|
|
|
1106
1570
|
return [...categories].join(", ");
|
|
1107
1571
|
}
|
|
1108
1572
|
async function injectScripts(scripts, opts, pm) {
|
|
1109
|
-
const pkgPath =
|
|
1573
|
+
const pkgPath = path5.join(opts.cwd, "package.json");
|
|
1110
1574
|
const pkg = readJson(pkgPath);
|
|
1111
1575
|
if (!pkg) {
|
|
1112
1576
|
logger.warn("package.json not found, skipping script injection");
|
|
@@ -1159,18 +1623,18 @@ var INIT_TOOLS = [
|
|
|
1159
1623
|
];
|
|
1160
1624
|
|
|
1161
1625
|
// src/generators/init.ts
|
|
1162
|
-
import
|
|
1163
|
-
import
|
|
1626
|
+
import fs4 from "fs";
|
|
1627
|
+
import path6 from "path";
|
|
1164
1628
|
function resolveSkillsDir() {
|
|
1165
|
-
const entryDir =
|
|
1166
|
-
return
|
|
1629
|
+
const entryDir = path6.dirname(process.argv[1] ?? "");
|
|
1630
|
+
return path6.resolve(entryDir, "skills");
|
|
1167
1631
|
}
|
|
1168
1632
|
function listFilesRecursive(dir, base) {
|
|
1169
|
-
const entries =
|
|
1633
|
+
const entries = fs4.readdirSync(dir, { withFileTypes: true });
|
|
1170
1634
|
const files = [];
|
|
1171
1635
|
for (const entry of entries) {
|
|
1172
1636
|
const childBase = `${base}/${entry.name}`;
|
|
1173
|
-
const fullPath =
|
|
1637
|
+
const fullPath = path6.join(dir, entry.name);
|
|
1174
1638
|
if (entry.isDirectory()) {
|
|
1175
1639
|
files.push(...listFilesRecursive(fullPath, childBase));
|
|
1176
1640
|
} else {
|
|
@@ -1181,20 +1645,20 @@ function listFilesRecursive(dir, base) {
|
|
|
1181
1645
|
}
|
|
1182
1646
|
function generateInitSkills(targetBaseDir, cwd) {
|
|
1183
1647
|
const skillsDir = resolveSkillsDir();
|
|
1184
|
-
if (!
|
|
1648
|
+
if (!fs4.existsSync(skillsDir)) {
|
|
1185
1649
|
logger.error(`Bundled skills directory not found: ${skillsDir}`);
|
|
1186
1650
|
logger.error('Please run "lux build" or reinstall lux.');
|
|
1187
1651
|
return { copiedFiles: [], targetDir: targetBaseDir };
|
|
1188
1652
|
}
|
|
1189
|
-
const targetPath =
|
|
1653
|
+
const targetPath = path6.resolve(cwd, targetBaseDir);
|
|
1190
1654
|
try {
|
|
1191
|
-
|
|
1655
|
+
fs4.cpSync(skillsDir, targetPath, { recursive: true, force: true });
|
|
1192
1656
|
} catch (error) {
|
|
1193
1657
|
const message = error instanceof Error ? error.message : String(error);
|
|
1194
1658
|
logger.error(`Failed to copy skills to ${targetPath}: ${message}`);
|
|
1195
1659
|
return { copiedFiles: [], targetDir: targetBaseDir };
|
|
1196
1660
|
}
|
|
1197
|
-
const copiedFiles =
|
|
1661
|
+
const copiedFiles = fs4.existsSync(targetPath) ? listFilesRecursive(targetPath, targetBaseDir) : [];
|
|
1198
1662
|
return { copiedFiles, targetDir: targetBaseDir };
|
|
1199
1663
|
}
|
|
1200
1664
|
|
|
@@ -1232,18 +1696,18 @@ function registerInitCommand(program2) {
|
|
|
1232
1696
|
}
|
|
1233
1697
|
|
|
1234
1698
|
// src/utils/config.ts
|
|
1235
|
-
import
|
|
1236
|
-
import
|
|
1237
|
-
import
|
|
1699
|
+
import fs5 from "fs";
|
|
1700
|
+
import os2 from "os";
|
|
1701
|
+
import path7 from "path";
|
|
1238
1702
|
var CONFIG_DIR = ".lux";
|
|
1239
1703
|
var ENV_FILE = "env.txt";
|
|
1240
1704
|
function getEnvConfigPath() {
|
|
1241
|
-
return
|
|
1705
|
+
return path7.join(os2.homedir(), CONFIG_DIR, ENV_FILE);
|
|
1242
1706
|
}
|
|
1243
1707
|
function getEnvConfig() {
|
|
1244
1708
|
let content;
|
|
1245
1709
|
try {
|
|
1246
|
-
content =
|
|
1710
|
+
content = fs5.readFileSync(getEnvConfigPath(), "utf-8");
|
|
1247
1711
|
} catch {
|
|
1248
1712
|
return {};
|
|
1249
1713
|
}
|
|
@@ -1266,7 +1730,7 @@ function setEnvConfig(data) {
|
|
|
1266
1730
|
}
|
|
1267
1731
|
function clearEnvConfig() {
|
|
1268
1732
|
try {
|
|
1269
|
-
|
|
1733
|
+
fs5.unlinkSync(getEnvConfigPath());
|
|
1270
1734
|
} catch {
|
|
1271
1735
|
}
|
|
1272
1736
|
}
|
|
@@ -2116,59 +2580,14 @@ var VSCODE_PRESETS = [
|
|
|
2116
2580
|
goVscode
|
|
2117
2581
|
];
|
|
2118
2582
|
|
|
2119
|
-
// src/core/merge-settings.ts
|
|
2120
|
-
var USER_PRIORITY_KEYS = /* @__PURE__ */ new Set([
|
|
2121
|
-
// Cursor/animation
|
|
2122
|
-
"editor.cursorBlinking",
|
|
2123
|
-
"editor.cursorSmoothCaretAnimation",
|
|
2124
|
-
"editor.renderWhitespace",
|
|
2125
|
-
"editor.guides.indentation",
|
|
2126
|
-
"editor.largeFileOptimizations",
|
|
2127
|
-
// Theme/appearance
|
|
2128
|
-
"workbench.iconTheme",
|
|
2129
|
-
"workbench.colorTheme",
|
|
2130
|
-
// Suggestions
|
|
2131
|
-
"editor.inlineSuggest.enabled",
|
|
2132
|
-
"editor.suggestSelection",
|
|
2133
|
-
"editor.acceptSuggestionOnEnter",
|
|
2134
|
-
"editor.bracketPairColorization.enabled",
|
|
2135
|
-
"editor.autoClosingBrackets",
|
|
2136
|
-
"editor.autoClosingOvertype"
|
|
2137
|
-
]);
|
|
2138
|
-
function mergeVscodeSettings(preset, existing) {
|
|
2139
|
-
const result = { ...existing };
|
|
2140
|
-
for (const [key, presetVal] of Object.entries(preset)) {
|
|
2141
|
-
const existingVal = existing[key];
|
|
2142
|
-
if (existingVal === void 0) {
|
|
2143
|
-
result[key] = presetVal;
|
|
2144
|
-
continue;
|
|
2145
|
-
}
|
|
2146
|
-
if (USER_PRIORITY_KEYS.has(key)) {
|
|
2147
|
-
continue;
|
|
2148
|
-
}
|
|
2149
|
-
if (isPlainObject(presetVal) && isPlainObject(existingVal)) {
|
|
2150
|
-
result[key] = mergeVscodeSettings(
|
|
2151
|
-
presetVal,
|
|
2152
|
-
existingVal
|
|
2153
|
-
);
|
|
2154
|
-
continue;
|
|
2155
|
-
}
|
|
2156
|
-
result[key] = presetVal;
|
|
2157
|
-
}
|
|
2158
|
-
return result;
|
|
2159
|
-
}
|
|
2160
|
-
function isPlainObject(val) {
|
|
2161
|
-
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
2583
|
// src/generators/vscode.ts
|
|
2165
|
-
var
|
|
2584
|
+
var STYLELINT_SETTINGS_PREFIXES2 = [
|
|
2166
2585
|
"stylelint.",
|
|
2167
2586
|
"css.validate",
|
|
2168
2587
|
"less.validate",
|
|
2169
2588
|
"scss.validate"
|
|
2170
2589
|
];
|
|
2171
|
-
var
|
|
2590
|
+
var STYLELINT_EXTENSION2 = "stylelint.vscode-stylelint";
|
|
2172
2591
|
function generateVscodeSettings(preset, opts) {
|
|
2173
2592
|
const settingsPath = `${opts.cwd}/.vscode/settings.json`;
|
|
2174
2593
|
if (opts.dryRun) {
|
|
@@ -2176,7 +2595,7 @@ function generateVscodeSettings(preset, opts) {
|
|
|
2176
2595
|
return existingSettings2 ? "overwritten" : "created";
|
|
2177
2596
|
}
|
|
2178
2597
|
const rawSettings = preset.settings();
|
|
2179
|
-
const presetSettings = opts.noStylelint ?
|
|
2598
|
+
const presetSettings = opts.noStylelint ? filterStylelintSettings2(rawSettings) : rawSettings;
|
|
2180
2599
|
const existingSettings = readJson(settingsPath);
|
|
2181
2600
|
if (existingSettings) {
|
|
2182
2601
|
const backupPath = `${settingsPath}.bak`;
|
|
@@ -2212,7 +2631,7 @@ function generateVscodeSettings(preset, opts) {
|
|
|
2212
2631
|
}
|
|
2213
2632
|
function generateVscodeExtensions(preset, opts) {
|
|
2214
2633
|
if (opts.dryRun) return "created";
|
|
2215
|
-
const extensions = opts.noStylelint ? preset.extensions().filter((ext) => ext !==
|
|
2634
|
+
const extensions = opts.noStylelint ? preset.extensions().filter((ext) => ext !== STYLELINT_EXTENSION2) : preset.extensions();
|
|
2216
2635
|
try {
|
|
2217
2636
|
writeJson(`${opts.cwd}/.vscode/extensions.json`, { recommendations: extensions });
|
|
2218
2637
|
} catch (error) {
|
|
@@ -2231,10 +2650,10 @@ function generateAllVscode(preset, opts) {
|
|
|
2231
2650
|
if (extAction === "created") result.created.push(".vscode/extensions.json");
|
|
2232
2651
|
return result;
|
|
2233
2652
|
}
|
|
2234
|
-
function
|
|
2653
|
+
function filterStylelintSettings2(settings) {
|
|
2235
2654
|
const filtered = Object.fromEntries(
|
|
2236
2655
|
Object.entries(settings).filter(
|
|
2237
|
-
([key]) => !
|
|
2656
|
+
([key]) => !STYLELINT_SETTINGS_PREFIXES2.some((prefix) => key.startsWith(prefix))
|
|
2238
2657
|
)
|
|
2239
2658
|
);
|
|
2240
2659
|
if (typeof filtered["editor.codeActionsOnSave"] === "object" && filtered["editor.codeActionsOnSave"] !== null) {
|
|
@@ -2248,29 +2667,20 @@ function filterStylelintSettings(settings) {
|
|
|
2248
2667
|
// src/commands/vscode.ts
|
|
2249
2668
|
function registerVscodeCommand(program2) {
|
|
2250
2669
|
const vscode = program2.command("vscode").description("Initialize VSCode config with preset");
|
|
2251
|
-
vscode.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--dry-run", "Preview without writing files").option("--stylelint", "Include Stylelint settings and extension").action(
|
|
2670
|
+
vscode.argument("<preset>").option("-F, --force", "Force overwrite existing files").option("--dry-run", "Preview without writing files").option("--stylelint", "Include Stylelint settings and extension").option("--reset", "Reset local preset and re-materialize from built-in").action(
|
|
2252
2671
|
async (presetName, options) => {
|
|
2253
2672
|
const preset = resolvePreset(VSCODE_PRESETS, presetName);
|
|
2254
2673
|
if (!preset) return;
|
|
2255
2674
|
const cwd = process.cwd();
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
force: options.force ?? false,
|
|
2259
|
-
dryRun: options.dryRun ?? false,
|
|
2260
|
-
noStylelint: options.stylelint !== true,
|
|
2261
|
-
noEditorconfig: false
|
|
2262
|
-
};
|
|
2263
|
-
const result = generateAllVscode(preset, opts);
|
|
2264
|
-
const files = [...result.created, ...result.overwritten];
|
|
2265
|
-
if (files.length === 0) {
|
|
2266
|
-
logger.warn("No files generated");
|
|
2267
|
-
return;
|
|
2675
|
+
if (options.reset) {
|
|
2676
|
+
resetLocalPreset("vscode", presetName);
|
|
2268
2677
|
}
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2678
|
+
const useLocal = localPresetExists("vscode", presetName);
|
|
2679
|
+
if (useLocal) {
|
|
2680
|
+
executeVscodeLocalPath(cwd, presetName, options);
|
|
2681
|
+
} else {
|
|
2682
|
+
executeVscodeBuiltinPath(cwd, presetName, preset, options);
|
|
2272
2683
|
}
|
|
2273
|
-
logger.log(`Created ${files.join(", ")}`);
|
|
2274
2684
|
}
|
|
2275
2685
|
);
|
|
2276
2686
|
vscode.command("list").description("List available vscode presets").action(() => {
|
|
@@ -2279,6 +2689,48 @@ function registerVscodeCommand(program2) {
|
|
|
2279
2689
|
}
|
|
2280
2690
|
});
|
|
2281
2691
|
}
|
|
2692
|
+
function executeVscodeLocalPath(cwd, presetName, options) {
|
|
2693
|
+
logger.log("Using local custom preset");
|
|
2694
|
+
const opts = {
|
|
2695
|
+
cwd,
|
|
2696
|
+
force: options.force ?? false,
|
|
2697
|
+
dryRun: options.dryRun ?? false,
|
|
2698
|
+
noStylelint: options.stylelint !== true,
|
|
2699
|
+
noEditorconfig: false
|
|
2700
|
+
};
|
|
2701
|
+
const result = applyLocalVscodePreset(cwd, presetName, opts);
|
|
2702
|
+
const files = [...result.created, ...result.overwritten];
|
|
2703
|
+
if (files.length === 0) {
|
|
2704
|
+
logger.warn("No files generated");
|
|
2705
|
+
return;
|
|
2706
|
+
}
|
|
2707
|
+
if (opts.dryRun) {
|
|
2708
|
+
logger.log(`[dry-run] Would create ${files.join(", ")} from local preset`);
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2711
|
+
logger.log(`Created ${files.join(", ")} from local preset`);
|
|
2712
|
+
}
|
|
2713
|
+
function executeVscodeBuiltinPath(cwd, presetName, preset, options) {
|
|
2714
|
+
const opts = {
|
|
2715
|
+
cwd,
|
|
2716
|
+
force: options.force ?? false,
|
|
2717
|
+
dryRun: options.dryRun ?? false,
|
|
2718
|
+
noStylelint: options.stylelint !== true,
|
|
2719
|
+
noEditorconfig: false
|
|
2720
|
+
};
|
|
2721
|
+
const result = generateAllVscode(preset, opts);
|
|
2722
|
+
const files = [...result.created, ...result.overwritten];
|
|
2723
|
+
if (files.length === 0) {
|
|
2724
|
+
logger.warn("No files generated");
|
|
2725
|
+
return;
|
|
2726
|
+
}
|
|
2727
|
+
if (opts.dryRun) {
|
|
2728
|
+
logger.log(`[dry-run] Would create ${files.join(", ")}`);
|
|
2729
|
+
return;
|
|
2730
|
+
}
|
|
2731
|
+
logger.log(`Created ${files.join(", ")}`);
|
|
2732
|
+
materializeVscodePreset(cwd, presetName);
|
|
2733
|
+
}
|
|
2282
2734
|
|
|
2283
2735
|
// src/commands/vpn.ts
|
|
2284
2736
|
import { spawnSync } from "child_process";
|