tailwind-lint 0.8.0 → 0.9.0
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/dist/cli.cjs +40 -40
- package/dist/linter.cjs +6 -7
- package/dist/{state-QQi4_-5a.cjs → state-CeRvUDZb.cjs} +14 -15
- package/package.json +8 -8
package/dist/cli.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_state = require('./state-
|
|
2
|
+
const require_state = require('./state-CeRvUDZb.cjs');
|
|
3
3
|
const require_linter = require('./linter.cjs');
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
node_path = require_state.__toESM(node_path);
|
|
6
|
-
let
|
|
7
|
-
|
|
6
|
+
let ansis = require("ansis");
|
|
7
|
+
ansis = require_state.__toESM(ansis);
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
node_fs = require_state.__toESM(node_fs);
|
|
10
10
|
let commander = require("commander");
|
|
@@ -117,10 +117,10 @@ async function displayResults(files, fixMode) {
|
|
|
117
117
|
console.log();
|
|
118
118
|
isFirstFile = false;
|
|
119
119
|
} else console.log();
|
|
120
|
-
console.log(
|
|
120
|
+
console.log(ansis.default.underline.bold(file.path));
|
|
121
121
|
if (fixMode && file.fixed) {
|
|
122
122
|
const issueText = `${file.fixedCount || 0} issue${file.fixedCount !== 1 ? "s" : ""}`;
|
|
123
|
-
console.log(
|
|
123
|
+
console.log(ansis.default.green(` ✔ Fixed ${issueText}`));
|
|
124
124
|
totalFixed += file.fixedCount || 0;
|
|
125
125
|
}
|
|
126
126
|
const { errors, warnings } = countBySeverity(file.diagnostics);
|
|
@@ -131,16 +131,16 @@ async function displayResults(files, fixMode) {
|
|
|
131
131
|
const line = diagnostic.range.start.line + 1;
|
|
132
132
|
const char = diagnostic.range.start.character + 1;
|
|
133
133
|
const severity = diagnostic.severity === require_state.SEVERITY.ERROR ? "error" : "warning";
|
|
134
|
-
const severityColor = diagnostic.severity === require_state.SEVERITY.ERROR ?
|
|
135
|
-
const code = diagnostic.code ?
|
|
136
|
-
console.log(` ${
|
|
134
|
+
const severityColor = diagnostic.severity === require_state.SEVERITY.ERROR ? ansis.default.red(severity) : ansis.default.yellow(severity);
|
|
135
|
+
const code = diagnostic.code ? ansis.default.dim(` (${diagnostic.code})`) : "";
|
|
136
|
+
console.log(` ${ansis.default.dim(`${line}:${char}`)} ${severityColor} ${diagnostic.message}${code}`);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
console.log();
|
|
140
140
|
if (totalErrors === 0 && totalWarnings === 0) if (totalFixed > 0) {
|
|
141
141
|
const issueText = `${totalFixed} issue${totalFixed !== 1 ? "s" : ""}`;
|
|
142
|
-
console.log(
|
|
143
|
-
} else console.log(
|
|
142
|
+
console.log(ansis.default.green.bold(`✔ Fixed ${issueText}`));
|
|
143
|
+
} else console.log(ansis.default.green.bold("✔ No issues found"));
|
|
144
144
|
else {
|
|
145
145
|
const parts = [];
|
|
146
146
|
if (totalErrors > 0) parts.push(`${totalErrors} error${totalErrors !== 1 ? "s" : ""}`);
|
|
@@ -149,7 +149,7 @@ async function displayResults(files, fixMode) {
|
|
|
149
149
|
const summary = `Found ${parts.join(" and ")} in ${fileText}`;
|
|
150
150
|
if (totalFixed > 0) {
|
|
151
151
|
const issueText = `${totalFixed} issue${totalFixed !== 1 ? "s" : ""}`;
|
|
152
|
-
console.log(
|
|
152
|
+
console.log(ansis.default.green.bold(`✔ Fixed ${issueText}`));
|
|
153
153
|
console.log(summary);
|
|
154
154
|
} else console.log(summary);
|
|
155
155
|
}
|
|
@@ -166,43 +166,43 @@ const getVersion = () => {
|
|
|
166
166
|
program.configureHelp({ formatHelp: (cmd, helper) => {
|
|
167
167
|
const termWidth = helper.padWidth(cmd, helper);
|
|
168
168
|
let output = "";
|
|
169
|
-
output += `${
|
|
169
|
+
output += `${ansis.default.bold.cyan("Usage:")} ${helper.commandUsage(cmd)}\n\n`;
|
|
170
170
|
if (cmd.description()) output += `${cmd.description()}\n\n`;
|
|
171
171
|
const args = helper.visibleArguments(cmd);
|
|
172
172
|
if (args.length > 0) {
|
|
173
|
-
output += `${
|
|
173
|
+
output += `${ansis.default.bold.cyan("Arguments:")}\n`;
|
|
174
174
|
args.forEach((arg) => {
|
|
175
175
|
const argName = arg.required ? `<${arg.name()}>` : `[${arg.name()}]`;
|
|
176
|
-
output += ` ${
|
|
176
|
+
output += ` ${ansis.default.green(argName.padEnd(termWidth))} ${arg.description}\n`;
|
|
177
177
|
});
|
|
178
178
|
output += "\n";
|
|
179
179
|
}
|
|
180
180
|
const options = helper.visibleOptions(cmd);
|
|
181
181
|
if (options.length > 0) {
|
|
182
|
-
output += `${
|
|
182
|
+
output += `${ansis.default.bold.cyan("Options:")}\n`;
|
|
183
183
|
options.forEach((option) => {
|
|
184
184
|
const flags = helper.optionTerm(option);
|
|
185
185
|
const description = helper.optionDescription(option);
|
|
186
|
-
output += ` ${
|
|
186
|
+
output += ` ${ansis.default.yellow(flags.padEnd(termWidth))} ${description}\n`;
|
|
187
187
|
});
|
|
188
188
|
output += "\n";
|
|
189
189
|
}
|
|
190
190
|
return output;
|
|
191
191
|
} });
|
|
192
192
|
program.name("tailwind-lint").description("A CLI tool for linting Tailwind CSS class usage").version(getVersion()).argument("[files...]", "File patterns to lint (e.g., \"src/**/*.{js,jsx,ts,tsx}\")").option("-c, --config <path>", "Path to Tailwind config file (default: auto-discover)").option("-a, --auto", "Auto-discover files from Tailwind config content patterns").option("--fix", "Automatically fix problems that can be fixed").option("-v, --verbose", "Enable verbose logging for debugging").option("--format <format>", "Output format: text or json", "text").addHelpText("after", `
|
|
193
|
-
${
|
|
194
|
-
${
|
|
195
|
-
${
|
|
196
|
-
${
|
|
197
|
-
${
|
|
198
|
-
${
|
|
193
|
+
${ansis.default.bold.cyan("Examples:")}
|
|
194
|
+
${ansis.default.dim("$")} tailwind-lint
|
|
195
|
+
${ansis.default.dim("$")} tailwind-lint ${ansis.default.green("\"src/**/*.{js,jsx,ts,tsx}\"")}
|
|
196
|
+
${ansis.default.dim("$")} tailwind-lint ${ansis.default.yellow("--config")} ${ansis.default.green("./tailwind.config.js")}
|
|
197
|
+
${ansis.default.dim("$")} tailwind-lint ${ansis.default.green("\"src/**/*.tsx\"")} ${ansis.default.yellow("--fix")}
|
|
198
|
+
${ansis.default.dim("$")} tailwind-lint ${ansis.default.green("\"**/*.vue\"")}
|
|
199
199
|
|
|
200
|
-
${
|
|
201
|
-
${
|
|
202
|
-
${
|
|
203
|
-
${
|
|
204
|
-
${
|
|
205
|
-
${
|
|
200
|
+
${ansis.default.bold.cyan("Notes:")}
|
|
201
|
+
${ansis.default.dim("•")} Running without arguments auto-discovers config and files
|
|
202
|
+
${ansis.default.dim("•")} For v3: uses content patterns from tailwind.config.js
|
|
203
|
+
${ansis.default.dim("•")} For v4: uses @source patterns from CSS config, or default pattern
|
|
204
|
+
${ansis.default.dim("•")} Default pattern: ${ansis.default.dim("./**/*.{js,jsx,ts,tsx,html}")}
|
|
205
|
+
${ansis.default.dim("•")} Use ${ansis.default.yellow("--fix")} to automatically resolve fixable issues
|
|
206
206
|
`).action(async (files, options) => {
|
|
207
207
|
const hasConfigFlag = !!options.config;
|
|
208
208
|
const hasAutoFlag = !!options.auto;
|
|
@@ -211,11 +211,11 @@ ${chalk.default.bold.cyan("Notes:")}
|
|
|
211
211
|
const isJsonOutput = (options.format === "json" ? "json" : "text") === "json";
|
|
212
212
|
try {
|
|
213
213
|
if (resolved.verbose && !isJsonOutput) {
|
|
214
|
-
console.log(
|
|
215
|
-
console.log(
|
|
216
|
-
console.log(
|
|
217
|
-
console.log(
|
|
218
|
-
console.log(
|
|
214
|
+
console.log(ansis.default.cyan.bold("→ Configuration"));
|
|
215
|
+
console.log(ansis.default.dim(` Working directory: ${resolved.cwd}`));
|
|
216
|
+
console.log(ansis.default.dim(` Config path: ${resolved.configPath || "auto-discover"}`));
|
|
217
|
+
console.log(ansis.default.dim(` Fix mode: ${resolved.fix}`));
|
|
218
|
+
console.log(ansis.default.dim(` Patterns: ${resolved.patterns.length > 0 ? resolved.patterns.join(", ") : "auto-discover"}`));
|
|
219
219
|
console.log();
|
|
220
220
|
}
|
|
221
221
|
const results = await require_linter.lint({
|
|
@@ -224,8 +224,8 @@ ${chalk.default.bold.cyan("Notes:")}
|
|
|
224
224
|
if (isJsonOutput) return;
|
|
225
225
|
if (process.stdout.isTTY && !resolved.verbose) {
|
|
226
226
|
const displayFile = truncateFilename(file);
|
|
227
|
-
process.stdout.write(`\r${
|
|
228
|
-
} else if (resolved.verbose) console.log(
|
|
227
|
+
process.stdout.write(`\r${ansis.default.cyan("→")} Linting files... ${ansis.default.dim(`(${current}/${total})`)} ${ansis.default.dim(displayFile)}${" ".repeat(require_state.TERMINAL_PADDING)}`);
|
|
228
|
+
} else if (resolved.verbose) console.log(ansis.default.dim(` [${current}/${total}] Linting ${file}`));
|
|
229
229
|
}
|
|
230
230
|
});
|
|
231
231
|
if (process.stdout.isTTY && !resolved.verbose && !isJsonOutput) process.stdout.write(`\r${" ".repeat(require_state.TERMINAL_WIDTH)}\r`);
|
|
@@ -237,7 +237,7 @@ ${chalk.default.bold.cyan("Notes:")}
|
|
|
237
237
|
})));
|
|
238
238
|
else {
|
|
239
239
|
console.log();
|
|
240
|
-
console.log(
|
|
240
|
+
console.log(ansis.default.yellow("⚠ No files found to lint"));
|
|
241
241
|
}
|
|
242
242
|
process.exit(0);
|
|
243
243
|
}
|
|
@@ -247,7 +247,7 @@ ${chalk.default.bold.cyan("Notes:")}
|
|
|
247
247
|
files: [],
|
|
248
248
|
totalFilesProcessed: results.totalFilesProcessed
|
|
249
249
|
})));
|
|
250
|
-
else console.log(
|
|
250
|
+
else console.log(ansis.default.green.bold("✔ No issues found"));
|
|
251
251
|
process.exit(0);
|
|
252
252
|
}
|
|
253
253
|
if (isJsonOutput) console.log(JSON.stringify(createJsonOutput({
|
|
@@ -264,10 +264,10 @@ ${chalk.default.bold.cyan("Notes:")}
|
|
|
264
264
|
ok: false,
|
|
265
265
|
error: errorMessage
|
|
266
266
|
}));
|
|
267
|
-
else console.error(
|
|
267
|
+
else console.error(ansis.default.red("✖ Error:"), errorMessage);
|
|
268
268
|
if (resolved.verbose && error instanceof Error && !isJsonOutput) {
|
|
269
|
-
console.error(
|
|
270
|
-
console.error(
|
|
269
|
+
console.error(ansis.default.dim("\nStack trace:"));
|
|
270
|
+
console.error(ansis.default.dim(error.stack || error.toString()));
|
|
271
271
|
}
|
|
272
272
|
process.exit(1);
|
|
273
273
|
}
|
package/dist/linter.cjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_state = require('./state-
|
|
2
|
+
const require_state = require('./state-CeRvUDZb.cjs');
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_state.__toESM(node_path);
|
|
5
5
|
let _tailwindcss_language_service = require("@tailwindcss/language-service");
|
|
6
|
-
let
|
|
7
|
-
|
|
8
|
-
let
|
|
9
|
-
fast_glob = require_state.__toESM(fast_glob);
|
|
6
|
+
let ansis = require("ansis");
|
|
7
|
+
ansis = require_state.__toESM(ansis);
|
|
8
|
+
let tinyglobby = require("tinyglobby");
|
|
10
9
|
let vscode_languageserver_textdocument = require("vscode-languageserver-textdocument");
|
|
11
10
|
|
|
12
11
|
//#region src/linter.ts
|
|
@@ -33,7 +32,7 @@ async function discoverFiles(cwd, patterns, configPath, autoDiscover) {
|
|
|
33
32
|
return expandPatterns(cwd, patterns);
|
|
34
33
|
}
|
|
35
34
|
async function expandPatterns(cwd, patterns, extraIgnore = []) {
|
|
36
|
-
const files = await (0,
|
|
35
|
+
const files = await (0, tinyglobby.glob)(patterns, {
|
|
37
36
|
cwd,
|
|
38
37
|
absolute: false,
|
|
39
38
|
ignore: [...require_state.DEFAULT_IGNORE_PATTERNS, ...extraIgnore]
|
|
@@ -150,7 +149,7 @@ async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verb
|
|
|
150
149
|
const state = await initializeState(cwd, configPath, verbose);
|
|
151
150
|
const files = await discoverFiles(cwd, patterns, configPath, autoDiscover);
|
|
152
151
|
if (verbose) {
|
|
153
|
-
console.log(
|
|
152
|
+
console.log(ansis.default.cyan.bold(`→ Discovered ${files.length} file${files.length !== 1 ? "s" : ""} to lint`));
|
|
154
153
|
console.log();
|
|
155
154
|
}
|
|
156
155
|
if (files.length === 0) return {
|
|
@@ -28,10 +28,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
let node_path = require("node:path");
|
|
29
29
|
node_path = __toESM(node_path);
|
|
30
30
|
let _tailwindcss_language_service = require("@tailwindcss/language-service");
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
let
|
|
34
|
-
fast_glob = __toESM(fast_glob);
|
|
31
|
+
let ansis = require("ansis");
|
|
32
|
+
ansis = __toESM(ansis);
|
|
33
|
+
let tinyglobby = require("tinyglobby");
|
|
35
34
|
let vscode_languageserver_textdocument = require("vscode-languageserver-textdocument");
|
|
36
35
|
let node_module = require("node:module");
|
|
37
36
|
let node_fs = require("node:fs");
|
|
@@ -328,11 +327,11 @@ async function loadV3ClassMetadata(state, cwd, verbose = false) {
|
|
|
328
327
|
expandApplyAtRules: { module: generateRulesModule.expandApplyAtRules }
|
|
329
328
|
}
|
|
330
329
|
};
|
|
331
|
-
if (verbose) console.log(
|
|
330
|
+
if (verbose) console.log(ansis.default.dim(" ✓ Loaded v3 JIT modules"));
|
|
332
331
|
} catch (jitError) {
|
|
333
332
|
if (verbose) {
|
|
334
333
|
const message = jitError instanceof Error ? jitError.message : String(jitError);
|
|
335
|
-
console.log(
|
|
334
|
+
console.log(ansis.default.yellow(` ⚠ Warning: Could not load v3 JIT modules: ${message}`));
|
|
336
335
|
}
|
|
337
336
|
state.modules = { tailwindcss: {
|
|
338
337
|
version: state.version || "unknown",
|
|
@@ -346,11 +345,11 @@ async function loadV3ClassMetadata(state, cwd, verbose = false) {
|
|
|
346
345
|
};
|
|
347
346
|
if (state.modules?.jit?.createContext && state.config) try {
|
|
348
347
|
state.jitContext = state.modules.jit.createContext.module(state.config);
|
|
349
|
-
if (verbose) console.log(
|
|
348
|
+
if (verbose) console.log(ansis.default.dim(" ✓ Created JIT context"));
|
|
350
349
|
} catch (contextError) {
|
|
351
350
|
if (verbose) {
|
|
352
351
|
const message = contextError instanceof Error ? contextError.message : String(contextError);
|
|
353
|
-
console.log(
|
|
352
|
+
console.log(ansis.default.yellow(` ⚠ Warning: Could not create JIT context: ${message}`));
|
|
354
353
|
}
|
|
355
354
|
}
|
|
356
355
|
} catch (error) {
|
|
@@ -473,7 +472,7 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
|
|
|
473
472
|
});
|
|
474
473
|
state.designSystem = designSystem;
|
|
475
474
|
if (!state.classNames) state.classNames = { context: {} };
|
|
476
|
-
if (verbose) console.log(
|
|
475
|
+
if (verbose) console.log(ansis.default.dim(" ✓ Loaded v4 design system"));
|
|
477
476
|
} else throw new AdapterLoadError("v4", /* @__PURE__ */ new Error("Tailwind v4 __unstable__loadDesignSystem is not available. Please ensure you have Tailwind CSS v4 installed."));
|
|
478
477
|
} catch (error) {
|
|
479
478
|
if (error instanceof AdapterLoadError) throw error;
|
|
@@ -512,7 +511,7 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
512
511
|
const fullPath = node_path.join(cwd, p);
|
|
513
512
|
if (fileExists(fullPath)) return fullPath;
|
|
514
513
|
}
|
|
515
|
-
const v3Recursive = await (0,
|
|
514
|
+
const v3Recursive = await (0, tinyglobby.glob)(V3_CONFIG_PATHS.map((p) => `**/${p}`), {
|
|
516
515
|
cwd,
|
|
517
516
|
absolute: true,
|
|
518
517
|
ignore: DEFAULT_IGNORE_PATTERNS,
|
|
@@ -527,7 +526,7 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
527
526
|
if (TAILWIND_V4_IMPORT_REGEX.test(content)) return fullPath;
|
|
528
527
|
} catch {}
|
|
529
528
|
}
|
|
530
|
-
const cssCandidates = await (0,
|
|
529
|
+
const cssCandidates = await (0, tinyglobby.glob)("**/*.css", {
|
|
531
530
|
cwd,
|
|
532
531
|
absolute: true,
|
|
533
532
|
ignore: DEFAULT_IGNORE_PATTERNS,
|
|
@@ -605,10 +604,10 @@ async function createState(cwd, configPath, verbose = false) {
|
|
|
605
604
|
const version = getTailwindVersion(cwd);
|
|
606
605
|
const isV4 = isV4Config(version);
|
|
607
606
|
if (verbose) {
|
|
608
|
-
console.log(
|
|
609
|
-
console.log(
|
|
610
|
-
console.log(
|
|
611
|
-
console.log(
|
|
607
|
+
console.log(ansis.default.cyan.bold("→ Tailwind Configuration"));
|
|
608
|
+
console.log(ansis.default.dim(` Version: ${version || "unknown"}`));
|
|
609
|
+
console.log(ansis.default.dim(` Config type: ${isCssConfig ? "CSS (v4)" : "JavaScript"}`));
|
|
610
|
+
console.log(ansis.default.dim(` Config path: ${resolvedConfigPath}`));
|
|
612
611
|
}
|
|
613
612
|
let config = {};
|
|
614
613
|
let resolvedConfig = { separator: ":" };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwind-lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "A command-line tool that uses the Tailwind CSS IntelliSense plugin to show linting suggestions for your Tailwind CSS classes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -59,16 +59,16 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@tailwindcss/language-service": "^0.14.29",
|
|
62
|
-
"
|
|
62
|
+
"ansis": "^4.2.0",
|
|
63
63
|
"commander": "^14.0.3",
|
|
64
|
-
"
|
|
65
|
-
"
|
|
64
|
+
"postcss": "^8.5.8",
|
|
65
|
+
"tinyglobby": "^0.2.15",
|
|
66
66
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@types/node": "^25.3.
|
|
70
|
-
"oxfmt": "^0.
|
|
71
|
-
"oxlint": "^1.
|
|
69
|
+
"@types/node": "^25.3.3",
|
|
70
|
+
"oxfmt": "^0.36.0",
|
|
71
|
+
"oxlint": "^1.51.0",
|
|
72
72
|
"tsdown": "^0.20.3",
|
|
73
73
|
"typescript": "^5.9.3",
|
|
74
74
|
"vitest": "^4.0.18"
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"node": ">=22.0.0",
|
|
78
78
|
"pnpm": ">=10.0.0"
|
|
79
79
|
},
|
|
80
|
-
"packageManager": "pnpm@10.30.
|
|
80
|
+
"packageManager": "pnpm@10.30.3"
|
|
81
81
|
}
|