cleanwind 0.3.0 → 0.3.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.
Files changed (2) hide show
  1. package/dist/index.js +137 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import path4 from "path";
4
5
  import { Command } from "commander";
5
6
 
6
7
  // ../core/dist/index.js
@@ -522,6 +523,7 @@ var displayClasses = /* @__PURE__ */ new Set([
522
523
  "hidden"
523
524
  ]);
524
525
  var positionClasses = /* @__PURE__ */ new Set(["static", "fixed", "absolute", "relative", "sticky"]);
526
+ var borderStyleClasses = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double", "hidden", "none"]);
525
527
  var variantOrder = [
526
528
  "sm",
527
529
  "md",
@@ -614,8 +616,9 @@ function conflictKey(className) {
614
616
  if (utility.startsWith("rounded")) {
615
617
  return `${variantPrefix}${roundedConflictKey(utility)}`;
616
618
  }
617
- if (/^border(?:-[trblxy])?-/u.test(utility) || utility === "border") {
618
- return `${variantPrefix}${borderConflictKey(utility)}`;
619
+ const border = borderConflictKey(utility);
620
+ if (border) {
621
+ return `${variantPrefix}${border}`;
619
622
  }
620
623
  if (/^flex-(row|row-reverse|col|col-reverse)$/u.test(utility)) {
621
624
  return `${variantPrefix}flex-direction`;
@@ -702,8 +705,26 @@ function roundedConflictKey(utility) {
702
705
  return match?.groups?.side ? `border-radius-${match.groups.side}` : "border-radius";
703
706
  }
704
707
  function borderConflictKey(utility) {
705
- const match = /^border(?:-(?<side>[trblxy]))?(?:-|$)/u.exec(utility);
706
- return match?.groups?.side ? `border-${match.groups.side}` : "border";
708
+ if (utility === "border-collapse" || utility === "border-separate") {
709
+ return "border-collapse";
710
+ }
711
+ const match = /^border(?:-(?<side>[trblxy]))?(?:-(?<value>.+))?$/u.exec(utility);
712
+ if (!match?.groups) {
713
+ return void 0;
714
+ }
715
+ const side = match.groups.side;
716
+ const value = match.groups.value;
717
+ const sideSuffix = side ? `-${side}` : "";
718
+ if (!value || isBorderWidthValue(value)) {
719
+ return `border-width${sideSuffix}`;
720
+ }
721
+ if (!side && borderStyleClasses.has(value)) {
722
+ return "border-style";
723
+ }
724
+ return `border-color${sideSuffix}`;
725
+ }
726
+ function isBorderWidthValue(value) {
727
+ return /^(0|2|4|8|\d+|\[.+\])$/u.test(value);
707
728
  }
708
729
  function rankUtility(utility) {
709
730
  if (utility.startsWith("container")) return 0;
@@ -1069,18 +1090,19 @@ function hasParseIssue(issues) {
1069
1090
  }
1070
1091
 
1071
1092
  // src/index.ts
1093
+ var defaultListLimit = 12;
1072
1094
  var program = new Command();
1073
- program.name("cleanwind").description("Clean imports and Tailwind CSS class names.").version("0.3.0");
1095
+ program.name("cleanwind").description("Clean imports and Tailwind CSS class names.").version("0.3.1");
1074
1096
  program.command("check").description("Check files without writing changes.").option("--cwd <path>", "Working directory").option("--config <path>", "Path to cleanwind config").option("--write", "Write fixes while running check").option("--check", "Force check mode", true).option("--verbose", "Print detailed diagnostics").option("--format", "Format output with Prettier after cleanup").action(async (options) => {
1075
1097
  const runOptions = toRunOptions(options);
1076
1098
  if (options.write) {
1077
1099
  const result2 = await fix({ ...runOptions, write: true });
1078
- printFixResult(result2, options.verbose ?? false);
1100
+ printFixResult(result2, options.verbose ?? false, runOptions.cwd ?? process.cwd());
1079
1101
  process.exitCode = result2.conflicts.length > 0 ? 1 : 0;
1080
1102
  return;
1081
1103
  }
1082
1104
  const result = await check(runOptions);
1083
- printCheckResult(result, options.verbose ?? false);
1105
+ printCheckResult(result, options.verbose ?? false, runOptions.cwd ?? process.cwd());
1084
1106
  process.exitCode = result.ok ? 0 : 1;
1085
1107
  });
1086
1108
  program.command("fix").description("Fix files in place.").option("--cwd <path>", "Working directory").option("--config <path>", "Path to cleanwind config").option("--write", "Write fixes", true).option("--check", "Preview fixes without writing").option("--verbose", "Print detailed diagnostics").option("--staged", "Only fix staged files").option("--format", "Format output with Prettier after cleanup").action(async (options) => {
@@ -1089,10 +1111,9 @@ program.command("fix").description("Fix files in place.").option("--cwd <path>",
1089
1111
  write: options.check ? false : options.write ?? true,
1090
1112
  staged: options.staged ?? false
1091
1113
  });
1092
- printFixResult(result, options.verbose ?? false);
1114
+ printFixResult(result, options.verbose ?? false, options.cwd ?? process.cwd());
1093
1115
  process.exitCode = result.conflicts.length > 0 ? 1 : 0;
1094
1116
  });
1095
- await program.parseAsync();
1096
1117
  function toRunOptions(options) {
1097
1118
  const runOptions = {};
1098
1119
  if (options.cwd !== void 0) runOptions.cwd = options.cwd;
@@ -1104,31 +1125,125 @@ function toRunOptions(options) {
1104
1125
  if (options.format !== void 0) runOptions.format = options.format;
1105
1126
  return runOptions;
1106
1127
  }
1107
- function printCheckResult(result, verbose) {
1128
+ function printCheckResult(result, verbose, cwd) {
1108
1129
  if (result.ok) {
1109
- console.log("cleanwind: all files are clean.");
1130
+ console.log(`${color.green("cleanwind")} all files are clean.`);
1110
1131
  return;
1111
1132
  }
1112
- console.log(`cleanwind: ${result.changedFiles.length} file(s) need cleanup.`);
1113
- printDiagnostics(result, verbose);
1114
- }
1115
- function printFixResult(result, verbose) {
1133
+ console.log(`${color.bold("cleanwind check")}`);
1134
+ console.log(
1135
+ summaryLine(
1136
+ result.changedFiles.length,
1137
+ result.conflicts.length,
1138
+ result.changedFiles.length === 1 ? "needs cleanup" : "need cleanup"
1139
+ )
1140
+ );
1141
+ printFileList("Files", result.changedFiles, cwd, verbose);
1142
+ printDiagnostics(result, verbose, cwd);
1143
+ printNextStep(result);
1144
+ }
1145
+ function printFixResult(result, verbose, cwd) {
1116
1146
  const written = result.writtenFiles.length;
1117
1147
  const changed = result.changedFiles.length;
1118
1148
  const mode = written > 0 ? "fixed" : "would change";
1119
- console.log(`cleanwind: ${mode} ${written > 0 ? written : changed} file(s).`);
1120
- printDiagnostics(result, verbose);
1149
+ console.log(`${color.bold("cleanwind fix")}`);
1150
+ console.log(summaryLine(written > 0 ? written : changed, result.conflicts.length, mode));
1151
+ printFileList(written > 0 ? "Written" : "Would change", written > 0 ? result.writtenFiles : result.changedFiles, cwd, verbose);
1152
+ printDiagnostics(result, verbose, cwd);
1153
+ printNextStep(result);
1154
+ }
1155
+ function summaryLine(fileCount, conflictCount, mode) {
1156
+ const files = `${fileCount} file${fileCount === 1 ? "" : "s"}`;
1157
+ const filePhrase = mode === "would change" ? `${mode} ${files}` : `${files} ${mode}`;
1158
+ const conflicts = conflictCount > 0 ? `, ${color.yellow(`${conflictCount} conflict${conflictCount === 1 ? "" : "s"}`)}` : "";
1159
+ return `${color.cyan(filePhrase)}${conflicts}.`;
1160
+ }
1161
+ function printFileList(title, files, cwd, verbose) {
1162
+ if (files.length === 0) {
1163
+ return;
1164
+ }
1165
+ const shown = verbose ? files : files.slice(0, defaultListLimit);
1166
+ console.log("");
1167
+ console.log(color.bold(title));
1168
+ for (const file of shown) {
1169
+ console.log(` ${formatPath(file, cwd)}`);
1170
+ }
1171
+ if (!verbose && files.length > shown.length) {
1172
+ console.log(color.dim(` ... ${files.length - shown.length} more. Run with --verbose to show all.`));
1173
+ }
1121
1174
  }
1122
- function printDiagnostics(result, verbose) {
1123
- for (const conflict of result.conflicts) {
1175
+ function printDiagnostics(result, verbose, cwd) {
1176
+ printConflicts(result, verbose, cwd);
1177
+ printIssues(result, verbose, cwd);
1178
+ }
1179
+ function printConflicts(result, verbose, cwd) {
1180
+ if (result.conflicts.length === 0) {
1181
+ return;
1182
+ }
1183
+ const conflicts = verbose ? result.conflicts : result.conflicts.slice(0, defaultListLimit);
1184
+ let currentFile = "";
1185
+ console.error("");
1186
+ console.error(color.bold("Conflicts"));
1187
+ for (const conflict of conflicts) {
1188
+ const file = formatPath(conflict.file, cwd);
1189
+ if (file !== currentFile) {
1190
+ currentFile = file;
1191
+ console.error(` ${color.cyan(file)}`);
1192
+ }
1124
1193
  console.error(
1125
- `${conflict.file}:${conflict.line} ${conflict.suggestion} (${conflict.conflictingClasses.join(" ")})`
1194
+ ` ${color.dim(String(conflict.line).padStart(4, " "))} ${conflict.conflictingClasses.join(" + ")}`
1126
1195
  );
1127
1196
  }
1197
+ if (!verbose && result.conflicts.length > conflicts.length) {
1198
+ console.error(
1199
+ color.dim(
1200
+ ` ... ${result.conflicts.length - conflicts.length} more conflict(s). Run with --verbose to show all.`
1201
+ )
1202
+ );
1203
+ }
1204
+ }
1205
+ function printIssues(result, verbose, cwd) {
1128
1206
  if (!verbose) {
1129
1207
  return;
1130
1208
  }
1131
- for (const issue of result.issues) {
1132
- console.error(`${issue.file}:${issue.line} [${issue.kind}] ${issue.message}`);
1209
+ const issues = result.issues.filter((issue) => issue.kind !== "conflict");
1210
+ if (issues.length === 0) {
1211
+ return;
1212
+ }
1213
+ console.error("");
1214
+ console.error(color.bold("Diagnostics"));
1215
+ for (const issue of issues) {
1216
+ console.error(
1217
+ ` ${color.cyan(formatPath(issue.file, cwd))}:${issue.line} ${color.dim(`[${issue.kind}]`)} ${issue.message}`
1218
+ );
1133
1219
  }
1134
1220
  }
1221
+ function printNextStep(result) {
1222
+ if (result.conflicts.length > 0) {
1223
+ console.log("");
1224
+ console.log(color.dim("Resolve conflicts manually, then run: npx cleanwind fix --format"));
1225
+ return;
1226
+ }
1227
+ if (result.changedFiles.length > 0) {
1228
+ console.log("");
1229
+ console.log(color.dim("Apply cleanup with: npx cleanwind fix --format"));
1230
+ }
1231
+ }
1232
+ function formatPath(file, cwd) {
1233
+ const relative = path4.relative(path4.resolve(cwd), file);
1234
+ return (relative && !relative.startsWith("..") ? relative : file).replaceAll("\\", "/");
1235
+ }
1236
+ function supportsColor() {
1237
+ return process.env.NO_COLOR === void 0 && process.stdout.isTTY === true;
1238
+ }
1239
+ function paint(code, value) {
1240
+ return supportsColor() ? `\x1B[${code}m${value}\x1B[0m` : value;
1241
+ }
1242
+ var color = {
1243
+ bold: (value) => paint("1", value),
1244
+ cyan: (value) => paint("36", value),
1245
+ dim: (value) => paint("2", value),
1246
+ green: (value) => paint("32", value),
1247
+ yellow: (value) => paint("33", value)
1248
+ };
1249
+ await program.parseAsync();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cleanwind",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Clean imports and Tailwind CSS class names from the command line.",
5
5
  "type": "module",
6
6
  "license": "MIT",