tailwind-lint 0.10.2 → 0.11.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 +52 -1
- package/dist/cli.cjs +38 -14
- package/dist/{linter-ChZk2xMs.cjs → linter-BBFc8gnJ.cjs} +179 -33
- package/dist/linter.cjs +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ tailwind-lint --verbose
|
|
|
65
65
|
### Options
|
|
66
66
|
|
|
67
67
|
- `-c, --config <path>` - Path to Tailwind config file (default: auto-discover)
|
|
68
|
-
- `-a, --auto` - Auto-discover files from
|
|
68
|
+
- `-a, --auto` - Auto-discover files from the resolved Tailwind config or CSS `@source` directives
|
|
69
69
|
- `--fix` - Automatically fix problems that can be fixed
|
|
70
70
|
- `--format <text|json>` - Output format (`text` default, `json` for machine-readable output)
|
|
71
71
|
- `-v, --verbose` - Enable verbose logging for debugging
|
|
@@ -81,6 +81,9 @@ tailwind-lint "src/**/*.{js,jsx,ts,tsx}"
|
|
|
81
81
|
# Specify a custom config location
|
|
82
82
|
tailwind-lint --config ./config/tailwind.config.js
|
|
83
83
|
|
|
84
|
+
# Scan files based on an explicit config
|
|
85
|
+
tailwind-lint --config ./src/app.css
|
|
86
|
+
|
|
84
87
|
# Lint and fix specific file types
|
|
85
88
|
tailwind-lint "**/*.vue" --fix
|
|
86
89
|
|
|
@@ -109,6 +112,8 @@ The JSON payload includes:
|
|
|
109
112
|
- `config` - resolved runtime values (`cwd`, `configPath`, `autoDiscover`, `fix`, `patterns`)
|
|
110
113
|
- `files[]` - per-file diagnostics with 1-based `line`/`column` ranges
|
|
111
114
|
|
|
115
|
+
On JSON errors, the CLI keeps the same top-level shape and adds `error` so agent integrations do not need a separate parser for failure cases.
|
|
116
|
+
|
|
112
117
|
Typical agent flow:
|
|
113
118
|
|
|
114
119
|
1. Run `tailwind-lint --auto --format json`.
|
|
@@ -147,6 +152,52 @@ export default defineConfig({
|
|
|
147
152
|
|
|
148
153
|
If a real CSS config is also present, the CLI uses that file so custom `@theme` tokens and `@source` directives are available to diagnostics.
|
|
149
154
|
|
|
155
|
+
### Workspace Settings
|
|
156
|
+
|
|
157
|
+
The CLI also reads Tailwind workspace settings from common editor config files so extraction behavior can match your editor more closely.
|
|
158
|
+
|
|
159
|
+
Supported locations:
|
|
160
|
+
|
|
161
|
+
- `.zed/settings.json`
|
|
162
|
+
- `.vscode/settings.json`
|
|
163
|
+
|
|
164
|
+
Supported settings:
|
|
165
|
+
|
|
166
|
+
- `classFunctions`
|
|
167
|
+
- `experimental.classRegex`
|
|
168
|
+
- `classAttributes`
|
|
169
|
+
- `includeLanguages`
|
|
170
|
+
- `files.exclude`
|
|
171
|
+
- `lint`
|
|
172
|
+
|
|
173
|
+
Zed format:
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"lsp": {
|
|
178
|
+
"tailwindcss-language-server": {
|
|
179
|
+
"settings": {
|
|
180
|
+
"classFunctions": ["cva", "cx"],
|
|
181
|
+
"experimental": {
|
|
182
|
+
"classRegex": ["tw=\"([^\"]*)\""]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
VS Code format:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"tailwindCSS.classFunctions": ["cva", "cx"],
|
|
195
|
+
"tailwindCSS.experimental": {
|
|
196
|
+
"classRegex": ["tw=\"([^\"]*)\""]
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
150
201
|
### Tailwind CSS v3 (Legacy)
|
|
151
202
|
|
|
152
203
|
Create a JavaScript config file (`tailwind.config.js`):
|
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_linter = require("./linter-
|
|
2
|
+
const require_linter = require("./linter-BBFc8gnJ.cjs");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_linter.__toESM(node_path, 1);
|
|
5
5
|
let ansis = require("ansis");
|
|
@@ -74,6 +74,27 @@ function createJsonOutput({ files, totalFilesProcessed, cwd, configPath, autoDis
|
|
|
74
74
|
files: mappedFiles
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
function createJsonErrorOutput({ error, cwd, configPath, autoDiscover, fix, patterns }) {
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
error,
|
|
81
|
+
summary: {
|
|
82
|
+
errors: 0,
|
|
83
|
+
warnings: 0,
|
|
84
|
+
fixed: 0,
|
|
85
|
+
filesWithIssues: 0,
|
|
86
|
+
totalFilesProcessed: 0
|
|
87
|
+
},
|
|
88
|
+
config: {
|
|
89
|
+
cwd,
|
|
90
|
+
configPath: configPath || null,
|
|
91
|
+
autoDiscover,
|
|
92
|
+
fix,
|
|
93
|
+
patterns
|
|
94
|
+
},
|
|
95
|
+
files: []
|
|
96
|
+
};
|
|
97
|
+
}
|
|
77
98
|
//#endregion
|
|
78
99
|
//#region src/cli.ts
|
|
79
100
|
const MAX_FILENAME_DISPLAY_LENGTH = 50;
|
|
@@ -84,13 +105,13 @@ function resolveOptions(files, options) {
|
|
|
84
105
|
let cwd = process.cwd();
|
|
85
106
|
let configPath = options.config;
|
|
86
107
|
let patterns = files;
|
|
108
|
+
let autoDiscover = hasAutoFlag;
|
|
109
|
+
if (hasConfigFlag && options.config) configPath = node_path.isAbsolute(options.config) ? options.config : node_path.resolve(process.cwd(), options.config);
|
|
87
110
|
if (hasConfigFlag && options.config && !hasFiles) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
patterns = [require_linter.DEFAULT_FILE_PATTERN];
|
|
111
|
+
cwd = node_path.dirname(configPath);
|
|
112
|
+
patterns = [];
|
|
113
|
+
autoDiscover = true;
|
|
92
114
|
}
|
|
93
|
-
const autoDiscover = hasAutoFlag;
|
|
94
115
|
return {
|
|
95
116
|
cwd,
|
|
96
117
|
configPath,
|
|
@@ -101,7 +122,7 @@ function resolveOptions(files, options) {
|
|
|
101
122
|
};
|
|
102
123
|
}
|
|
103
124
|
function truncateFilename(filename) {
|
|
104
|
-
return filename.length > MAX_FILENAME_DISPLAY_LENGTH ? `...${filename.slice(-
|
|
125
|
+
return filename.length > MAX_FILENAME_DISPLAY_LENGTH ? `...${filename.slice(-50)}` : filename;
|
|
105
126
|
}
|
|
106
127
|
async function displayResults(files, fixMode) {
|
|
107
128
|
let totalErrors = 0;
|
|
@@ -186,19 +207,22 @@ program.configureHelp({ formatHelp: (cmd, helper) => {
|
|
|
186
207
|
}
|
|
187
208
|
return output;
|
|
188
209
|
} });
|
|
189
|
-
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
|
|
210
|
+
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 or CSS @source 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", `
|
|
190
211
|
${ansis.default.bold.cyan("Examples:")}
|
|
191
212
|
${ansis.default.dim("$")} tailwind-lint
|
|
192
213
|
${ansis.default.dim("$")} tailwind-lint ${ansis.default.green("\"src/**/*.{js,jsx,ts,tsx}\"")}
|
|
193
214
|
${ansis.default.dim("$")} tailwind-lint ${ansis.default.yellow("--config")} ${ansis.default.green("./tailwind.config.js")}
|
|
215
|
+
${ansis.default.dim("$")} tailwind-lint ${ansis.default.yellow("--config")} ${ansis.default.green("./src/app.css")}
|
|
194
216
|
${ansis.default.dim("$")} tailwind-lint ${ansis.default.green("\"src/**/*.tsx\"")} ${ansis.default.yellow("--fix")}
|
|
195
217
|
${ansis.default.dim("$")} tailwind-lint ${ansis.default.green("\"**/*.vue\"")}
|
|
196
218
|
|
|
197
219
|
${ansis.default.bold.cyan("Notes:")}
|
|
198
220
|
${ansis.default.dim("•")} Running without arguments auto-discovers config and files
|
|
221
|
+
${ansis.default.dim("•")} Using ${ansis.default.yellow("--config")} without files scans based on that config
|
|
199
222
|
${ansis.default.dim("•")} For v3: uses content patterns from tailwind.config.js
|
|
200
|
-
${ansis.default.dim("•")} For v4: uses @source patterns from CSS config, or default pattern
|
|
201
|
-
${ansis.default.dim("•")} Default pattern: ${ansis.default.dim(
|
|
223
|
+
${ansis.default.dim("•")} For v4: uses @source patterns from CSS config, Vite detection, or default pattern
|
|
224
|
+
${ansis.default.dim("•")} Default pattern: ${ansis.default.dim(require_linter.DEFAULT_FILE_PATTERN)}
|
|
225
|
+
${ansis.default.dim("•")} Reads Tailwind workspace settings from ${ansis.default.dim(".zed/settings.json")} and ${ansis.default.dim(".vscode/settings.json")}
|
|
202
226
|
${ansis.default.dim("•")} Use ${ansis.default.yellow("--fix")} to automatically resolve fixable issues
|
|
203
227
|
`).action(async (files, options) => {
|
|
204
228
|
const hasConfigFlag = !!options.config;
|
|
@@ -257,10 +281,10 @@ ${ansis.default.bold.cyan("Notes:")}
|
|
|
257
281
|
process.exit(hasErrors ? 1 : 0);
|
|
258
282
|
} catch (error) {
|
|
259
283
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
260
|
-
if (isJsonOutput) console.log(JSON.stringify({
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}));
|
|
284
|
+
if (isJsonOutput) console.log(JSON.stringify(createJsonErrorOutput({
|
|
285
|
+
error: errorMessage,
|
|
286
|
+
...resolved
|
|
287
|
+
})));
|
|
264
288
|
else console.error(ansis.default.red("✖ Error:"), errorMessage);
|
|
265
289
|
if (resolved.verbose && error instanceof Error && !isJsonOutput) {
|
|
266
290
|
console.error(ansis.default.dim("\nStack trace:"));
|
|
@@ -206,6 +206,182 @@ async function applyCodeActions(state, filePath, content, diagnostics) {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
//#endregion
|
|
209
|
+
//#region src/utils/fs.ts
|
|
210
|
+
function fileExists(filePath) {
|
|
211
|
+
try {
|
|
212
|
+
return node_fs.existsSync(filePath);
|
|
213
|
+
} catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function readFileSync(filePath) {
|
|
218
|
+
if (!filePath || typeof filePath !== "string") throw new TypeError("File path must be a non-empty string");
|
|
219
|
+
return node_fs.readFileSync(filePath, "utf-8");
|
|
220
|
+
}
|
|
221
|
+
function writeFileSync(filePath, content) {
|
|
222
|
+
if (!filePath || typeof filePath !== "string") throw new TypeError("File path must be a non-empty string");
|
|
223
|
+
if (typeof content !== "string") throw new TypeError("Content must be a string");
|
|
224
|
+
node_fs.writeFileSync(filePath, content, "utf-8");
|
|
225
|
+
}
|
|
226
|
+
function readGitignorePatterns(cwd) {
|
|
227
|
+
const gitignorePath = node_path.join(cwd, ".gitignore");
|
|
228
|
+
if (!fileExists(gitignorePath)) return [];
|
|
229
|
+
try {
|
|
230
|
+
return node_fs.readFileSync(gitignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && !line.startsWith("!")).map((pattern) => {
|
|
231
|
+
const cleaned = pattern.replace(/\/+$/, "");
|
|
232
|
+
if (cleaned.includes("/") || cleaned.includes("*")) return cleaned.endsWith("/**") ? cleaned : `${cleaned}/**`;
|
|
233
|
+
return `**/${cleaned}/**`;
|
|
234
|
+
});
|
|
235
|
+
} catch {
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/utils/settings.ts
|
|
241
|
+
function loadWorkspaceTailwindSettings(cwd) {
|
|
242
|
+
return mergeTailwindSettings(readVsCodeTailwindSettings(cwd), readZedTailwindSettings(cwd));
|
|
243
|
+
}
|
|
244
|
+
function readVsCodeTailwindSettings(cwd) {
|
|
245
|
+
const parsed = readJsoncFile(node_path.join(cwd, ".vscode", "settings.json"));
|
|
246
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
247
|
+
const raw = parsed;
|
|
248
|
+
const experimental = readNestedObject(raw, "tailwindCSS.experimental");
|
|
249
|
+
const files = readNestedObject(raw, "tailwindCSS.files");
|
|
250
|
+
const lint = readNestedObject(raw, "tailwindCSS.lint");
|
|
251
|
+
return {
|
|
252
|
+
includeLanguages: asRecord(raw["tailwindCSS.includeLanguages"]),
|
|
253
|
+
classAttributes: asStringArray(raw["tailwindCSS.classAttributes"]),
|
|
254
|
+
classFunctions: asStringArray(raw["tailwindCSS.classFunctions"]),
|
|
255
|
+
experimental: {
|
|
256
|
+
classRegex: asClassRegex(experimental?.classRegex),
|
|
257
|
+
configFile: asConfigFile(experimental?.configFile)
|
|
258
|
+
},
|
|
259
|
+
files: { exclude: asStringArray(files?.exclude) },
|
|
260
|
+
lint: asLintSettings(lint)
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function readZedTailwindSettings(cwd) {
|
|
264
|
+
const parsed = readJsoncFile(node_path.join(cwd, ".zed", "settings.json"));
|
|
265
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
266
|
+
const serverSettings = asRecord(asRecord(asRecord(parsed.lsp)?.["tailwindcss-language-server"])?.settings);
|
|
267
|
+
const normalized = asRecord(serverSettings?.tailwindCSS) ?? serverSettings;
|
|
268
|
+
if (!normalized) return {};
|
|
269
|
+
return {
|
|
270
|
+
includeLanguages: asRecord(normalized.includeLanguages),
|
|
271
|
+
classAttributes: asStringArray(normalized.classAttributes),
|
|
272
|
+
classFunctions: asStringArray(normalized.classFunctions),
|
|
273
|
+
experimental: {
|
|
274
|
+
classRegex: asClassRegex(asRecord(normalized.experimental)?.classRegex),
|
|
275
|
+
configFile: asConfigFile(asRecord(normalized.experimental)?.configFile)
|
|
276
|
+
},
|
|
277
|
+
files: { exclude: asStringArray(asRecord(normalized.files)?.exclude) },
|
|
278
|
+
lint: asLintSettings(asRecord(normalized.lint))
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function readJsoncFile(filePath) {
|
|
282
|
+
if (!fileExists(filePath)) return null;
|
|
283
|
+
try {
|
|
284
|
+
return JSON.parse(stripJsonComments(readFileSync(filePath)));
|
|
285
|
+
} catch {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function stripJsonComments(content) {
|
|
290
|
+
return content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "").replace(/,\s*([}\]])/g, "$1");
|
|
291
|
+
}
|
|
292
|
+
function readNestedObject(input, key) {
|
|
293
|
+
return asRecord(input[key]);
|
|
294
|
+
}
|
|
295
|
+
function asRecord(value) {
|
|
296
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
297
|
+
}
|
|
298
|
+
function asStringArray(value) {
|
|
299
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
|
|
300
|
+
}
|
|
301
|
+
function asClassRegex(value) {
|
|
302
|
+
if (!Array.isArray(value)) return;
|
|
303
|
+
if (value.every((item) => typeof item === "string")) return value;
|
|
304
|
+
if (value.every((item) => Array.isArray(item) && item.length === 2 && item.every((part) => typeof part === "string"))) return value;
|
|
305
|
+
}
|
|
306
|
+
function asConfigFile(value) {
|
|
307
|
+
if (typeof value === "string" || value === null) return value;
|
|
308
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
309
|
+
const record = value;
|
|
310
|
+
const entries = Object.entries(record).filter(([, entry]) => typeof entry === "string" || Array.isArray(entry) && entry.every((item) => typeof item === "string"));
|
|
311
|
+
return entries.length === Object.keys(record).length ? Object.fromEntries(entries) : void 0;
|
|
312
|
+
}
|
|
313
|
+
function asLintSettings(value) {
|
|
314
|
+
if (!value) return;
|
|
315
|
+
const entries = Object.entries(value).filter(([, entry]) => [
|
|
316
|
+
"ignore",
|
|
317
|
+
"warning",
|
|
318
|
+
"error"
|
|
319
|
+
].includes(String(entry)));
|
|
320
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
321
|
+
}
|
|
322
|
+
function mergeTailwindSettings(...patches) {
|
|
323
|
+
return patches.reduce((acc, patch) => {
|
|
324
|
+
if (patch.includeLanguages) acc.includeLanguages = {
|
|
325
|
+
...acc.includeLanguages,
|
|
326
|
+
...patch.includeLanguages
|
|
327
|
+
};
|
|
328
|
+
if (patch.classAttributes) acc.classAttributes = uniqueStrings(acc.classAttributes, patch.classAttributes);
|
|
329
|
+
if (patch.classFunctions) acc.classFunctions = uniqueStrings(acc.classFunctions, patch.classFunctions);
|
|
330
|
+
if (patch.experimental) acc.experimental = {
|
|
331
|
+
...acc.experimental,
|
|
332
|
+
...patch.experimental,
|
|
333
|
+
classRegex: mergeClassRegex(acc.experimental?.classRegex, patch.experimental.classRegex)
|
|
334
|
+
};
|
|
335
|
+
if (patch.files?.exclude) acc.files = { exclude: uniqueStrings(acc.files?.exclude, patch.files.exclude) };
|
|
336
|
+
if (patch.lint) acc.lint = {
|
|
337
|
+
...acc.lint,
|
|
338
|
+
...patch.lint
|
|
339
|
+
};
|
|
340
|
+
return acc;
|
|
341
|
+
}, {});
|
|
342
|
+
}
|
|
343
|
+
function uniqueStrings(...arrays) {
|
|
344
|
+
return [...new Set(arrays.flatMap((array) => array ?? []))];
|
|
345
|
+
}
|
|
346
|
+
function mergeClassRegex(current, next) {
|
|
347
|
+
if (!next) return current;
|
|
348
|
+
if (!current) return next;
|
|
349
|
+
const serialized = /* @__PURE__ */ new Set();
|
|
350
|
+
const merged = [];
|
|
351
|
+
for (const item of [...current, ...next]) {
|
|
352
|
+
const key = JSON.stringify(item);
|
|
353
|
+
if (serialized.has(key)) continue;
|
|
354
|
+
serialized.add(key);
|
|
355
|
+
merged.push(item);
|
|
356
|
+
}
|
|
357
|
+
return merged;
|
|
358
|
+
}
|
|
359
|
+
function mergeEditorSettings(defaultSettings, overrides) {
|
|
360
|
+
return {
|
|
361
|
+
...defaultSettings,
|
|
362
|
+
tailwindCSS: {
|
|
363
|
+
...defaultSettings.tailwindCSS,
|
|
364
|
+
...overrides,
|
|
365
|
+
includeLanguages: {
|
|
366
|
+
...defaultSettings.tailwindCSS.includeLanguages,
|
|
367
|
+
...overrides.includeLanguages
|
|
368
|
+
},
|
|
369
|
+
classAttributes: uniqueStrings(defaultSettings.tailwindCSS.classAttributes, overrides.classAttributes),
|
|
370
|
+
classFunctions: uniqueStrings(defaultSettings.tailwindCSS.classFunctions, overrides.classFunctions),
|
|
371
|
+
files: { exclude: uniqueStrings(defaultSettings.tailwindCSS.files.exclude, overrides.files?.exclude) },
|
|
372
|
+
experimental: {
|
|
373
|
+
...defaultSettings.tailwindCSS.experimental,
|
|
374
|
+
...overrides.experimental,
|
|
375
|
+
classRegex: mergeClassRegex(defaultSettings.tailwindCSS.experimental.classRegex, overrides.experimental?.classRegex) ?? defaultSettings.tailwindCSS.experimental.classRegex
|
|
376
|
+
},
|
|
377
|
+
lint: {
|
|
378
|
+
...defaultSettings.tailwindCSS.lint,
|
|
379
|
+
...overrides.lint
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
//#endregion
|
|
209
385
|
//#region src/adapters/editor-state-adapter.ts
|
|
210
386
|
function isDirectory(filePath) {
|
|
211
387
|
try {
|
|
@@ -215,7 +391,7 @@ function isDirectory(filePath) {
|
|
|
215
391
|
}
|
|
216
392
|
}
|
|
217
393
|
function createEditorState(cwd) {
|
|
218
|
-
const settings = {
|
|
394
|
+
const settings = mergeEditorSettings({
|
|
219
395
|
editor: { tabSize: 2 },
|
|
220
396
|
tailwindCSS: {
|
|
221
397
|
validate: true,
|
|
@@ -264,7 +440,7 @@ function createEditorState(cwd) {
|
|
|
264
440
|
suggestCanonicalClasses: "warning"
|
|
265
441
|
}
|
|
266
442
|
}
|
|
267
|
-
};
|
|
443
|
+
}, loadWorkspaceTailwindSettings(cwd));
|
|
268
444
|
return {
|
|
269
445
|
connection: null,
|
|
270
446
|
folder: cwd,
|
|
@@ -293,6 +469,7 @@ function createEditorState(cwd) {
|
|
|
293
469
|
* Error thrown when adapter fails to load required modules
|
|
294
470
|
*/
|
|
295
471
|
var AdapterLoadError = class extends Error {
|
|
472
|
+
version;
|
|
296
473
|
constructor(version, cause) {
|
|
297
474
|
super(`Failed to load ${version} adapter: ${cause.message}`);
|
|
298
475
|
this.version = version;
|
|
@@ -366,37 +543,6 @@ function extractConfigMetadata(state) {
|
|
|
366
543
|
if (config.corePlugins) state.corePlugins = Array.isArray(config.corePlugins) ? config.corePlugins : Object.keys(config.corePlugins);
|
|
367
544
|
}
|
|
368
545
|
//#endregion
|
|
369
|
-
//#region src/utils/fs.ts
|
|
370
|
-
function fileExists(filePath) {
|
|
371
|
-
try {
|
|
372
|
-
return node_fs.existsSync(filePath);
|
|
373
|
-
} catch {
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
function readFileSync(filePath) {
|
|
378
|
-
if (!filePath || typeof filePath !== "string") throw new TypeError("File path must be a non-empty string");
|
|
379
|
-
return node_fs.readFileSync(filePath, "utf-8");
|
|
380
|
-
}
|
|
381
|
-
function writeFileSync(filePath, content) {
|
|
382
|
-
if (!filePath || typeof filePath !== "string") throw new TypeError("File path must be a non-empty string");
|
|
383
|
-
if (typeof content !== "string") throw new TypeError("Content must be a string");
|
|
384
|
-
node_fs.writeFileSync(filePath, content, "utf-8");
|
|
385
|
-
}
|
|
386
|
-
function readGitignorePatterns(cwd) {
|
|
387
|
-
const gitignorePath = node_path.join(cwd, ".gitignore");
|
|
388
|
-
if (!fileExists(gitignorePath)) return [];
|
|
389
|
-
try {
|
|
390
|
-
return node_fs.readFileSync(gitignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && !line.startsWith("!")).map((pattern) => {
|
|
391
|
-
const cleaned = pattern.replace(/\/+$/, "");
|
|
392
|
-
if (cleaned.includes("/") || cleaned.includes("*")) return cleaned.endsWith("/**") ? cleaned : `${cleaned}/**`;
|
|
393
|
-
return `**/${cleaned}/**`;
|
|
394
|
-
});
|
|
395
|
-
} catch {
|
|
396
|
-
return [];
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
//#endregion
|
|
400
546
|
//#region src/adapters/v4-adapter.ts
|
|
401
547
|
const require$3 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
|
|
402
548
|
async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
|
package/dist/linter.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_linter = require("./linter-
|
|
2
|
+
const require_linter = require("./linter-BBFc8gnJ.cjs");
|
|
3
3
|
exports.extractImportSourceDirectives = require_linter.extractImportSourceDirectives;
|
|
4
4
|
exports.extractSourcePatterns = require_linter.extractSourcePatterns;
|
|
5
5
|
exports.lint = require_linter.lint;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwind-lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
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,23 +59,23 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@tailwindcss/language-service": "^0.14.29",
|
|
62
|
-
"ansis": "^4.
|
|
62
|
+
"ansis": "^4.3.0",
|
|
63
63
|
"commander": "^14.0.3",
|
|
64
|
-
"postcss": "^8.5.
|
|
64
|
+
"postcss": "^8.5.15",
|
|
65
65
|
"tinyglobby": "^0.2.16",
|
|
66
66
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@types/node": "^25.
|
|
70
|
-
"oxfmt": "^0.
|
|
71
|
-
"oxlint": "^1.
|
|
72
|
-
"tsdown": "^0.
|
|
69
|
+
"@types/node": "^25.9.1",
|
|
70
|
+
"oxfmt": "^0.51.0",
|
|
71
|
+
"oxlint": "^1.66.0",
|
|
72
|
+
"tsdown": "^0.22.0",
|
|
73
73
|
"typescript": "^6.0.3",
|
|
74
|
-
"vitest": "^4.1.
|
|
74
|
+
"vitest": "^4.1.7"
|
|
75
75
|
},
|
|
76
76
|
"engines": {
|
|
77
77
|
"node": ">=22.0.0",
|
|
78
78
|
"pnpm": ">=10.0.0"
|
|
79
79
|
},
|
|
80
|
-
"packageManager": "pnpm@
|
|
80
|
+
"packageManager": "pnpm@11.2.2"
|
|
81
81
|
}
|