tailwind-lint 0.1.0 → 0.2.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/dist/cli.cjs +11 -12
- package/dist/cli.cjs.map +1 -1
- package/dist/{constants-Bstz7FuV.cjs → constants-BqCgJ23N.cjs} +1 -1
- package/dist/{constants-BFubEpZ9.cjs → constants-DgveH41I.cjs} +40 -4
- package/dist/{constants-BFubEpZ9.cjs.map → constants-DgveH41I.cjs.map} +1 -1
- package/dist/{linter-QRh7wAZ7.cjs → linter-psTnhyzO.cjs} +57 -84
- package/dist/linter-psTnhyzO.cjs.map +1 -0
- package/dist/linter.cjs +1 -1
- package/package.json +1 -1
- package/dist/linter-QRh7wAZ7.cjs.map +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_linter = require('./linter-
|
|
3
|
-
const require_constants = require('./constants-
|
|
2
|
+
const require_linter = require('./linter-psTnhyzO.cjs');
|
|
3
|
+
const require_constants = require('./constants-DgveH41I.cjs');
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
node_path = require_linter.__toESM(node_path);
|
|
6
6
|
let node_fs = require("node:fs");
|
|
@@ -10,6 +10,7 @@ chalk = require_linter.__toESM(chalk);
|
|
|
10
10
|
let commander = require("commander");
|
|
11
11
|
|
|
12
12
|
//#region src/cli.ts
|
|
13
|
+
const MAX_FILENAME_DISPLAY_LENGTH = 50;
|
|
13
14
|
function countDiagnosticsBySeverity(diagnostics) {
|
|
14
15
|
let errors = 0;
|
|
15
16
|
let warnings = 0;
|
|
@@ -45,20 +46,20 @@ function resolveOptions(files, options) {
|
|
|
45
46
|
verbose: options.verbose || false
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
|
-
function truncateFilename(filename
|
|
49
|
-
return filename.length >
|
|
49
|
+
function truncateFilename(filename) {
|
|
50
|
+
return filename.length > MAX_FILENAME_DISPLAY_LENGTH ? `...${filename.slice(-MAX_FILENAME_DISPLAY_LENGTH)}` : filename;
|
|
50
51
|
}
|
|
51
|
-
async function displayResults(files, fixMode
|
|
52
|
+
async function displayResults(files, fixMode) {
|
|
52
53
|
let totalErrors = 0;
|
|
53
54
|
let totalWarnings = 0;
|
|
54
55
|
let totalFixed = 0;
|
|
55
56
|
let filesWithIssues = 0;
|
|
56
57
|
let isFirstFile = true;
|
|
57
58
|
for (const file of files) if (file.diagnostics.length > 0 || fixMode && file.fixed) {
|
|
58
|
-
if (isFirstFile
|
|
59
|
+
if (isFirstFile) {
|
|
59
60
|
console.log();
|
|
60
61
|
isFirstFile = false;
|
|
61
|
-
} else
|
|
62
|
+
} else console.log();
|
|
62
63
|
console.log(chalk.default.underline.bold(file.path));
|
|
63
64
|
if (fixMode && file.fixed) {
|
|
64
65
|
const issueText = `${file.fixedCount || 0} issue${file.fixedCount !== 1 ? "s" : ""}`;
|
|
@@ -165,23 +166,21 @@ ${chalk.default.bold.cyan("Notes:")}
|
|
|
165
166
|
...resolved,
|
|
166
167
|
onProgress: (current, total, file) => {
|
|
167
168
|
if (process.stdout.isTTY && !resolved.verbose) {
|
|
168
|
-
const displayFile = truncateFilename(file
|
|
169
|
+
const displayFile = truncateFilename(file);
|
|
169
170
|
process.stdout.write(`\rLinting files... (${current}/${total}) ${chalk.default.dim(displayFile)}${" ".repeat(10)}`);
|
|
170
171
|
} else if (resolved.verbose) console.log(chalk.default.dim(` [${current}/${total}] Linting ${file}`));
|
|
171
172
|
}
|
|
172
173
|
});
|
|
173
|
-
if (process.stdout.isTTY && !resolved.verbose) process.stdout.write("\
|
|
174
|
+
if (process.stdout.isTTY && !resolved.verbose) process.stdout.write("\n");
|
|
174
175
|
if (results.totalFilesProcessed === 0) {
|
|
175
|
-
if (resolved.verbose) console.log();
|
|
176
176
|
console.log(chalk.default.yellow("No files found to lint."));
|
|
177
177
|
process.exit(0);
|
|
178
178
|
}
|
|
179
179
|
if (results.files.length === 0) {
|
|
180
|
-
if (resolved.verbose) console.log();
|
|
181
180
|
console.log(chalk.default.green.bold("✔ No issues found"));
|
|
182
181
|
process.exit(0);
|
|
183
182
|
}
|
|
184
|
-
await displayResults(results.files, resolved.fix
|
|
183
|
+
await displayResults(results.files, resolved.fix);
|
|
185
184
|
const hasErrors = results.files.some((file) => file.diagnostics.some((d) => d.severity === 1));
|
|
186
185
|
process.exit(hasErrors ? 1 : 0);
|
|
187
186
|
} catch (error) {
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["path","DEFAULT_FILE_PATTERN","Command","fs","DEFAULT_VERSION","lint"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport { DEFAULT_FILE_PATTERN, DEFAULT_VERSION } from \"./constants\";\nimport { lint } from \"./linter\";\nimport type { LintFileResult, SerializedDiagnostic } from \"./types\";\n\nfunction countDiagnosticsBySeverity(diagnostics: SerializedDiagnostic[]): {\n\terrors: number;\n\twarnings: number;\n} {\n\tlet errors = 0;\n\tlet warnings = 0;\n\n\tfor (const diagnostic of diagnostics) {\n\t\tif (diagnostic.severity === 1) errors++;\n\t\tif (diagnostic.severity === 2) warnings++;\n\t}\n\n\treturn { errors, warnings };\n}\n\ninterface ResolvedOptions {\n\tcwd: string;\n\tconfigPath: string | undefined;\n\tpatterns: string[];\n\tautoDiscover: boolean;\n\tfix: boolean;\n\tverbose: boolean;\n}\n\ninterface CliOptions {\n\tconfig?: string;\n\tauto?: boolean;\n\tfix?: boolean;\n\tverbose?: boolean;\n}\n\nfunction resolveOptions(files: string[], options: CliOptions): ResolvedOptions {\n\tconst hasConfigFlag = !!options.config;\n\tconst hasAutoFlag = !!options.auto;\n\tconst hasFiles = files.length > 0;\n\n\tlet cwd = process.cwd();\n\tlet configPath = options.config;\n\tlet patterns = files;\n\n\tif (hasConfigFlag && options.config && !hasFiles) {\n\t\tconst absoluteConfigPath = path.isAbsolute(options.config)\n\t\t\t? options.config\n\t\t\t: path.resolve(process.cwd(), options.config);\n\t\tcwd = path.dirname(absoluteConfigPath);\n\t\tconfigPath = path.basename(absoluteConfigPath);\n\t\tpatterns = [DEFAULT_FILE_PATTERN];\n\t}\n\n\tconst autoDiscover = hasAutoFlag;\n\n\treturn {\n\t\tcwd,\n\t\tconfigPath,\n\t\tpatterns: autoDiscover ? [] : patterns,\n\t\tautoDiscover,\n\t\tfix: options.fix || false,\n\t\tverbose: options.verbose || false,\n\t};\n}\n\nfunction truncateFilename(filename: string, maxLength: number): string {\n\treturn filename.length > maxLength\n\t\t? `...${filename.slice(-maxLength)}`\n\t\t: filename;\n}\n\nasync function displayResults(\n\tfiles: LintFileResult[],\n\tfixMode: boolean,\n\tverbose: boolean,\n): Promise<void> {\n\tlet totalErrors = 0;\n\tlet totalWarnings = 0;\n\tlet totalFixed = 0;\n\tlet filesWithIssues = 0;\n\tlet isFirstFile = true;\n\n\tfor (const file of files) {\n\t\tif (file.diagnostics.length > 0 || (fixMode && file.fixed)) {\n\t\t\tif (isFirstFile && verbose) {\n\t\t\t\tconsole.log();\n\t\t\t\tisFirstFile = false;\n\t\t\t} else if (!isFirstFile) {\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t\tconsole.log(chalk.underline.bold(file.path));\n\n\t\t\tif (fixMode && file.fixed) {\n\t\t\t\tconst issueText = `${file.fixedCount || 0} issue${file.fixedCount !== 1 ? \"s\" : \"\"}`;\n\t\t\t\tconsole.log(chalk.green(` ✔ Fixed ${issueText}`));\n\t\t\t\ttotalFixed += file.fixedCount || 0;\n\t\t\t}\n\n\t\t\tconst { errors, warnings } = countDiagnosticsBySeverity(file.diagnostics);\n\t\t\ttotalErrors += errors;\n\t\t\ttotalWarnings += warnings;\n\n\t\t\tif (file.diagnostics.length > 0) {\n\t\t\t\tfilesWithIssues++;\n\t\t\t}\n\n\t\t\tfor (const diagnostic of file.diagnostics) {\n\t\t\t\tconst line = diagnostic.range.start.line + 1;\n\t\t\t\tconst char = diagnostic.range.start.character + 1;\n\t\t\t\tconst severity = diagnostic.severity === 1 ? \"error\" : \"warning\";\n\t\t\t\tconst severityColor =\n\t\t\t\t\tdiagnostic.severity === 1\n\t\t\t\t\t\t? chalk.red(severity)\n\t\t\t\t\t\t: chalk.yellow(severity);\n\t\t\t\tconst code = diagnostic.code ? chalk.dim(` (${diagnostic.code})`) : \"\";\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${chalk.dim(`${line}:${char}`)} ${severityColor} ${diagnostic.message}${code}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconsole.log();\n\n\tif (totalErrors === 0 && totalWarnings === 0) {\n\t\tif (totalFixed > 0) {\n\t\t\tconst issueText = `${totalFixed} issue${totalFixed !== 1 ? \"s\" : \"\"}`;\n\t\t\tconsole.log(chalk.green.bold(`✔ Fixed ${issueText}`));\n\t\t} else {\n\t\t\tconsole.log(chalk.green.bold(\"✔ No issues found\"));\n\t\t}\n\t} else {\n\t\tconst parts = [];\n\t\tif (totalErrors > 0) {\n\t\t\tparts.push(`${totalErrors} error${totalErrors !== 1 ? \"s\" : \"\"}`);\n\t\t}\n\t\tif (totalWarnings > 0) {\n\t\t\tparts.push(`${totalWarnings} warning${totalWarnings !== 1 ? \"s\" : \"\"}`);\n\t\t}\n\n\t\tconst fileText = `${filesWithIssues} file${filesWithIssues !== 1 ? \"s\" : \"\"}`;\n\t\tconst summary = `Found ${parts.join(\" and \")} in ${fileText}`;\n\n\t\tif (totalFixed > 0) {\n\t\t\tconst issueText = `${totalFixed} issue${totalFixed !== 1 ? \"s\" : \"\"}`;\n\t\t\tconsole.log(chalk.green.bold(`✔ Fixed ${issueText}`));\n\t\t\tconsole.log(summary);\n\t\t} else {\n\t\t\tconsole.log(summary);\n\t\t}\n\t}\n}\n\nconst program = new Command();\n\nconst getVersion = (): string => {\n\tconst packageJsonPath = path.join(__dirname, \"../package.json\");\n\ttry {\n\t\tconst pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n\t\treturn pkg.version || DEFAULT_VERSION;\n\t} catch {\n\t\treturn DEFAULT_VERSION;\n\t}\n};\n\nprogram.configureHelp({\n\tformatHelp: (cmd, helper) => {\n\t\tconst termWidth = helper.padWidth(cmd, helper);\n\t\tlet output = \"\";\n\n\t\toutput += `${chalk.bold.cyan(\"Usage:\")} ${helper.commandUsage(cmd)}\\n\\n`;\n\n\t\tif (cmd.description()) {\n\t\t\toutput += `${cmd.description()}\\n\\n`;\n\t\t}\n\n\t\tconst args = helper.visibleArguments(cmd);\n\t\tif (args.length > 0) {\n\t\t\toutput += `${chalk.bold.cyan(\"Arguments:\")}\\n`;\n\t\t\targs.forEach((arg) => {\n\t\t\t\tconst argName = arg.required ? `<${arg.name()}>` : `[${arg.name()}]`;\n\t\t\t\toutput += ` ${chalk.green(argName.padEnd(termWidth))} ${arg.description}\\n`;\n\t\t\t});\n\t\t\toutput += \"\\n\";\n\t\t}\n\n\t\tconst options = helper.visibleOptions(cmd);\n\t\tif (options.length > 0) {\n\t\t\toutput += `${chalk.bold.cyan(\"Options:\")}\\n`;\n\t\t\toptions.forEach((option) => {\n\t\t\t\tconst flags = helper.optionTerm(option);\n\t\t\t\tconst description = helper.optionDescription(option);\n\t\t\t\toutput += ` ${chalk.yellow(flags.padEnd(termWidth))} ${description}\\n`;\n\t\t\t});\n\t\t\toutput += \"\\n\";\n\t\t}\n\n\t\treturn output;\n\t},\n});\n\nprogram\n\t.name(\"tailwind-lint\")\n\t.description(\"A CLI tool for linting Tailwind CSS class usage\")\n\t.version(getVersion())\n\t.argument(\n\t\t\"[files...]\",\n\t\t'File patterns to lint (e.g., \"src/**/*.{js,jsx,ts,tsx}\")',\n\t)\n\t.option(\n\t\t\"-c, --config <path>\",\n\t\t\"Path to Tailwind config file (default: auto-discover)\",\n\t)\n\t.option(\n\t\t\"-a, --auto\",\n\t\t\"Auto-discover files from Tailwind config content patterns\",\n\t)\n\t.option(\"--fix\", \"Automatically fix problems that can be fixed\")\n\t.option(\"-v, --verbose\", \"Enable verbose logging for debugging\")\n\t.addHelpText(\n\t\t\"after\",\n\t\t`\n${chalk.bold.cyan(\"Examples:\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"src/**/*.{js,jsx,ts,tsx}\"')}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.yellow(\"--auto\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.yellow(\"--config\")} ${chalk.green(\"./tailwind.config.js\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"src/**/*.tsx\"')} ${chalk.yellow(\"--fix\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"**/*.vue\"')}\n\n${chalk.bold.cyan(\"Notes:\")}\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--auto\")} to auto-discover files from your Tailwind config (v3 only)\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--config\")} alone to lint common file types from that directory\n ${chalk.dim(\"•\")} Default pattern: ${chalk.dim(\"./**/*.{js,jsx,ts,tsx,html}\")}\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--fix\")} to automatically resolve fixable issues\n`,\n\t)\n\t.action(async (files: string[], options) => {\n\t\tconst hasConfigFlag = !!options.config;\n\t\tconst hasAutoFlag = !!options.auto;\n\t\tconst hasFiles = files.length > 0;\n\n\t\tif (!hasFiles && !hasAutoFlag && !hasConfigFlag) {\n\t\t\tconsole.error(\n\t\t\t\t\"Error: No files specified. Use glob patterns, --auto flag, or --config flag.\\n\",\n\t\t\t);\n\t\t\tprogram.help();\n\t\t}\n\n\t\tconst resolved = resolveOptions(files, options);\n\n\t\ttry {\n\t\t\tif (resolved.verbose) {\n\t\t\t\tconsole.log(chalk.cyan(\"→ Running in verbose mode\"));\n\t\t\t\tconsole.log(chalk.dim(` Working directory: ${resolved.cwd}`));\n\t\t\t\tconsole.log(\n\t\t\t\t\tchalk.dim(` Config path: ${resolved.configPath || \"auto-discover\"}`),\n\t\t\t\t);\n\t\t\t\tconsole.log(chalk.dim(` Fix mode: ${resolved.fix}`));\n\t\t\t\tconsole.log(\n\t\t\t\t\tchalk.dim(\n\t\t\t\t\t\t` Patterns: ${resolved.patterns.length > 0 ? resolved.patterns.join(\", \") : \"auto-discover\"}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconsole.log();\n\n\t\t\tconst results = await lint({\n\t\t\t\t...resolved,\n\t\t\t\tonProgress: (current, total, file) => {\n\t\t\t\t\tif (process.stdout.isTTY && !resolved.verbose) {\n\t\t\t\t\t\tconst displayFile = truncateFilename(file, 50);\n\t\t\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\t\t`\\rLinting files... (${current}/${total}) ${chalk.dim(displayFile)}${\" \".repeat(10)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (resolved.verbose) {\n\t\t\t\t\t\tconsole.log(chalk.dim(` [${current}/${total}] Linting ${file}`));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (process.stdout.isTTY && !resolved.verbose) {\n\t\t\t\tprocess.stdout.write(\"\\r\\x1b[K\");\n\t\t\t}\n\n\t\t\tif (results.totalFilesProcessed === 0) {\n\t\t\t\tif (resolved.verbose) {\n\t\t\t\t\tconsole.log();\n\t\t\t\t}\n\t\t\t\tconsole.log(chalk.yellow(\"No files found to lint.\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\tif (results.files.length === 0) {\n\t\t\t\tif (resolved.verbose) {\n\t\t\t\t\tconsole.log();\n\t\t\t\t}\n\t\t\t\tconsole.log(chalk.green.bold(\"✔ No issues found\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\tawait displayResults(results.files, resolved.fix, resolved.verbose);\n\n\t\t\tconst hasErrors = results.files.some((file) =>\n\t\t\t\tfile.diagnostics.some((d) => d.severity === 1),\n\t\t\t);\n\t\t\tprocess.exit(hasErrors ? 1 : 0);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(chalk.red(\"✖ Error:\"), errorMessage);\n\n\t\t\tif (resolved.verbose && error instanceof Error) {\n\t\t\t\tconsole.error(chalk.dim(\"\\nStack trace:\"));\n\t\t\t\tconsole.error(chalk.dim(error.stack || error.toString()));\n\t\t\t}\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["path","DEFAULT_FILE_PATTERN","Command","fs","DEFAULT_VERSION","lint"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport { DEFAULT_FILE_PATTERN, DEFAULT_VERSION } from \"./constants\";\nimport { lint } from \"./linter\";\nimport type { LintFileResult, SerializedDiagnostic } from \"./types\";\n\nconst MAX_FILENAME_DISPLAY_LENGTH = 50;\n\nfunction countDiagnosticsBySeverity(diagnostics: SerializedDiagnostic[]): {\n\terrors: number;\n\twarnings: number;\n} {\n\tlet errors = 0;\n\tlet warnings = 0;\n\n\tfor (const diagnostic of diagnostics) {\n\t\tif (diagnostic.severity === 1) errors++;\n\t\tif (diagnostic.severity === 2) warnings++;\n\t}\n\n\treturn { errors, warnings };\n}\n\ninterface ResolvedOptions {\n\tcwd: string;\n\tconfigPath: string | undefined;\n\tpatterns: string[];\n\tautoDiscover: boolean;\n\tfix: boolean;\n\tverbose: boolean;\n}\n\ninterface CliOptions {\n\tconfig?: string;\n\tauto?: boolean;\n\tfix?: boolean;\n\tverbose?: boolean;\n}\n\nfunction resolveOptions(files: string[], options: CliOptions): ResolvedOptions {\n\tconst hasConfigFlag = !!options.config;\n\tconst hasAutoFlag = !!options.auto;\n\tconst hasFiles = files.length > 0;\n\n\tlet cwd = process.cwd();\n\tlet configPath = options.config;\n\tlet patterns = files;\n\n\tif (hasConfigFlag && options.config && !hasFiles) {\n\t\tconst absoluteConfigPath = path.isAbsolute(options.config)\n\t\t\t? options.config\n\t\t\t: path.resolve(process.cwd(), options.config);\n\t\tcwd = path.dirname(absoluteConfigPath);\n\t\tconfigPath = path.basename(absoluteConfigPath);\n\t\tpatterns = [DEFAULT_FILE_PATTERN];\n\t}\n\n\tconst autoDiscover = hasAutoFlag;\n\n\treturn {\n\t\tcwd,\n\t\tconfigPath,\n\t\tpatterns: autoDiscover ? [] : patterns,\n\t\tautoDiscover,\n\t\tfix: options.fix || false,\n\t\tverbose: options.verbose || false,\n\t};\n}\n\nfunction truncateFilename(filename: string): string {\n\treturn filename.length > MAX_FILENAME_DISPLAY_LENGTH\n\t\t? `...${filename.slice(-MAX_FILENAME_DISPLAY_LENGTH)}`\n\t\t: filename;\n}\n\nasync function displayResults(\n\tfiles: LintFileResult[],\n\tfixMode: boolean,\n): Promise<void> {\n\tlet totalErrors = 0;\n\tlet totalWarnings = 0;\n\tlet totalFixed = 0;\n\tlet filesWithIssues = 0;\n\tlet isFirstFile = true;\n\n\tfor (const file of files) {\n\t\tif (file.diagnostics.length > 0 || (fixMode && file.fixed)) {\n\t\t\tif (isFirstFile) {\n\t\t\t\tconsole.log();\n\t\t\t\tisFirstFile = false;\n\t\t\t} else {\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t\tconsole.log(chalk.underline.bold(file.path));\n\n\t\t\tif (fixMode && file.fixed) {\n\t\t\t\tconst issueText = `${file.fixedCount || 0} issue${file.fixedCount !== 1 ? \"s\" : \"\"}`;\n\t\t\t\tconsole.log(chalk.green(` ✔ Fixed ${issueText}`));\n\t\t\t\ttotalFixed += file.fixedCount || 0;\n\t\t\t}\n\n\t\t\tconst { errors, warnings } = countDiagnosticsBySeverity(file.diagnostics);\n\t\t\ttotalErrors += errors;\n\t\t\ttotalWarnings += warnings;\n\n\t\t\tif (file.diagnostics.length > 0) {\n\t\t\t\tfilesWithIssues++;\n\t\t\t}\n\n\t\t\tfor (const diagnostic of file.diagnostics) {\n\t\t\t\tconst line = diagnostic.range.start.line + 1;\n\t\t\t\tconst char = diagnostic.range.start.character + 1;\n\t\t\t\tconst severity = diagnostic.severity === 1 ? \"error\" : \"warning\";\n\t\t\t\tconst severityColor =\n\t\t\t\t\tdiagnostic.severity === 1\n\t\t\t\t\t\t? chalk.red(severity)\n\t\t\t\t\t\t: chalk.yellow(severity);\n\t\t\t\tconst code = diagnostic.code ? chalk.dim(` (${diagnostic.code})`) : \"\";\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${chalk.dim(`${line}:${char}`)} ${severityColor} ${diagnostic.message}${code}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconsole.log();\n\n\tif (totalErrors === 0 && totalWarnings === 0) {\n\t\tif (totalFixed > 0) {\n\t\t\tconst issueText = `${totalFixed} issue${totalFixed !== 1 ? \"s\" : \"\"}`;\n\t\t\tconsole.log(chalk.green.bold(`✔ Fixed ${issueText}`));\n\t\t} else {\n\t\t\tconsole.log(chalk.green.bold(\"✔ No issues found\"));\n\t\t}\n\t} else {\n\t\tconst parts = [];\n\t\tif (totalErrors > 0) {\n\t\t\tparts.push(`${totalErrors} error${totalErrors !== 1 ? \"s\" : \"\"}`);\n\t\t}\n\t\tif (totalWarnings > 0) {\n\t\t\tparts.push(`${totalWarnings} warning${totalWarnings !== 1 ? \"s\" : \"\"}`);\n\t\t}\n\n\t\tconst fileText = `${filesWithIssues} file${filesWithIssues !== 1 ? \"s\" : \"\"}`;\n\t\tconst summary = `Found ${parts.join(\" and \")} in ${fileText}`;\n\n\t\tif (totalFixed > 0) {\n\t\t\tconst issueText = `${totalFixed} issue${totalFixed !== 1 ? \"s\" : \"\"}`;\n\t\t\tconsole.log(chalk.green.bold(`✔ Fixed ${issueText}`));\n\t\t\tconsole.log(summary);\n\t\t} else {\n\t\t\tconsole.log(summary);\n\t\t}\n\t}\n}\n\nconst program = new Command();\n\nconst getVersion = (): string => {\n\tconst packageJsonPath = path.join(__dirname, \"../package.json\");\n\ttry {\n\t\tconst pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n\t\treturn pkg.version || DEFAULT_VERSION;\n\t} catch {\n\t\treturn DEFAULT_VERSION;\n\t}\n};\n\nprogram.configureHelp({\n\tformatHelp: (cmd, helper) => {\n\t\tconst termWidth = helper.padWidth(cmd, helper);\n\t\tlet output = \"\";\n\n\t\toutput += `${chalk.bold.cyan(\"Usage:\")} ${helper.commandUsage(cmd)}\\n\\n`;\n\n\t\tif (cmd.description()) {\n\t\t\toutput += `${cmd.description()}\\n\\n`;\n\t\t}\n\n\t\tconst args = helper.visibleArguments(cmd);\n\t\tif (args.length > 0) {\n\t\t\toutput += `${chalk.bold.cyan(\"Arguments:\")}\\n`;\n\t\t\targs.forEach((arg) => {\n\t\t\t\tconst argName = arg.required ? `<${arg.name()}>` : `[${arg.name()}]`;\n\t\t\t\toutput += ` ${chalk.green(argName.padEnd(termWidth))} ${arg.description}\\n`;\n\t\t\t});\n\t\t\toutput += \"\\n\";\n\t\t}\n\n\t\tconst options = helper.visibleOptions(cmd);\n\t\tif (options.length > 0) {\n\t\t\toutput += `${chalk.bold.cyan(\"Options:\")}\\n`;\n\t\t\toptions.forEach((option) => {\n\t\t\t\tconst flags = helper.optionTerm(option);\n\t\t\t\tconst description = helper.optionDescription(option);\n\t\t\t\toutput += ` ${chalk.yellow(flags.padEnd(termWidth))} ${description}\\n`;\n\t\t\t});\n\t\t\toutput += \"\\n\";\n\t\t}\n\n\t\treturn output;\n\t},\n});\n\nprogram\n\t.name(\"tailwind-lint\")\n\t.description(\"A CLI tool for linting Tailwind CSS class usage\")\n\t.version(getVersion())\n\t.argument(\n\t\t\"[files...]\",\n\t\t'File patterns to lint (e.g., \"src/**/*.{js,jsx,ts,tsx}\")',\n\t)\n\t.option(\n\t\t\"-c, --config <path>\",\n\t\t\"Path to Tailwind config file (default: auto-discover)\",\n\t)\n\t.option(\n\t\t\"-a, --auto\",\n\t\t\"Auto-discover files from Tailwind config content patterns\",\n\t)\n\t.option(\"--fix\", \"Automatically fix problems that can be fixed\")\n\t.option(\"-v, --verbose\", \"Enable verbose logging for debugging\")\n\t.addHelpText(\n\t\t\"after\",\n\t\t`\n${chalk.bold.cyan(\"Examples:\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"src/**/*.{js,jsx,ts,tsx}\"')}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.yellow(\"--auto\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.yellow(\"--config\")} ${chalk.green(\"./tailwind.config.js\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"src/**/*.tsx\"')} ${chalk.yellow(\"--fix\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"**/*.vue\"')}\n\n${chalk.bold.cyan(\"Notes:\")}\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--auto\")} to auto-discover files from your Tailwind config (v3 only)\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--config\")} alone to lint common file types from that directory\n ${chalk.dim(\"•\")} Default pattern: ${chalk.dim(\"./**/*.{js,jsx,ts,tsx,html}\")}\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--fix\")} to automatically resolve fixable issues\n`,\n\t)\n\t.action(async (files: string[], options) => {\n\t\tconst hasConfigFlag = !!options.config;\n\t\tconst hasAutoFlag = !!options.auto;\n\t\tconst hasFiles = files.length > 0;\n\n\t\tif (!hasFiles && !hasAutoFlag && !hasConfigFlag) {\n\t\t\tconsole.error(\n\t\t\t\t\"Error: No files specified. Use glob patterns, --auto flag, or --config flag.\\n\",\n\t\t\t);\n\t\t\tprogram.help();\n\t\t}\n\n\t\tconst resolved = resolveOptions(files, options);\n\n\t\ttry {\n\t\t\tif (resolved.verbose) {\n\t\t\t\tconsole.log(chalk.cyan(\"→ Running in verbose mode\"));\n\t\t\t\tconsole.log(chalk.dim(` Working directory: ${resolved.cwd}`));\n\t\t\t\tconsole.log(\n\t\t\t\t\tchalk.dim(` Config path: ${resolved.configPath || \"auto-discover\"}`),\n\t\t\t\t);\n\t\t\t\tconsole.log(chalk.dim(` Fix mode: ${resolved.fix}`));\n\t\t\t\tconsole.log(\n\t\t\t\t\tchalk.dim(\n\t\t\t\t\t\t` Patterns: ${resolved.patterns.length > 0 ? resolved.patterns.join(\", \") : \"auto-discover\"}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconsole.log();\n\n\t\t\tconst results = await lint({\n\t\t\t\t...resolved,\n\t\t\t\tonProgress: (current, total, file) => {\n\t\t\t\t\tif (process.stdout.isTTY && !resolved.verbose) {\n\t\t\t\t\t\tconst displayFile = truncateFilename(file);\n\t\t\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\t\t`\\rLinting files... (${current}/${total}) ${chalk.dim(displayFile)}${\" \".repeat(10)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (resolved.verbose) {\n\t\t\t\t\t\tconsole.log(chalk.dim(` [${current}/${total}] Linting ${file}`));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (process.stdout.isTTY && !resolved.verbose) {\n\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t}\n\n\t\t\tif (results.totalFilesProcessed === 0) {\n\t\t\t\tconsole.log(chalk.yellow(\"No files found to lint.\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\tif (results.files.length === 0) {\n\t\t\t\tconsole.log(chalk.green.bold(\"✔ No issues found\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\tawait displayResults(results.files, resolved.fix);\n\n\t\t\tconst hasErrors = results.files.some((file) =>\n\t\t\t\tfile.diagnostics.some((d) => d.severity === 1),\n\t\t\t);\n\t\t\tprocess.exit(hasErrors ? 1 : 0);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(chalk.red(\"✖ Error:\"), errorMessage);\n\n\t\t\tif (resolved.verbose && error instanceof Error) {\n\t\t\t\tconsole.error(chalk.dim(\"\\nStack trace:\"));\n\t\t\t\tconsole.error(chalk.dim(error.stack || error.toString()));\n\t\t\t}\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram.parse();\n"],"mappings":"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"}
|
|
@@ -32,13 +32,43 @@ const V4_CSS_FOLDERS = [
|
|
|
32
32
|
"./app/",
|
|
33
33
|
"./styles/"
|
|
34
34
|
];
|
|
35
|
+
const LANGUAGE_MAP = {
|
|
36
|
+
".astro": "astro",
|
|
37
|
+
".css": "css",
|
|
38
|
+
".erb": "erb",
|
|
39
|
+
".hbs": "handlebars",
|
|
40
|
+
".htm": "html",
|
|
41
|
+
".html": "html",
|
|
42
|
+
".js": "javascript",
|
|
43
|
+
".jsx": "javascriptreact",
|
|
44
|
+
".less": "less",
|
|
45
|
+
".md": "markdown",
|
|
46
|
+
".mdx": "mdx",
|
|
47
|
+
".php": "php",
|
|
48
|
+
".sass": "sass",
|
|
49
|
+
".scss": "scss",
|
|
50
|
+
".svelte": "svelte",
|
|
51
|
+
".ts": "typescript",
|
|
52
|
+
".tsx": "typescriptreact",
|
|
53
|
+
".twig": "twig",
|
|
54
|
+
".vue": "vue"
|
|
55
|
+
};
|
|
35
56
|
const DEFAULT_VERSION = "0.0.1";
|
|
36
|
-
const MAX_FIX_ITERATIONS = 10;
|
|
37
57
|
const DEFAULT_TAB_SIZE = 2;
|
|
38
58
|
const DEFAULT_SEPARATOR = ":";
|
|
39
59
|
const DEFAULT_ROOT_FONT_SIZE = 16;
|
|
60
|
+
const CONCURRENT_FILES = 10;
|
|
61
|
+
function getLanguageId(filePath) {
|
|
62
|
+
return LANGUAGE_MAP[filePath.substring(filePath.lastIndexOf(".")).toLowerCase()] || "html";
|
|
63
|
+
}
|
|
40
64
|
|
|
41
65
|
//#endregion
|
|
66
|
+
Object.defineProperty(exports, 'CONCURRENT_FILES', {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return CONCURRENT_FILES;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
42
72
|
Object.defineProperty(exports, 'DEFAULT_FILE_PATTERN', {
|
|
43
73
|
enumerable: true,
|
|
44
74
|
get: function () {
|
|
@@ -75,10 +105,10 @@ Object.defineProperty(exports, 'DEFAULT_VERSION', {
|
|
|
75
105
|
return DEFAULT_VERSION;
|
|
76
106
|
}
|
|
77
107
|
});
|
|
78
|
-
Object.defineProperty(exports, '
|
|
108
|
+
Object.defineProperty(exports, 'LANGUAGE_MAP', {
|
|
79
109
|
enumerable: true,
|
|
80
110
|
get: function () {
|
|
81
|
-
return
|
|
111
|
+
return LANGUAGE_MAP;
|
|
82
112
|
}
|
|
83
113
|
});
|
|
84
114
|
Object.defineProperty(exports, 'V3_CONFIG_PATHS', {
|
|
@@ -99,4 +129,10 @@ Object.defineProperty(exports, 'V4_CSS_NAMES', {
|
|
|
99
129
|
return V4_CSS_NAMES;
|
|
100
130
|
}
|
|
101
131
|
});
|
|
102
|
-
|
|
132
|
+
Object.defineProperty(exports, 'getLanguageId', {
|
|
133
|
+
enumerable: true,
|
|
134
|
+
get: function () {
|
|
135
|
+
return getLanguageId;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=constants-DgveH41I.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants-
|
|
1
|
+
{"version":3,"file":"constants-DgveH41I.cjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["export const DEFAULT_IGNORE_PATTERNS = [\n\t\"**/node_modules/**\",\n\t\"**/dist/**\",\n\t\"**/build/**\",\n\t\"**/.git/**\",\n\t\"**/.next/**\",\n\t\"**/.nuxt/**\",\n\t\"**/coverage/**\",\n\t\"**/.vscode/**\",\n\t\"**/.idea/**\",\n\t\"**/.cache/**\",\n\t\"**/.DS_Store/**\",\n];\n\nexport const DEFAULT_FILE_PATTERN = \"./**/*.{js,jsx,ts,tsx,html}\";\n\nexport const V3_CONFIG_PATHS = [\n\t\"tailwind.config.js\",\n\t\"tailwind.config.cjs\",\n\t\"tailwind.config.mjs\",\n\t\"tailwind.config.ts\",\n];\n\nexport const V4_CSS_NAMES = [\n\t\"app.css\",\n\t\"index.css\",\n\t\"tailwind.css\",\n\t\"globals.css\",\n];\n\nexport const V4_CSS_FOLDERS = [\"./\", \"./src/\", \"./app/\", \"./styles/\"];\n\nexport const LANGUAGE_MAP: Record<string, string> = {\n\t\".astro\": \"astro\",\n\t\".css\": \"css\",\n\t\".erb\": \"erb\",\n\t\".hbs\": \"handlebars\",\n\t\".htm\": \"html\",\n\t\".html\": \"html\",\n\t\".js\": \"javascript\",\n\t\".jsx\": \"javascriptreact\",\n\t\".less\": \"less\",\n\t\".md\": \"markdown\",\n\t\".mdx\": \"mdx\",\n\t\".php\": \"php\",\n\t\".sass\": \"sass\",\n\t\".scss\": \"scss\",\n\t\".svelte\": \"svelte\",\n\t\".ts\": \"typescript\",\n\t\".tsx\": \"typescriptreact\",\n\t\".twig\": \"twig\",\n\t\".vue\": \"vue\",\n};\n\nexport const DEFAULT_VERSION = \"0.0.1\";\n\nexport const DEFAULT_TAB_SIZE = 2;\n\nexport const DEFAULT_SEPARATOR = \":\";\n\nexport const DEFAULT_ROOT_FONT_SIZE = 16;\n\nexport const CONCURRENT_FILES = 10;\n\nexport function getLanguageId(filePath: string): string {\n\tconst ext = filePath.substring(filePath.lastIndexOf(\".\")).toLowerCase();\n\treturn LANGUAGE_MAP[ext] || \"html\";\n}\n"],"mappings":";;AAAA,MAAa,0BAA0B;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAED,MAAa,uBAAuB;AAEpC,MAAa,kBAAkB;CAC9B;CACA;CACA;CACA;CACA;AAED,MAAa,eAAe;CAC3B;CACA;CACA;CACA;CACA;AAED,MAAa,iBAAiB;CAAC;CAAM;CAAU;CAAU;CAAY;AAErE,MAAa,eAAuC;CACnD,UAAU;CACV,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,OAAO;CACP,QAAQ;CACR,SAAS;CACT,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,SAAS;CACT,WAAW;CACX,OAAO;CACP,QAAQ;CACR,SAAS;CACT,QAAQ;CACR;AAED,MAAa,kBAAkB;AAE/B,MAAa,mBAAmB;AAEhC,MAAa,oBAAoB;AAEjC,MAAa,yBAAyB;AAEtC,MAAa,mBAAmB;AAEhC,SAAgB,cAAc,UAA0B;AAEvD,QAAO,aADK,SAAS,UAAU,SAAS,YAAY,IAAI,CAAC,CAAC,aAAa,KAC3C"}
|
|
@@ -25,7 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
|
-
const require_constants = require('./constants-
|
|
28
|
+
const require_constants = require('./constants-DgveH41I.cjs');
|
|
29
29
|
let node_path = require("node:path");
|
|
30
30
|
node_path = __toESM(node_path);
|
|
31
31
|
let _tailwindcss_language_service = require("@tailwindcss/language-service");
|
|
@@ -37,29 +37,6 @@ node_fs = __toESM(node_fs);
|
|
|
37
37
|
let node_module = require("node:module");
|
|
38
38
|
|
|
39
39
|
//#region src/code-actions.ts
|
|
40
|
-
function getLanguageId$1(filePath) {
|
|
41
|
-
return {
|
|
42
|
-
".astro": "astro",
|
|
43
|
-
".css": "css",
|
|
44
|
-
".erb": "erb",
|
|
45
|
-
".hbs": "handlebars",
|
|
46
|
-
".htm": "html",
|
|
47
|
-
".html": "html",
|
|
48
|
-
".js": "javascript",
|
|
49
|
-
".jsx": "javascriptreact",
|
|
50
|
-
".less": "less",
|
|
51
|
-
".md": "markdown",
|
|
52
|
-
".mdx": "mdx",
|
|
53
|
-
".php": "php",
|
|
54
|
-
".sass": "sass",
|
|
55
|
-
".scss": "scss",
|
|
56
|
-
".svelte": "svelte",
|
|
57
|
-
".ts": "typescript",
|
|
58
|
-
".tsx": "typescriptreact",
|
|
59
|
-
".twig": "twig",
|
|
60
|
-
".vue": "vue"
|
|
61
|
-
}[node_path.extname(filePath).toLowerCase()] || "html";
|
|
62
|
-
}
|
|
63
40
|
async function getQuickfixes(state, document, uri, diagnostics) {
|
|
64
41
|
const lspDiagnostics = diagnostics.map((diag) => ({
|
|
65
42
|
range: diag.range,
|
|
@@ -104,31 +81,40 @@ async function applyCodeActions(state, filePath, content, diagnostics) {
|
|
|
104
81
|
changed: false,
|
|
105
82
|
fixedCount: 0
|
|
106
83
|
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
84
|
+
try {
|
|
85
|
+
const languageId = require_constants.getLanguageId(filePath);
|
|
86
|
+
const uri = `file://${filePath}`;
|
|
87
|
+
let currentDocument = vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content);
|
|
88
|
+
let currentContent = content;
|
|
89
|
+
let totalFixed = 0;
|
|
90
|
+
while (true) {
|
|
91
|
+
const currentDiagnostics = await (0, _tailwindcss_language_service.doValidate)(state, currentDocument);
|
|
92
|
+
if (currentDiagnostics.length === 0) break;
|
|
93
|
+
const quickfixes = await getQuickfixes(state, currentDocument, uri, currentDiagnostics);
|
|
94
|
+
if (quickfixes.length === 0) break;
|
|
95
|
+
const fixResult = applyFirstQuickfix(quickfixes[0], uri, currentDocument, currentContent);
|
|
96
|
+
if (!fixResult) break;
|
|
97
|
+
currentContent = fixResult.content;
|
|
98
|
+
currentDocument = vscode_languageserver_textdocument.TextDocument.create(uri, languageId, currentDocument.version + 1, currentContent);
|
|
99
|
+
totalFixed++;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
content: currentContent,
|
|
103
|
+
changed: currentContent !== content,
|
|
104
|
+
fixedCount: totalFixed
|
|
105
|
+
};
|
|
106
|
+
} catch (error) {
|
|
107
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
+
if (message.includes("Cannot read") || message.includes("undefined")) {
|
|
109
|
+
console.warn(`Warning: Language service crashed while applying fixes to ${filePath}. Skipping auto-fix for this file.`);
|
|
110
|
+
return {
|
|
111
|
+
content,
|
|
112
|
+
changed: false,
|
|
113
|
+
fixedCount: 0
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
throw error;
|
|
126
117
|
}
|
|
127
|
-
return {
|
|
128
|
-
content: currentContent,
|
|
129
|
-
changed: currentContent !== content,
|
|
130
|
-
fixedCount: totalFixed
|
|
131
|
-
};
|
|
132
118
|
}
|
|
133
119
|
|
|
134
120
|
//#endregion
|
|
@@ -391,6 +377,8 @@ async function loadTailwindConfig$1(configPath) {
|
|
|
391
377
|
return config;
|
|
392
378
|
} catch (error) {
|
|
393
379
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
380
|
+
if (errorMessage.includes("Cannot find module")) throw new Error(`Failed to load config from ${configPath}.\nThe config file may have missing dependencies. Check that all imports are installed.`);
|
|
381
|
+
if (errorMessage.includes("SyntaxError") || errorMessage.includes("Unexpected token")) throw new Error(`Failed to parse config from ${configPath}.\nThe config file has syntax errors. Check your JavaScript/TypeScript syntax.`);
|
|
394
382
|
throw new Error(`Failed to load config from ${configPath}: ${errorMessage}`);
|
|
395
383
|
}
|
|
396
384
|
}
|
|
@@ -418,12 +406,12 @@ function resolveTailwindPath(cwd, configDir) {
|
|
|
418
406
|
try {
|
|
419
407
|
return require$1.resolve("tailwindcss", { paths });
|
|
420
408
|
} catch {
|
|
421
|
-
throw new Error(`Could not
|
|
409
|
+
throw new Error(`Could not find tailwindcss module in ${paths.join(" or ")}.\nInstall it with: npm install -D tailwindcss`);
|
|
422
410
|
}
|
|
423
411
|
}
|
|
424
412
|
async function createState(cwd, configPath, verbose = false) {
|
|
425
413
|
const resolvedConfigPath = await findTailwindConfigPath$1(cwd, configPath);
|
|
426
|
-
if (!resolvedConfigPath) throw new Error("Could not find
|
|
414
|
+
if (!resolvedConfigPath) throw new Error("Could not find Tailwind config file. Expected one of:\n • Tailwind v4 (CSS): app.css, index.css, tailwind.css in project root or src/\n • Tailwind v3 (JS): tailwind.config.js, tailwind.config.ts\nRun 'npx tailwindcss init' to create a config file.");
|
|
427
415
|
const isCssConfig = isCssConfigFile$1(resolvedConfigPath);
|
|
428
416
|
const tailwindcss = require$1(resolveTailwindPath(cwd, node_path.dirname(resolvedConfigPath)));
|
|
429
417
|
const version = getTailwindVersion(cwd);
|
|
@@ -500,44 +488,25 @@ function serializeDiagnostics(diagnostics) {
|
|
|
500
488
|
source: diagnostic.source
|
|
501
489
|
}));
|
|
502
490
|
}
|
|
503
|
-
function getLanguageId(filePath) {
|
|
504
|
-
return {
|
|
505
|
-
".astro": "astro",
|
|
506
|
-
".css": "css",
|
|
507
|
-
".erb": "erb",
|
|
508
|
-
".hbs": "handlebars",
|
|
509
|
-
".htm": "html",
|
|
510
|
-
".html": "html",
|
|
511
|
-
".js": "javascript",
|
|
512
|
-
".jsx": "javascriptreact",
|
|
513
|
-
".less": "less",
|
|
514
|
-
".md": "markdown",
|
|
515
|
-
".mdx": "mdx",
|
|
516
|
-
".php": "php",
|
|
517
|
-
".sass": "sass",
|
|
518
|
-
".scss": "scss",
|
|
519
|
-
".svelte": "svelte",
|
|
520
|
-
".ts": "typescript",
|
|
521
|
-
".tsx": "typescriptreact",
|
|
522
|
-
".twig": "twig",
|
|
523
|
-
".vue": "vue"
|
|
524
|
-
}[node_path.extname(filePath).toLowerCase()] || "html";
|
|
525
|
-
}
|
|
526
491
|
async function validateDocument(state, filePath, content) {
|
|
527
492
|
try {
|
|
528
493
|
if (!state) throw new Error("State is not initialized");
|
|
529
494
|
if (state.v4 && !state.designSystem) throw new Error("Design system not initialized for Tailwind v4. This might indicate a configuration issue.");
|
|
530
495
|
if (!state.v4 && !state.modules?.tailwindcss) throw new Error("Tailwind modules not initialized for Tailwind v3. This might indicate a configuration issue.");
|
|
531
|
-
const languageId = getLanguageId(filePath);
|
|
496
|
+
const languageId = require_constants.getLanguageId(filePath);
|
|
532
497
|
const uri = `file://${filePath}`;
|
|
533
498
|
return serializeDiagnostics(await (0, _tailwindcss_language_service.doValidate)(state, vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content)));
|
|
534
499
|
} catch (error) {
|
|
535
500
|
const message = error instanceof Error ? error.message : String(error);
|
|
501
|
+
if (message.includes("Cannot read") || message.includes("undefined")) {
|
|
502
|
+
console.warn(`Warning: Language service crashed while validating ${filePath}. Skipping this file.`);
|
|
503
|
+
return [];
|
|
504
|
+
}
|
|
536
505
|
throw new Error(`Failed to validate document ${filePath}: ${message}`);
|
|
537
506
|
}
|
|
538
507
|
}
|
|
539
508
|
async function findTailwindConfigPath(cwd, configPath) {
|
|
540
|
-
const { V3_CONFIG_PATHS, V4_CSS_FOLDERS, V4_CSS_NAMES } = await Promise.resolve().then(() => require("./constants-
|
|
509
|
+
const { V3_CONFIG_PATHS, V4_CSS_FOLDERS, V4_CSS_NAMES } = await Promise.resolve().then(() => require("./constants-BqCgJ23N.cjs"));
|
|
541
510
|
if (configPath) {
|
|
542
511
|
const resolved = node_path.isAbsolute(configPath) ? configPath : node_path.resolve(cwd, configPath);
|
|
543
512
|
return fileExists(resolved) ? resolved : null;
|
|
@@ -597,15 +566,15 @@ async function expandPatterns(cwd, patterns) {
|
|
|
597
566
|
}
|
|
598
567
|
async function discoverFilesFromConfig(cwd, configPath) {
|
|
599
568
|
const configFilePath = await findTailwindConfigPath(cwd, configPath);
|
|
600
|
-
if (!configFilePath) throw new Error("Could not find Tailwind config");
|
|
569
|
+
if (!configFilePath) throw new Error("Could not find Tailwind config for auto-discovery.\nUse --config to specify the path, or provide file patterns directly.");
|
|
601
570
|
if (!isCssConfigFile(configFilePath)) {
|
|
602
571
|
const config = await loadTailwindConfig(configFilePath);
|
|
603
|
-
if (!config || !config.content) throw new Error("
|
|
572
|
+
if (!config || !config.content) throw new Error("Tailwind config is missing the 'content' property.\nAdd a content array to specify which files to scan:\n content: ['./src/**/*.{js,jsx,ts,tsx}']");
|
|
604
573
|
const patterns = extractContentPatterns(config);
|
|
605
|
-
if (patterns.length === 0) throw new Error("No content patterns found in Tailwind config");
|
|
574
|
+
if (patterns.length === 0) throw new Error("No content patterns found in Tailwind config.\nEnsure your config has a content array with file patterns.");
|
|
606
575
|
return expandPatterns(cwd, patterns);
|
|
607
576
|
}
|
|
608
|
-
throw new Error("Auto-discovery is not supported for CSS-based configs
|
|
577
|
+
throw new Error("Auto-discovery is not supported for Tailwind v4 CSS-based configs.\nPlease specify file patterns explicitly:\n tailwind-lint \"src/**/*.{js,jsx,ts,tsx}\"");
|
|
609
578
|
}
|
|
610
579
|
function extractContentPatterns(config) {
|
|
611
580
|
if (!config.content) return [];
|
|
@@ -615,10 +584,14 @@ function extractContentPatterns(config) {
|
|
|
615
584
|
}
|
|
616
585
|
async function processFiles(state, cwd, files, fix, onProgress) {
|
|
617
586
|
const results = [];
|
|
618
|
-
for (let i = 0; i < files.length; i
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
587
|
+
for (let i = 0; i < files.length; i += require_constants.CONCURRENT_FILES) {
|
|
588
|
+
const batchPromises = files.slice(i, i + require_constants.CONCURRENT_FILES).map(async (file, batchIndex) => {
|
|
589
|
+
const fileIndex = i + batchIndex;
|
|
590
|
+
if (onProgress) onProgress(fileIndex + 1, files.length, file);
|
|
591
|
+
return await processFile(state, cwd, file, fix);
|
|
592
|
+
});
|
|
593
|
+
const batchResults = await Promise.all(batchPromises);
|
|
594
|
+
for (const result of batchResults) if (result) results.push(result);
|
|
622
595
|
}
|
|
623
596
|
return results;
|
|
624
597
|
}
|
|
@@ -683,4 +656,4 @@ Object.defineProperty(exports, 'lint', {
|
|
|
683
656
|
return lint;
|
|
684
657
|
}
|
|
685
658
|
});
|
|
686
|
-
//# sourceMappingURL=linter-
|
|
659
|
+
//# sourceMappingURL=linter-psTnhyzO.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linter-psTnhyzO.cjs","names":["getLanguageId","TextDocument","fs","DEFAULT_TAB_SIZE","DEFAULT_ROOT_FONT_SIZE","path","require","path","require","fileExists","fs","readFileSync","path","require","fileExists","fs","readFileSync","isCssConfigFile","loadTailwindConfig","path","findTailwindConfigPath","V3_CONFIG_PATHS","V4_CSS_FOLDERS","V4_CSS_NAMES","DEFAULT_SEPARATOR","getLanguageId","TextDocument","path","DEFAULT_IGNORE_PATTERNS","CONCURRENT_FILES"],"sources":["../src/code-actions.ts","../src/adapters/editor-state-adapter.ts","../src/types.ts","../src/adapters/v3-adapter.ts","../src/adapters/v4-adapter.ts","../src/state.ts","../src/linter.ts"],"sourcesContent":["import type { State } from \"@tailwindcss/language-service\";\nimport { doCodeActions, doValidate } from \"@tailwindcss/language-service\";\nimport type { CodeActionParams, Diagnostic } from \"vscode-languageserver\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport { getLanguageId } from \"./constants\";\nimport type { ApplyCodeActionsResult, SerializedDiagnostic } from \"./types\";\n\nexport type { ApplyCodeActionsResult };\n\ninterface QuickfixAction {\n\tkind?: string;\n\tedit?: {\n\t\tchanges?: Record<string, unknown[]>;\n\t};\n}\n\nasync function getQuickfixes(\n\tstate: State,\n\tdocument: TextDocument,\n\turi: string,\n\tdiagnostics: Diagnostic[],\n): Promise<QuickfixAction[]> {\n\tconst lspDiagnostics: Diagnostic[] = diagnostics.map((diag) => ({\n\t\trange: diag.range,\n\t\tseverity: diag.severity,\n\t\tmessage: diag.message,\n\t\tcode: diag.code,\n\t\tsource: diag.source || \"tailwindcss\",\n\t}));\n\n\tconst params: CodeActionParams = {\n\t\ttextDocument: {\n\t\t\turi,\n\t\t},\n\t\trange: {\n\t\t\tstart: {\n\t\t\t\tline: 0,\n\t\t\t\tcharacter: 0,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\tline: document.lineCount,\n\t\t\t\tcharacter: 0,\n\t\t\t},\n\t\t},\n\t\tcontext: {\n\t\t\tdiagnostics: lspDiagnostics,\n\t\t},\n\t};\n\n\tconst codeActions = await doCodeActions(state, params, document);\n\n\treturn codeActions.filter(\n\t\t(action) =>\n\t\t\taction.kind === \"quickfix\" || action.kind?.startsWith(\"quickfix.\"),\n\t) as QuickfixAction[];\n}\n\nfunction applyFirstQuickfix(\n\taction: QuickfixAction,\n\turi: string,\n\tdocument: TextDocument,\n\tcontent: string,\n): {\n\tcontent: string;\n} | null {\n\tif (!action.edit?.changes?.[uri]) return null;\n\n\tconst edits = action.edit.changes[uri] as {\n\t\trange: {\n\t\t\tstart: {\n\t\t\t\tline: number;\n\t\t\t\tcharacter: number;\n\t\t\t};\n\t\t\tend: {\n\t\t\t\tline: number;\n\t\t\t\tcharacter: number;\n\t\t\t};\n\t\t};\n\t\tnewText: string;\n\t}[];\n\n\tconst sortedEdits = [...edits].sort((a, b) => {\n\t\tconst lineDiff = b.range.start.line - a.range.start.line;\n\t\tif (lineDiff !== 0) return lineDiff;\n\t\treturn b.range.start.character - a.range.start.character;\n\t});\n\n\tlet newContent = content;\n\tfor (const edit of sortedEdits) {\n\t\tconst startOffset = document.offsetAt(edit.range.start);\n\t\tconst endOffset = document.offsetAt(edit.range.end);\n\t\tnewContent =\n\t\t\tnewContent.substring(0, startOffset) +\n\t\t\tedit.newText +\n\t\t\tnewContent.substring(endOffset);\n\t}\n\n\treturn { content: newContent };\n}\n\nexport async function applyCodeActions(\n\tstate: State,\n\tfilePath: string,\n\tcontent: string,\n\tdiagnostics: SerializedDiagnostic[],\n): Promise<ApplyCodeActionsResult> {\n\tif (diagnostics.length === 0) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\tchanged: false,\n\t\t\tfixedCount: 0,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst languageId = getLanguageId(filePath);\n\t\tconst uri = `file://${filePath}`;\n\t\tlet currentDocument = TextDocument.create(uri, languageId, 1, content);\n\t\tlet currentContent = content;\n\t\tlet totalFixed = 0;\n\n\t\t// Keep fixing until no more fixable issues remain\n\t\twhile (true) {\n\t\t\tconst currentDiagnostics = await doValidate(state, currentDocument);\n\t\t\tif (currentDiagnostics.length === 0) break;\n\n\t\t\tconst quickfixes = await getQuickfixes(\n\t\t\t\tstate,\n\t\t\t\tcurrentDocument,\n\t\t\t\turi,\n\t\t\t\tcurrentDiagnostics,\n\t\t\t);\n\t\t\tif (quickfixes.length === 0) break;\n\n\t\t\tconst fixResult = applyFirstQuickfix(\n\t\t\t\tquickfixes[0],\n\t\t\t\turi,\n\t\t\t\tcurrentDocument,\n\t\t\t\tcurrentContent,\n\t\t\t);\n\t\t\tif (!fixResult) break;\n\n\t\t\tcurrentContent = fixResult.content;\n\t\t\tcurrentDocument = TextDocument.create(\n\t\t\t\turi,\n\t\t\t\tlanguageId,\n\t\t\t\tcurrentDocument.version + 1,\n\t\t\t\tcurrentContent,\n\t\t\t);\n\t\t\ttotalFixed++;\n\t\t}\n\n\t\treturn {\n\t\t\tcontent: currentContent,\n\t\t\tchanged: currentContent !== content,\n\t\t\tfixedCount: totalFixed,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\n\t\t// Handle language service crashes gracefully\n\t\tif (message.includes(\"Cannot read\") || message.includes(\"undefined\")) {\n\t\t\tconsole.warn(\n\t\t\t\t`Warning: Language service crashed while applying fixes to ${filePath}. Skipping auto-fix for this file.`,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tcontent,\n\t\t\t\tchanged: false,\n\t\t\t\tfixedCount: 0,\n\t\t\t};\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { EditorState, Settings } from \"@tailwindcss/language-service\";\nimport { DEFAULT_ROOT_FONT_SIZE, DEFAULT_TAB_SIZE } from \"../constants\";\n\nfunction isDirectory(filePath: string): boolean {\n\ttry {\n\t\treturn fs.statSync(filePath).isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function createEditorState(cwd: string): EditorState {\n\tconst settings: Settings = {\n\t\teditor: {\n\t\t\ttabSize: DEFAULT_TAB_SIZE,\n\t\t},\n\t\ttailwindCSS: {\n\t\t\tinspectPort: null,\n\t\t\temmetCompletions: false,\n\t\t\tincludeLanguages: {},\n\t\t\tclassAttributes: [\n\t\t\t\t\"class\",\n\t\t\t\t\"className\",\n\t\t\t\t\"ngClass\",\n\t\t\t\t\"[class]\",\n\t\t\t\t\":class\",\n\t\t\t\t\"v-bind:class\",\n\t\t\t\t\"x-bind:class\",\n\t\t\t\t\"class:list\",\n\t\t\t\t\"classList\",\n\t\t\t],\n\t\t\tclassFunctions: [],\n\t\t\tcodeActions: true,\n\t\t\thovers: true,\n\t\t\tcodeLens: false,\n\t\t\tsuggestions: true,\n\t\t\tvalidate: true,\n\t\t\tcolorDecorators: true,\n\t\t\trootFontSize: DEFAULT_ROOT_FONT_SIZE,\n\t\t\tshowPixelEquivalents: true,\n\t\t\tfiles: {\n\t\t\t\texclude: [\n\t\t\t\t\t\"**/.git/**\",\n\t\t\t\t\t\"**/node_modules/**\",\n\t\t\t\t\t\"**/.hg/**\",\n\t\t\t\t\t\"**/.svn/**\",\n\t\t\t\t],\n\t\t\t},\n\t\t\texperimental: {\n\t\t\t\tconfigFile: null,\n\t\t\t\tclassRegex: [],\n\t\t\t},\n\t\t\tlint: {\n\t\t\t\tcssConflict: \"warning\",\n\t\t\t\tinvalidApply: \"error\",\n\t\t\t\tinvalidScreen: \"error\",\n\t\t\t\tinvalidVariant: \"error\",\n\t\t\t\tinvalidConfigPath: \"error\",\n\t\t\t\tinvalidTailwindDirective: \"error\",\n\t\t\t\tinvalidSourceDirective: \"error\",\n\t\t\t\trecommendedVariantOrder: \"warning\",\n\t\t\t\tusedBlocklistedClass: \"warning\",\n\t\t\t\tsuggestCanonicalClasses: \"warning\",\n\t\t\t},\n\t\t},\n\t};\n\n\treturn {\n\t\tconnection: null as unknown as EditorState[\"connection\"],\n\t\tfolder: cwd,\n\t\tuserLanguages: {},\n\t\tcapabilities: {\n\t\t\tconfiguration: true,\n\t\t\tdiagnosticRelatedInformation: true,\n\t\t\titemDefaults: [],\n\t\t},\n\t\tgetConfiguration: async () => settings,\n\t\tgetDocumentSymbols: async () => [],\n\t\treadDirectory: async (document, directory) => {\n\t\t\tconst docPath =\n\t\t\t\ttypeof document === \"string\"\n\t\t\t\t\t? document\n\t\t\t\t\t: document.uri.replace(\"file://\", \"\");\n\t\t\tconst dir = path.resolve(path.dirname(docPath), directory);\n\t\t\ttry {\n\t\t\t\tconst files = fs.readdirSync(dir);\n\t\t\t\treturn files.map((file) => [\n\t\t\t\t\tfile,\n\t\t\t\t\t{ isDirectory: isDirectory(path.join(dir, file)) },\n\t\t\t\t]);\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t};\n}\n","export interface TailwindConfig {\n\tcontent?: string[] | { files?: string[] };\n\tseparator?: string;\n\t[key: string]: unknown;\n}\n\nexport interface ResolvedTailwindConfig extends TailwindConfig {\n\tseparator: string;\n}\n\nexport interface DesignSystem {\n\tcandidatesToAst?: (candidates: string[]) => unknown[];\n\tcandidatesToCss?: (candidates: string[]) => string[];\n\t[key: string]: unknown;\n}\n\nexport interface ContextUtils {\n\t[key: string]: unknown;\n}\n\nexport interface GenerateRulesModule {\n\tgenerateRules?: (set: unknown, context: unknown) => unknown[];\n\t[key: string]: unknown;\n}\n\nexport interface SerializedDiagnostic {\n\trange: {\n\t\tstart: { line: number; character: number };\n\t\tend: { line: number; character: number };\n\t};\n\tseverity: number;\n\tmessage: string;\n\tcode?: string;\n\tsource?: string;\n}\n\nexport interface ApplyCodeActionsResult {\n\tcontent: string;\n\tchanged: boolean;\n\tfixedCount: number;\n}\n\nexport interface LintFileResult {\n\tpath: string;\n\tdiagnostics: SerializedDiagnostic[];\n\tfixed?: boolean;\n\tfixedCount?: number;\n}\n\nexport interface LintOptions {\n\tcwd: string;\n\tpatterns: string[];\n\tconfigPath?: string;\n\tautoDiscover: boolean;\n\tfix?: boolean;\n\tverbose?: boolean;\n\tonProgress?: (current: number, total: number, file: string) => void;\n}\n\nexport interface LintResult {\n\tfiles: LintFileResult[];\n\ttotalFilesProcessed: number;\n}\n\n/**\n * Error thrown when adapter fails to load required modules\n */\nexport class AdapterLoadError extends Error {\n\tconstructor(\n\t\tpublic readonly version: string,\n\t\tcause: Error,\n\t) {\n\t\tsuper(`Failed to load ${version} adapter: ${cause.message}`);\n\t\tthis.name = \"AdapterLoadError\";\n\t}\n}\n","import { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport type { ContextUtils, GenerateRulesModule } from \"../types\";\nimport { AdapterLoadError } from \"../types\";\n\nconst require = createRequire(import.meta.url || __filename);\n\nexport async function loadV3ClassMetadata(\n\tstate: State,\n\tcwd: string,\n\tverbose = false,\n): Promise<void> {\n\ttry {\n\t\tconst tailwindPath = require.resolve(\"tailwindcss\", { paths: [cwd] });\n\t\tconst tailwindcss = require(tailwindPath) as unknown;\n\n\t\ttry {\n\t\t\tconst tailwindDir = path.dirname(\n\t\t\t\trequire.resolve(\"tailwindcss/package.json\", { paths: [cwd] }),\n\t\t\t);\n\n\t\t\tconst contextUtils = require(\n\t\t\t\tpath.join(tailwindDir, \"lib\", \"lib\", \"setupContextUtils\"),\n\t\t\t) as ContextUtils;\n\t\t\tconst generateRulesModule = require(\n\t\t\t\tpath.join(tailwindDir, \"lib\", \"lib\", \"generateRules\"),\n\t\t\t) as GenerateRulesModule;\n\n\t\t\tstate.modules = {\n\t\t\t\ttailwindcss: {\n\t\t\t\t\tversion: state.version || \"unknown\",\n\t\t\t\t\tmodule: tailwindcss,\n\t\t\t\t},\n\t\t\t\tjit: {\n\t\t\t\t\tgenerateRules: {\n\t\t\t\t\t\tmodule:\n\t\t\t\t\t\t\tgenerateRulesModule.generateRules ||\n\t\t\t\t\t\t\t((_set: unknown, _context: unknown) => []),\n\t\t\t\t\t},\n\t\t\t\t\tcreateContext: {\n\t\t\t\t\t\tmodule: contextUtils.createContext,\n\t\t\t\t\t},\n\t\t\t\t\texpandApplyAtRules: {\n\t\t\t\t\t\tmodule: generateRulesModule.expandApplyAtRules,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tif (verbose) {\n\t\t\t\tconsole.log(\" ✓ Loaded v3 JIT modules\");\n\t\t\t}\n\t\t} catch (jitError) {\n\t\t\tif (verbose) {\n\t\t\t\tconst message =\n\t\t\t\t\tjitError instanceof Error ? jitError.message : String(jitError);\n\t\t\t\tconsole.log(` ⚠ Warning: Could not load v3 JIT modules: ${message}`);\n\t\t\t}\n\n\t\t\tstate.modules = {\n\t\t\t\ttailwindcss: {\n\t\t\t\t\tversion: state.version || \"unknown\",\n\t\t\t\t\tmodule: tailwindcss,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\textractConfigMetadata(state);\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tthrow new AdapterLoadError(\"v3\", error);\n\t\t}\n\t\tthrow new Error(`Failed to load v3 class metadata: ${String(error)}`);\n\t}\n}\n\nfunction extractConfigMetadata(state: State): void {\n\tconst { config } = state;\n\tif (!config || typeof config !== \"object\") return;\n\n\tconst theme = (config as Record<string, unknown>).theme as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\tstate.screens = Object.keys(\n\t\t(theme?.screens as Record<string, unknown>) ?? {},\n\t);\n\tstate.blocklist = (config.blocklist as string[] | undefined) ?? [];\n\n\tif (config.variants && typeof config.variants === \"object\") {\n\t\tstate.variants = Object.keys(config.variants).map((name) => ({\n\t\t\tname,\n\t\t\tvalues: [],\n\t\t\tisArbitrary: false,\n\t\t\thasDash: true,\n\t\t\tselectors: () => [],\n\t\t}));\n\t}\n\n\tif (config.corePlugins) {\n\t\tstate.corePlugins = Array.isArray(config.corePlugins)\n\t\t\t? (config.corePlugins as string[])\n\t\t\t: Object.keys(config.corePlugins as Record<string, unknown>);\n\t}\n}\n","import * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport type { DesignSystem } from \"../types\";\nimport { AdapterLoadError } from \"../types\";\n\nconst require = createRequire(import.meta.url || __filename);\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\treturn fs.existsSync(filePath);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readFileSync(filePath: string): string {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\treturn fs.readFileSync(filePath, \"utf-8\");\n}\n\nexport async function loadV4DesignSystem(\n\tstate: State,\n\tcwd: string,\n\tconfigPath: string,\n\tverbose = false,\n): Promise<void> {\n\ttry {\n\t\tconst tailwindPath = require.resolve(\"tailwindcss\", { paths: [cwd] });\n\t\tconst tailwindcss = require(tailwindPath) as unknown;\n\n\t\tif (\n\t\t\ttailwindcss !== null &&\n\t\t\ttailwindcss !== undefined &&\n\t\t\t(typeof tailwindcss === \"object\" || typeof tailwindcss === \"function\") &&\n\t\t\t\"__unstable__loadDesignSystem\" in tailwindcss &&\n\t\t\ttypeof tailwindcss.__unstable__loadDesignSystem === \"function\"\n\t\t) {\n\t\t\tlet cssContent: string;\n\t\t\tconst basePath = path.dirname(configPath);\n\n\t\t\tif (fileExists(configPath)) {\n\t\t\t\tcssContent = readFileSync(configPath, true);\n\t\t\t} else {\n\t\t\t\tcssContent = '@import \"tailwindcss\";';\n\t\t\t}\n\n\t\t\ttype LoadDesignSystemFn = (\n\t\t\t\tcss: string,\n\t\t\t\toptions: {\n\t\t\t\t\tbase: string;\n\t\t\t\t\tloadStylesheet: (\n\t\t\t\t\t\tid: string,\n\t\t\t\t\t\tbase: string,\n\t\t\t\t\t\tcontent?: string,\n\t\t\t\t\t) => Promise<{ base: string; content: string }>;\n\t\t\t\t},\n\t\t\t) => Promise<DesignSystem>;\n\n\t\t\tconst loadDesignSystem =\n\t\t\t\ttailwindcss.__unstable__loadDesignSystem as LoadDesignSystemFn;\n\n\t\t\tconst designSystem = await loadDesignSystem(cssContent, {\n\t\t\t\tbase: basePath,\n\t\t\t\tasync loadStylesheet(\n\t\t\t\t\t_id: string,\n\t\t\t\t\tbase: string,\n\t\t\t\t\tcontent?: string,\n\t\t\t\t): Promise<{ base: string; content: string }> {\n\t\t\t\t\tif (content) {\n\t\t\t\t\t\treturn { base, content };\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!_id.startsWith(\".\") && !_id.startsWith(\"/\")) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst pkgJsonPath = require.resolve(`${_id}/package.json`, {\n\t\t\t\t\t\t\t\tpaths: [base, cwd],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst pkgDir = path.dirname(pkgJsonPath);\n\t\t\t\t\t\t\tconst cssPath = path.join(pkgDir, \"index.css\");\n\t\t\t\t\t\t\tif (fileExists(cssPath)) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tbase: pkgDir,\n\t\t\t\t\t\t\t\t\tcontent: readFileSync(cssPath, true),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst filePath = path.resolve(base, _id);\n\t\t\t\t\tif (fileExists(filePath)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tbase: path.dirname(filePath),\n\t\t\t\t\t\t\tcontent: readFileSync(filePath, true),\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { base, content: \"\" };\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tObject.assign(designSystem, {\n\t\t\t\tdependencies: () => new Set<string>(),\n\n\t\t\t\tcompile(classes: string[]): unknown[][] {\n\t\t\t\t\tconst results = designSystem.candidatesToAst\n\t\t\t\t\t\t? designSystem.candidatesToAst(classes)\n\t\t\t\t\t\t: designSystem.candidatesToCss?.(classes) || [];\n\n\t\t\t\t\treturn results.map((result: unknown) => {\n\t\t\t\t\t\tif (Array.isArray(result)) {\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (result === null) {\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// @ts-expect-error - DesignSystem types are loaded dynamically at runtime\n\t\t\tstate.designSystem = designSystem;\n\n\t\t\tif (!state.classNames) {\n\t\t\t\tstate.classNames = {\n\t\t\t\t\tcontext: {},\n\t\t\t\t} as unknown as typeof state.classNames;\n\t\t\t}\n\n\t\t\tif (verbose) {\n\t\t\t\tconsole.log(\" ✓ Loaded v4 design system\");\n\t\t\t}\n\t\t} else {\n\t\t\tconst error = new Error(\n\t\t\t\t\"Tailwind v4 __unstable__loadDesignSystem is not available. Please ensure you have Tailwind CSS v4 installed.\",\n\t\t\t);\n\t\t\tthrow new AdapterLoadError(\"v4\", error);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof AdapterLoadError) {\n\t\t\tthrow error;\n\t\t}\n\t\tif (error instanceof Error) {\n\t\t\tthrow new AdapterLoadError(\"v4\", error);\n\t\t}\n\t\tthrow new Error(`Failed to load v4 design system: ${String(error)}`);\n\t}\n}\n","import * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport { createEditorState } from \"./adapters/editor-state-adapter\";\nimport { loadV3ClassMetadata } from \"./adapters/v3-adapter\";\nimport { loadV4DesignSystem } from \"./adapters/v4-adapter\";\nimport {\n\tDEFAULT_SEPARATOR,\n\tV3_CONFIG_PATHS,\n\tV4_CSS_FOLDERS,\n\tV4_CSS_NAMES,\n} from \"./constants\";\nimport type { ResolvedTailwindConfig, TailwindConfig } from \"./types\";\n\nconst require = createRequire(import.meta.url || __filename);\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\treturn fs.existsSync(filePath);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readFileSync(filePath: string): string {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\treturn fs.readFileSync(filePath, \"utf-8\");\n}\n\nfunction getTailwindVersion(cwd: string): string | undefined {\n\ttry {\n\t\tconst tailwindPackageJson = require.resolve(\"tailwindcss/package.json\", {\n\t\t\tpaths: [cwd],\n\t\t});\n\t\tconst pkg = JSON.parse(fs.readFileSync(tailwindPackageJson, \"utf-8\")) as {\n\t\t\tversion?: string;\n\t\t};\n\t\treturn pkg.version;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction isV4Config(version: string | undefined): boolean {\n\treturn version?.startsWith(\"4.\") ?? false;\n}\n\nfunction isCssConfigFile(filePath: string): boolean {\n\treturn filePath.endsWith(\".css\");\n}\n\nasync function loadTailwindConfig(configPath: string): Promise<TailwindConfig> {\n\tif (isCssConfigFile(configPath)) {\n\t\treturn {};\n\t}\n\n\tif (!path.isAbsolute(configPath)) {\n\t\tthrow new Error(\n\t\t\t`Config path must be absolute for security reasons: ${configPath}`,\n\t\t);\n\t}\n\n\ttry {\n\t\tdelete require.cache[configPath];\n\n\t\tconst configModule = require(configPath) as\n\t\t\t| TailwindConfig\n\t\t\t| { default: TailwindConfig };\n\t\tconst config = (\n\t\t\t\"default\" in configModule ? configModule.default : configModule\n\t\t) as TailwindConfig;\n\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new Error(\"Config must be an object\");\n\t\t}\n\n\t\treturn config;\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\n\t\tif (errorMessage.includes(\"Cannot find module\")) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to load config from ${configPath}.\\n` +\n\t\t\t\t\t\"The config file may have missing dependencies. Check that all imports are installed.\",\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\terrorMessage.includes(\"SyntaxError\") ||\n\t\t\terrorMessage.includes(\"Unexpected token\")\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse config from ${configPath}.\\n` +\n\t\t\t\t\t\"The config file has syntax errors. Check your JavaScript/TypeScript syntax.\",\n\t\t\t);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Failed to load config from ${configPath}: ${errorMessage}`,\n\t\t);\n\t}\n}\n\nasync function findTailwindConfigPath(\n\tcwd: string,\n\tconfigPath?: string,\n): Promise<string | null> {\n\tif (configPath) {\n\t\tconst resolved = path.isAbsolute(configPath)\n\t\t\t? configPath\n\t\t\t: path.resolve(cwd, configPath);\n\t\treturn fileExists(resolved) ? resolved : null;\n\t}\n\n\tfor (const p of V3_CONFIG_PATHS) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\treturn fullPath;\n\t\t}\n\t}\n\n\tconst v4Paths = V4_CSS_FOLDERS.flatMap((folder) =>\n\t\tV4_CSS_NAMES.map((name) => path.join(folder, name)),\n\t);\n\n\tfor (const p of v4Paths) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(fullPath);\n\t\t\t\tif (\n\t\t\t\t\tcontent.includes('@import \"tailwindcss\"') ||\n\t\t\t\t\tcontent.includes(\"@import 'tailwindcss'\")\n\t\t\t\t) {\n\t\t\t\t\treturn fullPath;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction resolveTailwindPath(cwd: string, configDir?: string): string {\n\tconst paths = configDir ? [configDir, cwd] : [cwd];\n\ttry {\n\t\treturn require.resolve(\"tailwindcss\", { paths });\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Could not find tailwindcss module in ${paths.join(\" or \")}.\\n` +\n\t\t\t\t\"Install it with: npm install -D tailwindcss\",\n\t\t);\n\t}\n}\n\nexport async function createState(\n\tcwd: string,\n\tconfigPath?: string,\n\tverbose = false,\n): Promise<State> {\n\tconst resolvedConfigPath = await findTailwindConfigPath(cwd, configPath);\n\n\tif (!resolvedConfigPath) {\n\t\tthrow new Error(\n\t\t\t\"Could not find Tailwind config file. Expected one of:\\n\" +\n\t\t\t\t\" • Tailwind v4 (CSS): app.css, index.css, tailwind.css in project root or src/\\n\" +\n\t\t\t\t\" • Tailwind v3 (JS): tailwind.config.js, tailwind.config.ts\\n\" +\n\t\t\t\t\"Run 'npx tailwindcss init' to create a config file.\",\n\t\t);\n\t}\n\n\tconst isCssConfig = isCssConfigFile(resolvedConfigPath);\n\tconst configDir = path.dirname(resolvedConfigPath);\n\tconst tailwindPath = resolveTailwindPath(cwd, configDir);\n\n\tconst tailwindcss = require(tailwindPath) as {\n\t\tresolveConfig?: (config: unknown) => unknown;\n\t};\n\n\tconst version = getTailwindVersion(cwd);\n\tconst isV4 = isV4Config(version);\n\n\tif (verbose) {\n\t\tconsole.log(` Tailwind version: ${version || \"unknown\"}`);\n\t\tconsole.log(` Config type: ${isCssConfig ? \"CSS (v4)\" : \"JavaScript\"}`);\n\t\tconsole.log(` Config path: ${resolvedConfigPath}`);\n\t}\n\n\tlet config: TailwindConfig = {};\n\tlet resolvedConfig: ResolvedTailwindConfig = { separator: \":\" };\n\n\tif (!isCssConfig) {\n\t\tconfig = await loadTailwindConfig(resolvedConfigPath);\n\t\tresolvedConfig = {\n\t\t\t...config,\n\t\t\tseparator: config.separator ?? DEFAULT_SEPARATOR,\n\t\t};\n\t\tif (tailwindcss.resolveConfig) {\n\t\t\tresolvedConfig = tailwindcss.resolveConfig(\n\t\t\t\tconfig,\n\t\t\t) as ResolvedTailwindConfig;\n\t\t}\n\t}\n\n\tconst state: State = {\n\t\tenabled: true,\n\t\tconfigPath: resolvedConfigPath,\n\t\tconfig: resolvedConfig,\n\t\tversion,\n\t\tv4: isV4 || undefined,\n\t\tseparator: resolvedConfig.separator || DEFAULT_SEPARATOR,\n\t\tscreens: [],\n\t\tvariants: [],\n\t\tclassNames: undefined,\n\t\tclassList: undefined,\n\t\tmodules: undefined,\n\t\tblocklist: [],\n\t\teditor: createEditorState(cwd),\n\t\tfeatures: [\"diagnostics\"] as unknown as State[\"features\"],\n\t};\n\n\tif (isV4 || isCssConfig) {\n\t\tawait loadV4DesignSystem(state, cwd, resolvedConfigPath, verbose);\n\t} else {\n\t\tawait loadV3ClassMetadata(state, cwd, verbose);\n\t}\n\n\treturn state;\n}\n","import * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport { doValidate } from \"@tailwindcss/language-service\";\nimport glob from \"fast-glob\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport { applyCodeActions } from \"./code-actions\";\nimport {\n\tCONCURRENT_FILES,\n\tDEFAULT_IGNORE_PATTERNS,\n\tgetLanguageId,\n} from \"./constants\";\nimport { createState } from \"./state\";\nimport type {\n\tLintFileResult,\n\tLintOptions,\n\tLintResult,\n\tSerializedDiagnostic,\n\tTailwindConfig,\n} from \"./types\";\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\treturn require(\"node:fs\").existsSync(filePath);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readFileSync(filePath: string): string {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\treturn require(\"node:fs\").readFileSync(filePath, \"utf-8\");\n}\n\nfunction writeFileSync(filePath: string, content: string): void {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\tif (typeof content !== \"string\") {\n\t\tthrow new TypeError(\"Content must be a string\");\n\t}\n\trequire(\"node:fs\").writeFileSync(filePath, content, \"utf-8\");\n}\n\nfunction serializeDiagnostics(\n\tdiagnostics: import(\"vscode-languageserver\").Diagnostic[],\n): SerializedDiagnostic[] {\n\treturn diagnostics.map((diagnostic) => ({\n\t\trange: {\n\t\t\tstart: {\n\t\t\t\tline: diagnostic.range.start.line,\n\t\t\t\tcharacter: diagnostic.range.start.character,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\tline: diagnostic.range.end.line,\n\t\t\t\tcharacter: diagnostic.range.end.character,\n\t\t\t},\n\t\t},\n\t\tseverity: diagnostic.severity || 2,\n\t\tmessage: diagnostic.message,\n\t\tcode: diagnostic.code?.toString(),\n\t\tsource: diagnostic.source,\n\t}));\n}\n\nasync function validateDocument(\n\tstate: State,\n\tfilePath: string,\n\tcontent: string,\n): Promise<SerializedDiagnostic[]> {\n\ttry {\n\t\tif (!state) {\n\t\t\tthrow new Error(\"State is not initialized\");\n\t\t}\n\n\t\tif (state.v4 && !state.designSystem) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Design system not initialized for Tailwind v4. This might indicate a configuration issue.\",\n\t\t\t);\n\t\t}\n\n\t\tif (!state.v4 && !state.modules?.tailwindcss) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Tailwind modules not initialized for Tailwind v3. This might indicate a configuration issue.\",\n\t\t\t);\n\t\t}\n\n\t\tconst languageId = getLanguageId(filePath);\n\t\tconst uri = `file://${filePath}`;\n\t\tconst document = TextDocument.create(uri, languageId, 1, content);\n\n\t\tconst diagnostics = await doValidate(state, document);\n\n\t\treturn serializeDiagnostics(diagnostics);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\n\t\t// Handle crashes from the language service gracefully\n\t\tif (message.includes(\"Cannot read\") || message.includes(\"undefined\")) {\n\t\t\tconsole.warn(\n\t\t\t\t`Warning: Language service crashed while validating ${filePath}. Skipping this file.`,\n\t\t\t);\n\t\t\treturn [];\n\t\t}\n\n\t\tthrow new Error(`Failed to validate document ${filePath}: ${message}`);\n\t}\n}\n\nasync function findTailwindConfigPath(\n\tcwd: string,\n\tconfigPath?: string,\n): Promise<string | null> {\n\tconst { V3_CONFIG_PATHS, V4_CSS_FOLDERS, V4_CSS_NAMES } = await import(\n\t\t\"./constants\"\n\t);\n\n\tif (configPath) {\n\t\tconst resolved = path.isAbsolute(configPath)\n\t\t\t? configPath\n\t\t\t: path.resolve(cwd, configPath);\n\t\treturn fileExists(resolved) ? resolved : null;\n\t}\n\n\tfor (const p of V3_CONFIG_PATHS) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\treturn fullPath;\n\t\t}\n\t}\n\n\tconst v4Paths = V4_CSS_FOLDERS.flatMap((folder) =>\n\t\tV4_CSS_NAMES.map((name) => path.join(folder, name)),\n\t);\n\n\tfor (const p of v4Paths) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(fullPath);\n\t\t\t\tif (\n\t\t\t\t\tcontent.includes('@import \"tailwindcss\"') ||\n\t\t\t\t\tcontent.includes(\"@import 'tailwindcss'\")\n\t\t\t\t) {\n\t\t\t\t\treturn fullPath;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction isCssConfigFile(filePath: string): boolean {\n\treturn filePath.endsWith(\".css\");\n}\n\nasync function loadTailwindConfig(configPath: string): Promise<TailwindConfig> {\n\tif (isCssConfigFile(configPath)) {\n\t\treturn {};\n\t}\n\n\tif (!path.isAbsolute(configPath)) {\n\t\tthrow new Error(\n\t\t\t`Config path must be absolute for security reasons: ${configPath}`,\n\t\t);\n\t}\n\n\ttry {\n\t\tconst { createRequire } = await import(\"node:module\");\n\t\tconst require = createRequire(import.meta.url || __filename);\n\t\tdelete require.cache[configPath];\n\n\t\tconst configModule = require(configPath) as\n\t\t\t| TailwindConfig\n\t\t\t| { default: TailwindConfig };\n\t\tconst config = (\n\t\t\t\"default\" in configModule ? configModule.default : configModule\n\t\t) as TailwindConfig;\n\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new Error(\"Config must be an object\");\n\t\t}\n\n\t\treturn config;\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t`Failed to load config from ${configPath}: ${errorMessage}`,\n\t\t);\n\t}\n}\n\nasync function discoverFiles(\n\tcwd: string,\n\tpatterns: string[],\n\tconfigPath: string | undefined,\n\tautoDiscover: boolean,\n): Promise<string[]> {\n\tif (autoDiscover) {\n\t\treturn discoverFilesFromConfig(cwd, configPath);\n\t}\n\treturn expandPatterns(cwd, patterns);\n}\n\nasync function expandPatterns(\n\tcwd: string,\n\tpatterns: string[],\n): Promise<string[]> {\n\tconst explicitFiles: string[] = [];\n\tconst globPatterns: string[] = [];\n\n\tfor (const pattern of patterns) {\n\t\tif (\n\t\t\tpattern.includes(\"*\") ||\n\t\t\tpattern.includes(\"?\") ||\n\t\t\tpattern.includes(\"[\")\n\t\t) {\n\t\t\tglobPatterns.push(pattern);\n\t\t} else {\n\t\t\tconst fullPath = path.resolve(cwd, pattern);\n\t\t\tif (fileExists(fullPath)) {\n\t\t\t\texplicitFiles.push(pattern);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (globPatterns.length === 0) {\n\t\treturn explicitFiles;\n\t}\n\n\tconst globResults = await glob(globPatterns, {\n\t\tcwd,\n\t\tabsolute: false,\n\t\tignore: DEFAULT_IGNORE_PATTERNS,\n\t});\n\n\tif (explicitFiles.length === 0) {\n\t\treturn globResults;\n\t}\n\n\tconst fileSet = new Set(explicitFiles);\n\tfor (const file of globResults) {\n\t\tfileSet.add(file);\n\t}\n\treturn Array.from(fileSet);\n}\n\nasync function discoverFilesFromConfig(\n\tcwd: string,\n\tconfigPath?: string,\n): Promise<string[]> {\n\tconst configFilePath = await findTailwindConfigPath(cwd, configPath);\n\n\tif (!configFilePath) {\n\t\tthrow new Error(\n\t\t\t\"Could not find Tailwind config for auto-discovery.\\n\" +\n\t\t\t\t\"Use --config to specify the path, or provide file patterns directly.\",\n\t\t);\n\t}\n\n\tif (!isCssConfigFile(configFilePath)) {\n\t\tconst config = await loadTailwindConfig(configFilePath);\n\n\t\tif (!config || !config.content) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Tailwind config is missing the 'content' property.\\n\" +\n\t\t\t\t\t\"Add a content array to specify which files to scan:\\n\" +\n\t\t\t\t\t\" content: ['./src/**/*.{js,jsx,ts,tsx}']\",\n\t\t\t);\n\t\t}\n\n\t\tconst patterns = extractContentPatterns(config);\n\n\t\tif (patterns.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t\"No content patterns found in Tailwind config.\\n\" +\n\t\t\t\t\t\"Ensure your config has a content array with file patterns.\",\n\t\t\t);\n\t\t}\n\n\t\treturn expandPatterns(cwd, patterns);\n\t}\n\n\tthrow new Error(\n\t\t\"Auto-discovery is not supported for Tailwind v4 CSS-based configs.\\n\" +\n\t\t\t\"Please specify file patterns explicitly:\\n\" +\n\t\t\t' tailwind-lint \"src/**/*.{js,jsx,ts,tsx}\"',\n\t);\n}\n\nfunction extractContentPatterns(config: TailwindConfig): string[] {\n\tif (!config.content) return [];\n\n\tif (Array.isArray(config.content)) {\n\t\treturn config.content.filter((p): p is string => typeof p === \"string\");\n\t}\n\n\tif (config.content.files) {\n\t\treturn config.content.files.filter(\n\t\t\t(p): p is string => typeof p === \"string\",\n\t\t);\n\t}\n\n\treturn [];\n}\n\nasync function processFiles(\n\tstate: State,\n\tcwd: string,\n\tfiles: string[],\n\tfix: boolean,\n\tonProgress?: (current: number, total: number, file: string) => void,\n): Promise<LintFileResult[]> {\n\tconst results: LintFileResult[] = [];\n\n\tfor (let i = 0; i < files.length; i += CONCURRENT_FILES) {\n\t\tconst batch = files.slice(i, i + CONCURRENT_FILES);\n\n\t\tconst batchPromises = batch.map(async (file, batchIndex) => {\n\t\t\tconst fileIndex = i + batchIndex;\n\t\t\tif (onProgress) {\n\t\t\t\tonProgress(fileIndex + 1, files.length, file);\n\t\t\t}\n\n\t\t\tconst result = await processFile(state, cwd, file, fix);\n\t\t\treturn result;\n\t\t});\n\n\t\tconst batchResults = await Promise.all(batchPromises);\n\n\t\tfor (const result of batchResults) {\n\t\t\tif (result) {\n\t\t\t\tresults.push(result);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n\nasync function processFile(\n\tstate: State,\n\tcwd: string,\n\tfilePath: string,\n\tfix: boolean,\n): Promise<LintFileResult | null> {\n\tconst absolutePath = path.isAbsolute(filePath)\n\t\t? filePath\n\t\t: path.resolve(cwd, filePath);\n\n\tif (!fileExists(absolutePath)) {\n\t\treturn null;\n\t}\n\n\tlet content = readFileSync(absolutePath);\n\tlet diagnostics = await validateDocument(state, absolutePath, content);\n\n\tlet fixedCount = 0;\n\tlet wasFixed = false;\n\n\tif (fix && diagnostics.length > 0) {\n\t\tconst fixResult = await applyCodeActions(\n\t\t\tstate,\n\t\t\tabsolutePath,\n\t\t\tcontent,\n\t\t\tdiagnostics,\n\t\t);\n\n\t\tif (fixResult.changed) {\n\t\t\twriteFileSync(absolutePath, fixResult.content);\n\t\t\tcontent = fixResult.content;\n\t\t\twasFixed = true;\n\t\t\tfixedCount = fixResult.fixedCount;\n\t\t\tdiagnostics = await validateDocument(state, absolutePath, content);\n\t\t}\n\t}\n\n\treturn {\n\t\tpath: path.relative(cwd, absolutePath),\n\t\tdiagnostics,\n\t\tfixed: wasFixed,\n\t\tfixedCount,\n\t};\n}\nasync function initializeState(\n\tcwd: string,\n\tconfigPath?: string,\n\tverbose = false,\n) {\n\ttry {\n\t\tif (verbose) {\n\t\t\tconsole.log(\"→ Initializing Tailwind CSS language service...\");\n\t\t}\n\t\tconst state = await createState(cwd, configPath, verbose);\n\t\tif (verbose) {\n\t\t\tconsole.log(\" ✓ State initialized successfully\\n\");\n\t\t}\n\t\treturn state;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to initialize Tailwind state: ${message}`);\n\t}\n}\n\nexport type { LintFileResult, LintOptions, LintResult };\n\nexport async function lint({\n\tcwd,\n\tpatterns,\n\tconfigPath,\n\tautoDiscover,\n\tfix = false,\n\tverbose = false,\n\tonProgress,\n}: LintOptions): Promise<LintResult> {\n\tconst files = await discoverFiles(cwd, patterns, configPath, autoDiscover);\n\n\tif (verbose) {\n\t\tconsole.log(\n\t\t\t`→ Discovered ${files.length} file${files.length !== 1 ? \"s\" : \"\"} to lint`,\n\t\t);\n\t}\n\n\tif (files.length === 0) {\n\t\treturn { files: [], totalFilesProcessed: 0 };\n\t}\n\n\tconst state = await initializeState(cwd, configPath, verbose);\n\tconst results = await processFiles(state, cwd, files, fix, onProgress);\n\n\treturn {\n\t\tfiles: results.filter(\n\t\t\t(result) => result.diagnostics.length > 0 || result.fixed,\n\t\t),\n\t\ttotalFilesProcessed: files.length,\n\t};\n}\n"],"mappings":"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"}
|
package/dist/linter.cjs
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"linter-QRh7wAZ7.cjs","names":["getLanguageId","path","TextDocument","MAX_FIX_ITERATIONS","fs","DEFAULT_TAB_SIZE","DEFAULT_ROOT_FONT_SIZE","path","require","path","require","fileExists","fs","readFileSync","path","require","fileExists","fs","readFileSync","isCssConfigFile","loadTailwindConfig","path","findTailwindConfigPath","V3_CONFIG_PATHS","V4_CSS_FOLDERS","V4_CSS_NAMES","DEFAULT_SEPARATOR","path","TextDocument","DEFAULT_IGNORE_PATTERNS"],"sources":["../src/code-actions.ts","../src/adapters/editor-state-adapter.ts","../src/types.ts","../src/adapters/v3-adapter.ts","../src/adapters/v4-adapter.ts","../src/state.ts","../src/linter.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport { doCodeActions, doValidate } from \"@tailwindcss/language-service\";\nimport type { CodeActionParams, Diagnostic } from \"vscode-languageserver\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport { MAX_FIX_ITERATIONS } from \"./constants\";\nimport type { ApplyCodeActionsResult, SerializedDiagnostic } from \"./types\";\n\nexport type { ApplyCodeActionsResult };\n\nfunction getLanguageId(filePath: string): string {\n\tconst LANGUAGE_MAP: Record<string, string> = {\n\t\t\".astro\": \"astro\",\n\t\t\".css\": \"css\",\n\t\t\".erb\": \"erb\",\n\t\t\".hbs\": \"handlebars\",\n\t\t\".htm\": \"html\",\n\t\t\".html\": \"html\",\n\t\t\".js\": \"javascript\",\n\t\t\".jsx\": \"javascriptreact\",\n\t\t\".less\": \"less\",\n\t\t\".md\": \"markdown\",\n\t\t\".mdx\": \"mdx\",\n\t\t\".php\": \"php\",\n\t\t\".sass\": \"sass\",\n\t\t\".scss\": \"scss\",\n\t\t\".svelte\": \"svelte\",\n\t\t\".ts\": \"typescript\",\n\t\t\".tsx\": \"typescriptreact\",\n\t\t\".twig\": \"twig\",\n\t\t\".vue\": \"vue\",\n\t};\n\tconst ext = path.extname(filePath).toLowerCase();\n\treturn LANGUAGE_MAP[ext] || \"html\";\n}\n\ninterface QuickfixAction {\n\tkind?: string;\n\tedit?: {\n\t\tchanges?: Record<string, unknown[]>;\n\t};\n}\n\nasync function getQuickfixes(\n\tstate: State,\n\tdocument: TextDocument,\n\turi: string,\n\tdiagnostics: Diagnostic[],\n): Promise<QuickfixAction[]> {\n\tconst lspDiagnostics: Diagnostic[] = diagnostics.map((diag) => ({\n\t\trange: diag.range,\n\t\tseverity: diag.severity,\n\t\tmessage: diag.message,\n\t\tcode: diag.code,\n\t\tsource: diag.source || \"tailwindcss\",\n\t}));\n\n\tconst params: CodeActionParams = {\n\t\ttextDocument: {\n\t\t\turi,\n\t\t},\n\t\trange: {\n\t\t\tstart: {\n\t\t\t\tline: 0,\n\t\t\t\tcharacter: 0,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\tline: document.lineCount,\n\t\t\t\tcharacter: 0,\n\t\t\t},\n\t\t},\n\t\tcontext: {\n\t\t\tdiagnostics: lspDiagnostics,\n\t\t},\n\t};\n\n\tconst codeActions = await doCodeActions(state, params, document);\n\n\treturn codeActions.filter(\n\t\t(action) =>\n\t\t\taction.kind === \"quickfix\" || action.kind?.startsWith(\"quickfix.\"),\n\t) as QuickfixAction[];\n}\n\nfunction applyFirstQuickfix(\n\taction: QuickfixAction,\n\turi: string,\n\tdocument: TextDocument,\n\tcontent: string,\n): {\n\tcontent: string;\n} | null {\n\tif (!action.edit?.changes?.[uri]) return null;\n\n\tconst edits = action.edit.changes[uri] as {\n\t\trange: {\n\t\t\tstart: {\n\t\t\t\tline: number;\n\t\t\t\tcharacter: number;\n\t\t\t};\n\t\t\tend: {\n\t\t\t\tline: number;\n\t\t\t\tcharacter: number;\n\t\t\t};\n\t\t};\n\t\tnewText: string;\n\t}[];\n\n\tconst sortedEdits = [...edits].sort((a, b) => {\n\t\tconst lineDiff = b.range.start.line - a.range.start.line;\n\t\tif (lineDiff !== 0) return lineDiff;\n\t\treturn b.range.start.character - a.range.start.character;\n\t});\n\n\tlet newContent = content;\n\tfor (const edit of sortedEdits) {\n\t\tconst startOffset = document.offsetAt(edit.range.start);\n\t\tconst endOffset = document.offsetAt(edit.range.end);\n\t\tnewContent =\n\t\t\tnewContent.substring(0, startOffset) +\n\t\t\tedit.newText +\n\t\t\tnewContent.substring(endOffset);\n\t}\n\n\treturn { content: newContent };\n}\n\nexport async function applyCodeActions(\n\tstate: State,\n\tfilePath: string,\n\tcontent: string,\n\tdiagnostics: SerializedDiagnostic[],\n): Promise<ApplyCodeActionsResult> {\n\tif (diagnostics.length === 0) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\tchanged: false,\n\t\t\tfixedCount: 0,\n\t\t};\n\t}\n\n\tconst languageId = getLanguageId(filePath);\n\tconst uri = `file://${filePath}`;\n\tlet currentDocument = TextDocument.create(uri, languageId, 1, content);\n\tlet currentContent = content;\n\tlet totalFixed = 0;\n\n\tlet iteration = 0;\n\tfor (; iteration < MAX_FIX_ITERATIONS; iteration++) {\n\t\tconst currentDiagnostics = await doValidate(state, currentDocument);\n\t\tif (currentDiagnostics.length === 0) break;\n\n\t\tconst quickfixes = await getQuickfixes(\n\t\t\tstate,\n\t\t\tcurrentDocument,\n\t\t\turi,\n\t\t\tcurrentDiagnostics,\n\t\t);\n\t\tif (quickfixes.length === 0) break;\n\n\t\tconst fixResult = applyFirstQuickfix(\n\t\t\tquickfixes[0],\n\t\t\turi,\n\t\t\tcurrentDocument,\n\t\t\tcurrentContent,\n\t\t);\n\t\tif (!fixResult) break;\n\n\t\tcurrentContent = fixResult.content;\n\t\tcurrentDocument = TextDocument.create(\n\t\t\turi,\n\t\t\tlanguageId,\n\t\t\tcurrentDocument.version + 1,\n\t\t\tcurrentContent,\n\t\t);\n\t\ttotalFixed++;\n\t}\n\n\tif (iteration === MAX_FIX_ITERATIONS) {\n\t\tconst remainingDiagnostics = await doValidate(state, currentDocument);\n\t\tif (remainingDiagnostics.length > 0) {\n\t\t\tconsole.warn(\n\t\t\t\t`Warning: Reached maximum fix iterations (${MAX_FIX_ITERATIONS}) for ${filePath}. Some issues may remain.`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tcontent: currentContent,\n\t\tchanged: currentContent !== content,\n\t\tfixedCount: totalFixed,\n\t};\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { EditorState, Settings } from \"@tailwindcss/language-service\";\nimport { DEFAULT_ROOT_FONT_SIZE, DEFAULT_TAB_SIZE } from \"../constants\";\n\nfunction isDirectory(filePath: string): boolean {\n\ttry {\n\t\treturn fs.statSync(filePath).isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function createEditorState(cwd: string): EditorState {\n\tconst settings: Settings = {\n\t\teditor: {\n\t\t\ttabSize: DEFAULT_TAB_SIZE,\n\t\t},\n\t\ttailwindCSS: {\n\t\t\tinspectPort: null,\n\t\t\temmetCompletions: false,\n\t\t\tincludeLanguages: {},\n\t\t\tclassAttributes: [\n\t\t\t\t\"class\",\n\t\t\t\t\"className\",\n\t\t\t\t\"ngClass\",\n\t\t\t\t\"[class]\",\n\t\t\t\t\":class\",\n\t\t\t\t\"v-bind:class\",\n\t\t\t\t\"x-bind:class\",\n\t\t\t\t\"class:list\",\n\t\t\t\t\"classList\",\n\t\t\t],\n\t\t\tclassFunctions: [],\n\t\t\tcodeActions: true,\n\t\t\thovers: true,\n\t\t\tcodeLens: false,\n\t\t\tsuggestions: true,\n\t\t\tvalidate: true,\n\t\t\tcolorDecorators: true,\n\t\t\trootFontSize: DEFAULT_ROOT_FONT_SIZE,\n\t\t\tshowPixelEquivalents: true,\n\t\t\tfiles: {\n\t\t\t\texclude: [\n\t\t\t\t\t\"**/.git/**\",\n\t\t\t\t\t\"**/node_modules/**\",\n\t\t\t\t\t\"**/.hg/**\",\n\t\t\t\t\t\"**/.svn/**\",\n\t\t\t\t],\n\t\t\t},\n\t\t\texperimental: {\n\t\t\t\tconfigFile: null,\n\t\t\t\tclassRegex: [],\n\t\t\t},\n\t\t\tlint: {\n\t\t\t\tcssConflict: \"warning\",\n\t\t\t\tinvalidApply: \"error\",\n\t\t\t\tinvalidScreen: \"error\",\n\t\t\t\tinvalidVariant: \"error\",\n\t\t\t\tinvalidConfigPath: \"error\",\n\t\t\t\tinvalidTailwindDirective: \"error\",\n\t\t\t\tinvalidSourceDirective: \"error\",\n\t\t\t\trecommendedVariantOrder: \"warning\",\n\t\t\t\tusedBlocklistedClass: \"warning\",\n\t\t\t\tsuggestCanonicalClasses: \"warning\",\n\t\t\t},\n\t\t},\n\t};\n\n\treturn {\n\t\tconnection: null as unknown as EditorState[\"connection\"],\n\t\tfolder: cwd,\n\t\tuserLanguages: {},\n\t\tcapabilities: {\n\t\t\tconfiguration: true,\n\t\t\tdiagnosticRelatedInformation: true,\n\t\t\titemDefaults: [],\n\t\t},\n\t\tgetConfiguration: async () => settings,\n\t\tgetDocumentSymbols: async () => [],\n\t\treadDirectory: async (document, directory) => {\n\t\t\tconst docPath =\n\t\t\t\ttypeof document === \"string\"\n\t\t\t\t\t? document\n\t\t\t\t\t: document.uri.replace(\"file://\", \"\");\n\t\t\tconst dir = path.resolve(path.dirname(docPath), directory);\n\t\t\ttry {\n\t\t\t\tconst files = fs.readdirSync(dir);\n\t\t\t\treturn files.map((file) => [\n\t\t\t\t\tfile,\n\t\t\t\t\t{ isDirectory: isDirectory(path.join(dir, file)) },\n\t\t\t\t]);\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t};\n}\n","export interface TailwindConfig {\n\tcontent?: string[] | { files?: string[] };\n\tseparator?: string;\n\t[key: string]: unknown;\n}\n\nexport interface ResolvedTailwindConfig extends TailwindConfig {\n\tseparator: string;\n}\n\nexport interface DesignSystem {\n\tcandidatesToAst?: (candidates: string[]) => unknown[];\n\tcandidatesToCss?: (candidates: string[]) => string[];\n\t[key: string]: unknown;\n}\n\nexport interface ContextUtils {\n\t[key: string]: unknown;\n}\n\nexport interface GenerateRulesModule {\n\tgenerateRules?: (set: unknown, context: unknown) => unknown[];\n\t[key: string]: unknown;\n}\n\nexport interface SerializedDiagnostic {\n\trange: {\n\t\tstart: { line: number; character: number };\n\t\tend: { line: number; character: number };\n\t};\n\tseverity: number;\n\tmessage: string;\n\tcode?: string;\n\tsource?: string;\n}\n\nexport interface ApplyCodeActionsResult {\n\tcontent: string;\n\tchanged: boolean;\n\tfixedCount: number;\n}\n\nexport interface LintFileResult {\n\tpath: string;\n\tdiagnostics: SerializedDiagnostic[];\n\tfixed?: boolean;\n\tfixedCount?: number;\n}\n\nexport interface LintOptions {\n\tcwd: string;\n\tpatterns: string[];\n\tconfigPath?: string;\n\tautoDiscover: boolean;\n\tfix?: boolean;\n\tverbose?: boolean;\n\tonProgress?: (current: number, total: number, file: string) => void;\n}\n\nexport interface LintResult {\n\tfiles: LintFileResult[];\n\ttotalFilesProcessed: number;\n}\n\n/**\n * Error thrown when adapter fails to load required modules\n */\nexport class AdapterLoadError extends Error {\n\tconstructor(\n\t\tpublic readonly version: string,\n\t\tcause: Error,\n\t) {\n\t\tsuper(`Failed to load ${version} adapter: ${cause.message}`);\n\t\tthis.name = \"AdapterLoadError\";\n\t}\n}\n","import { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport type { ContextUtils, GenerateRulesModule } from \"../types\";\nimport { AdapterLoadError } from \"../types\";\n\nconst require = createRequire(import.meta.url || __filename);\n\nexport async function loadV3ClassMetadata(\n\tstate: State,\n\tcwd: string,\n\tverbose = false,\n): Promise<void> {\n\ttry {\n\t\tconst tailwindPath = require.resolve(\"tailwindcss\", { paths: [cwd] });\n\t\tconst tailwindcss = require(tailwindPath) as unknown;\n\n\t\ttry {\n\t\t\tconst tailwindDir = path.dirname(\n\t\t\t\trequire.resolve(\"tailwindcss/package.json\", { paths: [cwd] }),\n\t\t\t);\n\n\t\t\tconst contextUtils = require(\n\t\t\t\tpath.join(tailwindDir, \"lib\", \"lib\", \"setupContextUtils\"),\n\t\t\t) as ContextUtils;\n\t\t\tconst generateRulesModule = require(\n\t\t\t\tpath.join(tailwindDir, \"lib\", \"lib\", \"generateRules\"),\n\t\t\t) as GenerateRulesModule;\n\n\t\t\tstate.modules = {\n\t\t\t\ttailwindcss: {\n\t\t\t\t\tversion: state.version || \"unknown\",\n\t\t\t\t\tmodule: tailwindcss,\n\t\t\t\t},\n\t\t\t\tjit: {\n\t\t\t\t\tgenerateRules: {\n\t\t\t\t\t\tmodule:\n\t\t\t\t\t\t\tgenerateRulesModule.generateRules ||\n\t\t\t\t\t\t\t((_set: unknown, _context: unknown) => []),\n\t\t\t\t\t},\n\t\t\t\t\tcreateContext: {\n\t\t\t\t\t\tmodule: contextUtils.createContext,\n\t\t\t\t\t},\n\t\t\t\t\texpandApplyAtRules: {\n\t\t\t\t\t\tmodule: generateRulesModule.expandApplyAtRules,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tif (verbose) {\n\t\t\t\tconsole.log(\" ✓ Loaded v3 JIT modules\");\n\t\t\t}\n\t\t} catch (jitError) {\n\t\t\tif (verbose) {\n\t\t\t\tconst message =\n\t\t\t\t\tjitError instanceof Error ? jitError.message : String(jitError);\n\t\t\t\tconsole.log(` ⚠ Warning: Could not load v3 JIT modules: ${message}`);\n\t\t\t}\n\n\t\t\tstate.modules = {\n\t\t\t\ttailwindcss: {\n\t\t\t\t\tversion: state.version || \"unknown\",\n\t\t\t\t\tmodule: tailwindcss,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\textractConfigMetadata(state);\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tthrow new AdapterLoadError(\"v3\", error);\n\t\t}\n\t\tthrow new Error(`Failed to load v3 class metadata: ${String(error)}`);\n\t}\n}\n\nfunction extractConfigMetadata(state: State): void {\n\tconst { config } = state;\n\tif (!config || typeof config !== \"object\") return;\n\n\tconst theme = (config as Record<string, unknown>).theme as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\tstate.screens = Object.keys(\n\t\t(theme?.screens as Record<string, unknown>) ?? {},\n\t);\n\tstate.blocklist = (config.blocklist as string[] | undefined) ?? [];\n\n\tif (config.variants && typeof config.variants === \"object\") {\n\t\tstate.variants = Object.keys(config.variants).map((name) => ({\n\t\t\tname,\n\t\t\tvalues: [],\n\t\t\tisArbitrary: false,\n\t\t\thasDash: true,\n\t\t\tselectors: () => [],\n\t\t}));\n\t}\n\n\tif (config.corePlugins) {\n\t\tstate.corePlugins = Array.isArray(config.corePlugins)\n\t\t\t? (config.corePlugins as string[])\n\t\t\t: Object.keys(config.corePlugins as Record<string, unknown>);\n\t}\n}\n","import * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport type { DesignSystem } from \"../types\";\nimport { AdapterLoadError } from \"../types\";\n\nconst require = createRequire(import.meta.url || __filename);\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\treturn fs.existsSync(filePath);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readFileSync(filePath: string): string {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\treturn fs.readFileSync(filePath, \"utf-8\");\n}\n\nexport async function loadV4DesignSystem(\n\tstate: State,\n\tcwd: string,\n\tconfigPath: string,\n\tverbose = false,\n): Promise<void> {\n\ttry {\n\t\tconst tailwindPath = require.resolve(\"tailwindcss\", { paths: [cwd] });\n\t\tconst tailwindcss = require(tailwindPath) as unknown;\n\n\t\tif (\n\t\t\ttailwindcss !== null &&\n\t\t\ttailwindcss !== undefined &&\n\t\t\t(typeof tailwindcss === \"object\" || typeof tailwindcss === \"function\") &&\n\t\t\t\"__unstable__loadDesignSystem\" in tailwindcss &&\n\t\t\ttypeof tailwindcss.__unstable__loadDesignSystem === \"function\"\n\t\t) {\n\t\t\tlet cssContent: string;\n\t\t\tconst basePath = path.dirname(configPath);\n\n\t\t\tif (fileExists(configPath)) {\n\t\t\t\tcssContent = readFileSync(configPath, true);\n\t\t\t} else {\n\t\t\t\tcssContent = '@import \"tailwindcss\";';\n\t\t\t}\n\n\t\t\ttype LoadDesignSystemFn = (\n\t\t\t\tcss: string,\n\t\t\t\toptions: {\n\t\t\t\t\tbase: string;\n\t\t\t\t\tloadStylesheet: (\n\t\t\t\t\t\tid: string,\n\t\t\t\t\t\tbase: string,\n\t\t\t\t\t\tcontent?: string,\n\t\t\t\t\t) => Promise<{ base: string; content: string }>;\n\t\t\t\t},\n\t\t\t) => Promise<DesignSystem>;\n\n\t\t\tconst loadDesignSystem =\n\t\t\t\ttailwindcss.__unstable__loadDesignSystem as LoadDesignSystemFn;\n\n\t\t\tconst designSystem = await loadDesignSystem(cssContent, {\n\t\t\t\tbase: basePath,\n\t\t\t\tasync loadStylesheet(\n\t\t\t\t\t_id: string,\n\t\t\t\t\tbase: string,\n\t\t\t\t\tcontent?: string,\n\t\t\t\t): Promise<{ base: string; content: string }> {\n\t\t\t\t\tif (content) {\n\t\t\t\t\t\treturn { base, content };\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!_id.startsWith(\".\") && !_id.startsWith(\"/\")) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst pkgJsonPath = require.resolve(`${_id}/package.json`, {\n\t\t\t\t\t\t\t\tpaths: [base, cwd],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst pkgDir = path.dirname(pkgJsonPath);\n\t\t\t\t\t\t\tconst cssPath = path.join(pkgDir, \"index.css\");\n\t\t\t\t\t\t\tif (fileExists(cssPath)) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tbase: pkgDir,\n\t\t\t\t\t\t\t\t\tcontent: readFileSync(cssPath, true),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst filePath = path.resolve(base, _id);\n\t\t\t\t\tif (fileExists(filePath)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tbase: path.dirname(filePath),\n\t\t\t\t\t\t\tcontent: readFileSync(filePath, true),\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { base, content: \"\" };\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tObject.assign(designSystem, {\n\t\t\t\tdependencies: () => new Set<string>(),\n\n\t\t\t\tcompile(classes: string[]): unknown[][] {\n\t\t\t\t\tconst results = designSystem.candidatesToAst\n\t\t\t\t\t\t? designSystem.candidatesToAst(classes)\n\t\t\t\t\t\t: designSystem.candidatesToCss?.(classes) || [];\n\n\t\t\t\t\treturn results.map((result: unknown) => {\n\t\t\t\t\t\tif (Array.isArray(result)) {\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (result === null) {\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// @ts-expect-error - DesignSystem types are loaded dynamically at runtime\n\t\t\tstate.designSystem = designSystem;\n\n\t\t\tif (!state.classNames) {\n\t\t\t\tstate.classNames = {\n\t\t\t\t\tcontext: {},\n\t\t\t\t} as unknown as typeof state.classNames;\n\t\t\t}\n\n\t\t\tif (verbose) {\n\t\t\t\tconsole.log(\" ✓ Loaded v4 design system\");\n\t\t\t}\n\t\t} else {\n\t\t\tconst error = new Error(\n\t\t\t\t\"Tailwind v4 __unstable__loadDesignSystem is not available. Please ensure you have Tailwind CSS v4 installed.\",\n\t\t\t);\n\t\t\tthrow new AdapterLoadError(\"v4\", error);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof AdapterLoadError) {\n\t\t\tthrow error;\n\t\t}\n\t\tif (error instanceof Error) {\n\t\t\tthrow new AdapterLoadError(\"v4\", error);\n\t\t}\n\t\tthrow new Error(`Failed to load v4 design system: ${String(error)}`);\n\t}\n}\n","import * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport { createEditorState } from \"./adapters/editor-state-adapter\";\nimport { loadV3ClassMetadata } from \"./adapters/v3-adapter\";\nimport { loadV4DesignSystem } from \"./adapters/v4-adapter\";\nimport {\n\tDEFAULT_SEPARATOR,\n\tV3_CONFIG_PATHS,\n\tV4_CSS_FOLDERS,\n\tV4_CSS_NAMES,\n} from \"./constants\";\nimport type { ResolvedTailwindConfig, TailwindConfig } from \"./types\";\n\nconst require = createRequire(import.meta.url || __filename);\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\treturn fs.existsSync(filePath);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readFileSync(filePath: string): string {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\treturn fs.readFileSync(filePath, \"utf-8\");\n}\n\nfunction getTailwindVersion(cwd: string): string | undefined {\n\ttry {\n\t\tconst tailwindPackageJson = require.resolve(\"tailwindcss/package.json\", {\n\t\t\tpaths: [cwd],\n\t\t});\n\t\tconst pkg = JSON.parse(fs.readFileSync(tailwindPackageJson, \"utf-8\")) as {\n\t\t\tversion?: string;\n\t\t};\n\t\treturn pkg.version;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction isV4Config(version: string | undefined): boolean {\n\treturn version?.startsWith(\"4.\") ?? false;\n}\n\nfunction isCssConfigFile(filePath: string): boolean {\n\treturn filePath.endsWith(\".css\");\n}\n\nasync function loadTailwindConfig(configPath: string): Promise<TailwindConfig> {\n\tif (isCssConfigFile(configPath)) {\n\t\treturn {};\n\t}\n\n\tif (!path.isAbsolute(configPath)) {\n\t\tthrow new Error(\n\t\t\t`Config path must be absolute for security reasons: ${configPath}`,\n\t\t);\n\t}\n\n\ttry {\n\t\tdelete require.cache[configPath];\n\n\t\tconst configModule = require(configPath) as\n\t\t\t| TailwindConfig\n\t\t\t| { default: TailwindConfig };\n\t\tconst config = (\n\t\t\t\"default\" in configModule ? configModule.default : configModule\n\t\t) as TailwindConfig;\n\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new Error(\"Config must be an object\");\n\t\t}\n\n\t\treturn config;\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t`Failed to load config from ${configPath}: ${errorMessage}`,\n\t\t);\n\t}\n}\n\nasync function findTailwindConfigPath(\n\tcwd: string,\n\tconfigPath?: string,\n): Promise<string | null> {\n\tif (configPath) {\n\t\tconst resolved = path.isAbsolute(configPath)\n\t\t\t? configPath\n\t\t\t: path.resolve(cwd, configPath);\n\t\treturn fileExists(resolved) ? resolved : null;\n\t}\n\n\tfor (const p of V3_CONFIG_PATHS) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\treturn fullPath;\n\t\t}\n\t}\n\n\tconst v4Paths = V4_CSS_FOLDERS.flatMap((folder) =>\n\t\tV4_CSS_NAMES.map((name) => path.join(folder, name)),\n\t);\n\n\tfor (const p of v4Paths) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(fullPath);\n\t\t\t\tif (\n\t\t\t\t\tcontent.includes('@import \"tailwindcss\"') ||\n\t\t\t\t\tcontent.includes(\"@import 'tailwindcss'\")\n\t\t\t\t) {\n\t\t\t\t\treturn fullPath;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction resolveTailwindPath(cwd: string, configDir?: string): string {\n\tconst paths = configDir ? [configDir, cwd] : [cwd];\n\ttry {\n\t\treturn require.resolve(\"tailwindcss\", { paths });\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Could not resolve tailwindcss module from ${paths.join(\" or \")}`,\n\t\t);\n\t}\n}\n\nexport async function createState(\n\tcwd: string,\n\tconfigPath?: string,\n\tverbose = false,\n): Promise<State> {\n\tconst resolvedConfigPath = await findTailwindConfigPath(cwd, configPath);\n\n\tif (!resolvedConfigPath) {\n\t\tthrow new Error(\"Could not find tailwind config file (JS/TS or CSS)\");\n\t}\n\n\tconst isCssConfig = isCssConfigFile(resolvedConfigPath);\n\tconst configDir = path.dirname(resolvedConfigPath);\n\tconst tailwindPath = resolveTailwindPath(cwd, configDir);\n\n\tconst tailwindcss = require(tailwindPath) as {\n\t\tresolveConfig?: (config: unknown) => unknown;\n\t};\n\n\tconst version = getTailwindVersion(cwd);\n\tconst isV4 = isV4Config(version);\n\n\tif (verbose) {\n\t\tconsole.log(` Tailwind version: ${version || \"unknown\"}`);\n\t\tconsole.log(` Config type: ${isCssConfig ? \"CSS (v4)\" : \"JavaScript\"}`);\n\t\tconsole.log(` Config path: ${resolvedConfigPath}`);\n\t}\n\n\tlet config: TailwindConfig = {};\n\tlet resolvedConfig: ResolvedTailwindConfig = { separator: \":\" };\n\n\tif (!isCssConfig) {\n\t\tconfig = await loadTailwindConfig(resolvedConfigPath);\n\t\tresolvedConfig = {\n\t\t\t...config,\n\t\t\tseparator: config.separator ?? DEFAULT_SEPARATOR,\n\t\t};\n\t\tif (tailwindcss.resolveConfig) {\n\t\t\tresolvedConfig = tailwindcss.resolveConfig(\n\t\t\t\tconfig,\n\t\t\t) as ResolvedTailwindConfig;\n\t\t}\n\t}\n\n\tconst state: State = {\n\t\tenabled: true,\n\t\tconfigPath: resolvedConfigPath,\n\t\tconfig: resolvedConfig,\n\t\tversion,\n\t\tv4: isV4 || undefined,\n\t\tseparator: resolvedConfig.separator || DEFAULT_SEPARATOR,\n\t\tscreens: [],\n\t\tvariants: [],\n\t\tclassNames: undefined,\n\t\tclassList: undefined,\n\t\tmodules: undefined,\n\t\tblocklist: [],\n\t\teditor: createEditorState(cwd),\n\t\tfeatures: [\"diagnostics\"] as unknown as State[\"features\"],\n\t};\n\n\tif (isV4 || isCssConfig) {\n\t\tawait loadV4DesignSystem(state, cwd, resolvedConfigPath, verbose);\n\t} else {\n\t\tawait loadV3ClassMetadata(state, cwd, verbose);\n\t}\n\n\treturn state;\n}\n","import * as path from \"node:path\";\nimport type { State } from \"@tailwindcss/language-service\";\nimport { doValidate } from \"@tailwindcss/language-service\";\nimport glob from \"fast-glob\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport { applyCodeActions } from \"./code-actions\";\nimport { DEFAULT_IGNORE_PATTERNS } from \"./constants\";\nimport { createState } from \"./state\";\nimport type {\n\tLintFileResult,\n\tLintOptions,\n\tLintResult,\n\tSerializedDiagnostic,\n\tTailwindConfig,\n} from \"./types\";\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\treturn require(\"node:fs\").existsSync(filePath);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readFileSync(filePath: string): string {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\treturn require(\"node:fs\").readFileSync(filePath, \"utf-8\");\n}\n\nfunction writeFileSync(filePath: string, content: string): void {\n\tif (!filePath || typeof filePath !== \"string\") {\n\t\tthrow new TypeError(\"File path must be a non-empty string\");\n\t}\n\tif (typeof content !== \"string\") {\n\t\tthrow new TypeError(\"Content must be a string\");\n\t}\n\trequire(\"node:fs\").writeFileSync(filePath, content, \"utf-8\");\n}\n\nfunction serializeDiagnostics(\n\tdiagnostics: import(\"vscode-languageserver\").Diagnostic[],\n): SerializedDiagnostic[] {\n\treturn diagnostics.map((diagnostic) => ({\n\t\trange: {\n\t\t\tstart: {\n\t\t\t\tline: diagnostic.range.start.line,\n\t\t\t\tcharacter: diagnostic.range.start.character,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\tline: diagnostic.range.end.line,\n\t\t\t\tcharacter: diagnostic.range.end.character,\n\t\t\t},\n\t\t},\n\t\tseverity: diagnostic.severity || 2,\n\t\tmessage: diagnostic.message,\n\t\tcode: diagnostic.code?.toString(),\n\t\tsource: diagnostic.source,\n\t}));\n}\n\nfunction getLanguageId(filePath: string): string {\n\tconst LANGUAGE_MAP: Record<string, string> = {\n\t\t\".astro\": \"astro\",\n\t\t\".css\": \"css\",\n\t\t\".erb\": \"erb\",\n\t\t\".hbs\": \"handlebars\",\n\t\t\".htm\": \"html\",\n\t\t\".html\": \"html\",\n\t\t\".js\": \"javascript\",\n\t\t\".jsx\": \"javascriptreact\",\n\t\t\".less\": \"less\",\n\t\t\".md\": \"markdown\",\n\t\t\".mdx\": \"mdx\",\n\t\t\".php\": \"php\",\n\t\t\".sass\": \"sass\",\n\t\t\".scss\": \"scss\",\n\t\t\".svelte\": \"svelte\",\n\t\t\".ts\": \"typescript\",\n\t\t\".tsx\": \"typescriptreact\",\n\t\t\".twig\": \"twig\",\n\t\t\".vue\": \"vue\",\n\t};\n\tconst ext = path.extname(filePath).toLowerCase();\n\treturn LANGUAGE_MAP[ext] || \"html\";\n}\n\nasync function validateDocument(\n\tstate: State,\n\tfilePath: string,\n\tcontent: string,\n): Promise<SerializedDiagnostic[]> {\n\ttry {\n\t\tif (!state) {\n\t\t\tthrow new Error(\"State is not initialized\");\n\t\t}\n\n\t\tif (state.v4 && !state.designSystem) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Design system not initialized for Tailwind v4. This might indicate a configuration issue.\",\n\t\t\t);\n\t\t}\n\n\t\tif (!state.v4 && !state.modules?.tailwindcss) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Tailwind modules not initialized for Tailwind v3. This might indicate a configuration issue.\",\n\t\t\t);\n\t\t}\n\n\t\tconst languageId = getLanguageId(filePath);\n\t\tconst uri = `file://${filePath}`;\n\t\tconst document = TextDocument.create(uri, languageId, 1, content);\n\n\t\tconst diagnostics = await doValidate(state, document);\n\n\t\treturn serializeDiagnostics(diagnostics);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to validate document ${filePath}: ${message}`);\n\t}\n}\n\nasync function findTailwindConfigPath(\n\tcwd: string,\n\tconfigPath?: string,\n): Promise<string | null> {\n\tconst { V3_CONFIG_PATHS, V4_CSS_FOLDERS, V4_CSS_NAMES } = await import(\n\t\t\"./constants\"\n\t);\n\n\tif (configPath) {\n\t\tconst resolved = path.isAbsolute(configPath)\n\t\t\t? configPath\n\t\t\t: path.resolve(cwd, configPath);\n\t\treturn fileExists(resolved) ? resolved : null;\n\t}\n\n\tfor (const p of V3_CONFIG_PATHS) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\treturn fullPath;\n\t\t}\n\t}\n\n\tconst v4Paths = V4_CSS_FOLDERS.flatMap((folder) =>\n\t\tV4_CSS_NAMES.map((name) => path.join(folder, name)),\n\t);\n\n\tfor (const p of v4Paths) {\n\t\tconst fullPath = path.join(cwd, p);\n\t\tif (fileExists(fullPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(fullPath);\n\t\t\t\tif (\n\t\t\t\t\tcontent.includes('@import \"tailwindcss\"') ||\n\t\t\t\t\tcontent.includes(\"@import 'tailwindcss'\")\n\t\t\t\t) {\n\t\t\t\t\treturn fullPath;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction isCssConfigFile(filePath: string): boolean {\n\treturn filePath.endsWith(\".css\");\n}\n\nasync function loadTailwindConfig(configPath: string): Promise<TailwindConfig> {\n\tif (isCssConfigFile(configPath)) {\n\t\treturn {};\n\t}\n\n\tif (!path.isAbsolute(configPath)) {\n\t\tthrow new Error(\n\t\t\t`Config path must be absolute for security reasons: ${configPath}`,\n\t\t);\n\t}\n\n\ttry {\n\t\tconst { createRequire } = await import(\"node:module\");\n\t\tconst require = createRequire(import.meta.url || __filename);\n\t\tdelete require.cache[configPath];\n\n\t\tconst configModule = require(configPath) as\n\t\t\t| TailwindConfig\n\t\t\t| { default: TailwindConfig };\n\t\tconst config = (\n\t\t\t\"default\" in configModule ? configModule.default : configModule\n\t\t) as TailwindConfig;\n\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new Error(\"Config must be an object\");\n\t\t}\n\n\t\treturn config;\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(\n\t\t\t`Failed to load config from ${configPath}: ${errorMessage}`,\n\t\t);\n\t}\n}\n\nasync function discoverFiles(\n\tcwd: string,\n\tpatterns: string[],\n\tconfigPath: string | undefined,\n\tautoDiscover: boolean,\n): Promise<string[]> {\n\tif (autoDiscover) {\n\t\treturn discoverFilesFromConfig(cwd, configPath);\n\t}\n\treturn expandPatterns(cwd, patterns);\n}\n\nasync function expandPatterns(\n\tcwd: string,\n\tpatterns: string[],\n): Promise<string[]> {\n\tconst explicitFiles: string[] = [];\n\tconst globPatterns: string[] = [];\n\n\tfor (const pattern of patterns) {\n\t\tif (\n\t\t\tpattern.includes(\"*\") ||\n\t\t\tpattern.includes(\"?\") ||\n\t\t\tpattern.includes(\"[\")\n\t\t) {\n\t\t\tglobPatterns.push(pattern);\n\t\t} else {\n\t\t\tconst fullPath = path.resolve(cwd, pattern);\n\t\t\tif (fileExists(fullPath)) {\n\t\t\t\texplicitFiles.push(pattern);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (globPatterns.length === 0) {\n\t\treturn explicitFiles;\n\t}\n\n\tconst globResults = await glob(globPatterns, {\n\t\tcwd,\n\t\tabsolute: false,\n\t\tignore: DEFAULT_IGNORE_PATTERNS,\n\t});\n\n\tif (explicitFiles.length === 0) {\n\t\treturn globResults;\n\t}\n\n\tconst fileSet = new Set(explicitFiles);\n\tfor (const file of globResults) {\n\t\tfileSet.add(file);\n\t}\n\treturn Array.from(fileSet);\n}\n\nasync function discoverFilesFromConfig(\n\tcwd: string,\n\tconfigPath?: string,\n): Promise<string[]> {\n\tconst configFilePath = await findTailwindConfigPath(cwd, configPath);\n\n\tif (!configFilePath) {\n\t\tthrow new Error(\"Could not find Tailwind config\");\n\t}\n\n\tif (!isCssConfigFile(configFilePath)) {\n\t\tconst config = await loadTailwindConfig(configFilePath);\n\n\t\tif (!config || !config.content) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Could not find Tailwind config or config has no content property\",\n\t\t\t);\n\t\t}\n\n\t\tconst patterns = extractContentPatterns(config);\n\n\t\tif (patterns.length === 0) {\n\t\t\tthrow new Error(\"No content patterns found in Tailwind config\");\n\t\t}\n\n\t\treturn expandPatterns(cwd, patterns);\n\t}\n\n\tthrow new Error(\n\t\t\"Auto-discovery is not supported for CSS-based configs (v4). Please specify file patterns.\",\n\t);\n}\n\nfunction extractContentPatterns(config: TailwindConfig): string[] {\n\tif (!config.content) return [];\n\n\tif (Array.isArray(config.content)) {\n\t\treturn config.content.filter((p): p is string => typeof p === \"string\");\n\t}\n\n\tif (config.content.files) {\n\t\treturn config.content.files.filter(\n\t\t\t(p): p is string => typeof p === \"string\",\n\t\t);\n\t}\n\n\treturn [];\n}\n\nasync function processFiles(\n\tstate: State,\n\tcwd: string,\n\tfiles: string[],\n\tfix: boolean,\n\tonProgress?: (current: number, total: number, file: string) => void,\n): Promise<LintFileResult[]> {\n\tconst results: LintFileResult[] = [];\n\n\tfor (let i = 0; i < files.length; i++) {\n\t\tif (onProgress) {\n\t\t\tonProgress(i + 1, files.length, files[i]);\n\t\t}\n\n\t\tconst result = await processFile(state, cwd, files[i], fix);\n\t\tif (result) {\n\t\t\tresults.push(result);\n\t\t}\n\t}\n\n\treturn results;\n}\n\nasync function processFile(\n\tstate: State,\n\tcwd: string,\n\tfilePath: string,\n\tfix: boolean,\n): Promise<LintFileResult | null> {\n\tconst absolutePath = path.isAbsolute(filePath)\n\t\t? filePath\n\t\t: path.resolve(cwd, filePath);\n\n\tif (!fileExists(absolutePath)) {\n\t\treturn null;\n\t}\n\n\tlet content = readFileSync(absolutePath);\n\tlet diagnostics = await validateDocument(state, absolutePath, content);\n\n\tlet fixedCount = 0;\n\tlet wasFixed = false;\n\n\tif (fix && diagnostics.length > 0) {\n\t\tconst fixResult = await applyCodeActions(\n\t\t\tstate,\n\t\t\tabsolutePath,\n\t\t\tcontent,\n\t\t\tdiagnostics,\n\t\t);\n\n\t\tif (fixResult.changed) {\n\t\t\twriteFileSync(absolutePath, fixResult.content);\n\t\t\tcontent = fixResult.content;\n\t\t\twasFixed = true;\n\t\t\tfixedCount = fixResult.fixedCount;\n\n\t\t\t// Re-validate to get remaining diagnostics\n\t\t\tdiagnostics = await validateDocument(state, absolutePath, content);\n\t\t}\n\t}\n\n\treturn {\n\t\tpath: path.relative(cwd, absolutePath),\n\t\tdiagnostics,\n\t\tfixed: wasFixed,\n\t\tfixedCount,\n\t};\n}\nasync function initializeState(\n\tcwd: string,\n\tconfigPath?: string,\n\tverbose = false,\n) {\n\ttry {\n\t\tif (verbose) {\n\t\t\tconsole.log(\"→ Initializing Tailwind CSS language service...\");\n\t\t}\n\t\tconst state = await createState(cwd, configPath, verbose);\n\t\tif (verbose) {\n\t\t\tconsole.log(\" ✓ State initialized successfully\\n\");\n\t\t}\n\t\treturn state;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`Failed to initialize Tailwind state: ${message}`);\n\t}\n}\n\nexport type { LintFileResult, LintOptions, LintResult };\n\nexport async function lint({\n\tcwd,\n\tpatterns,\n\tconfigPath,\n\tautoDiscover,\n\tfix = false,\n\tverbose = false,\n\tonProgress,\n}: LintOptions): Promise<LintResult> {\n\tconst files = await discoverFiles(cwd, patterns, configPath, autoDiscover);\n\n\tif (verbose) {\n\t\tconsole.log(\n\t\t\t`→ Discovered ${files.length} file${files.length !== 1 ? \"s\" : \"\"} to lint`,\n\t\t);\n\t}\n\n\tif (files.length === 0) {\n\t\treturn { files: [], totalFilesProcessed: 0 };\n\t}\n\n\tconst state = await initializeState(cwd, configPath, verbose);\n\tconst results = await processFiles(state, cwd, files, fix, onProgress);\n\n\treturn {\n\t\tfiles: results.filter(\n\t\t\t(result) => result.diagnostics.length > 0 || result.fixed,\n\t\t),\n\t\ttotalFilesProcessed: files.length,\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,SAASA,gBAAc,UAA0B;AAuBhD,QAtB6C;EAC5C,UAAU;EACV,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,SAAS;EACT,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,SAAS;EACT,SAAS;EACT,WAAW;EACX,OAAO;EACP,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,CACWC,UAAK,QAAQ,SAAS,CAAC,aAAa,KACpB;;AAU7B,eAAe,cACd,OACA,UACA,KACA,aAC4B;CAC5B,MAAM,iBAA+B,YAAY,KAAK,UAAU;EAC/D,OAAO,KAAK;EACZ,UAAU,KAAK;EACf,SAAS,KAAK;EACd,MAAM,KAAK;EACX,QAAQ,KAAK,UAAU;EACvB,EAAE;AAuBH,SAFoB,uDAAoB,OAnBP;EAChC,cAAc,EACb,KACA;EACD,OAAO;GACN,OAAO;IACN,MAAM;IACN,WAAW;IACX;GACD,KAAK;IACJ,MAAM,SAAS;IACf,WAAW;IACX;GACD;EACD,SAAS,EACR,aAAa,gBACb;EACD,EAEsD,SAAS,EAE7C,QACjB,WACA,OAAO,SAAS,cAAc,OAAO,MAAM,WAAW,YAAY,CACnE;;AAGF,SAAS,mBACR,QACA,KACA,UACA,SAGQ;AACR,KAAI,CAAC,OAAO,MAAM,UAAU,KAAM,QAAO;CAgBzC,MAAM,cAAc,CAAC,GAdP,OAAO,KAAK,QAAQ,KAcJ,CAAC,MAAM,GAAG,MAAM;EAC7C,MAAM,WAAW,EAAE,MAAM,MAAM,OAAO,EAAE,MAAM,MAAM;AACpD,MAAI,aAAa,EAAG,QAAO;AAC3B,SAAO,EAAE,MAAM,MAAM,YAAY,EAAE,MAAM,MAAM;GAC9C;CAEF,IAAI,aAAa;AACjB,MAAK,MAAM,QAAQ,aAAa;EAC/B,MAAM,cAAc,SAAS,SAAS,KAAK,MAAM,MAAM;EACvD,MAAM,YAAY,SAAS,SAAS,KAAK,MAAM,IAAI;AACnD,eACC,WAAW,UAAU,GAAG,YAAY,GACpC,KAAK,UACL,WAAW,UAAU,UAAU;;AAGjC,QAAO,EAAE,SAAS,YAAY;;AAG/B,eAAsB,iBACrB,OACA,UACA,SACA,aACkC;AAClC,KAAI,YAAY,WAAW,EAC1B,QAAO;EACN;EACA,SAAS;EACT,YAAY;EACZ;CAGF,MAAM,aAAaD,gBAAc,SAAS;CAC1C,MAAM,MAAM,UAAU;CACtB,IAAI,kBAAkBE,gDAAa,OAAO,KAAK,YAAY,GAAG,QAAQ;CACtE,IAAI,iBAAiB;CACrB,IAAI,aAAa;CAEjB,IAAI,YAAY;AAChB,QAAO,YAAYC,sCAAoB,aAAa;EACnD,MAAM,qBAAqB,oDAAiB,OAAO,gBAAgB;AACnE,MAAI,mBAAmB,WAAW,EAAG;EAErC,MAAM,aAAa,MAAM,cACxB,OACA,iBACA,KACA,mBACA;AACD,MAAI,WAAW,WAAW,EAAG;EAE7B,MAAM,YAAY,mBACjB,WAAW,IACX,KACA,iBACA,eACA;AACD,MAAI,CAAC,UAAW;AAEhB,mBAAiB,UAAU;AAC3B,oBAAkBD,gDAAa,OAC9B,KACA,YACA,gBAAgB,UAAU,GAC1B,eACA;AACD;;AAGD,KAAI,cAAcC,sCAEjB;OAD6B,oDAAiB,OAAO,gBAAgB,EAC5C,SAAS,EACjC,SAAQ,KACP,4CAA4CA,qCAAmB,QAAQ,SAAS,2BAChF;;AAIH,QAAO;EACN,SAAS;EACT,SAAS,mBAAmB;EAC5B,YAAY;EACZ;;;;;AC1LF,SAAS,YAAY,UAA2B;AAC/C,KAAI;AACH,SAAOC,QAAG,SAAS,SAAS,CAAC,aAAa;SACnC;AACP,SAAO;;;AAIT,SAAgB,kBAAkB,KAA0B;CAC3D,MAAM,WAAqB;EAC1B,QAAQ,EACP,SAASC,oCACT;EACD,aAAa;GACZ,aAAa;GACb,kBAAkB;GAClB,kBAAkB,EAAE;GACpB,iBAAiB;IAChB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACD,gBAAgB,EAAE;GAClB,aAAa;GACb,QAAQ;GACR,UAAU;GACV,aAAa;GACb,UAAU;GACV,iBAAiB;GACjB,cAAcC;GACd,sBAAsB;GACtB,OAAO,EACN,SAAS;IACR;IACA;IACA;IACA;IACA,EACD;GACD,cAAc;IACb,YAAY;IACZ,YAAY,EAAE;IACd;GACD,MAAM;IACL,aAAa;IACb,cAAc;IACd,eAAe;IACf,gBAAgB;IAChB,mBAAmB;IACnB,0BAA0B;IAC1B,wBAAwB;IACxB,yBAAyB;IACzB,sBAAsB;IACtB,yBAAyB;IACzB;GACD;EACD;AAED,QAAO;EACN,YAAY;EACZ,QAAQ;EACR,eAAe,EAAE;EACjB,cAAc;GACb,eAAe;GACf,8BAA8B;GAC9B,cAAc,EAAE;GAChB;EACD,kBAAkB,YAAY;EAC9B,oBAAoB,YAAY,EAAE;EAClC,eAAe,OAAO,UAAU,cAAc;GAC7C,MAAM,UACL,OAAO,aAAa,WACjB,WACA,SAAS,IAAI,QAAQ,WAAW,GAAG;GACvC,MAAM,MAAMC,UAAK,QAAQA,UAAK,QAAQ,QAAQ,EAAE,UAAU;AAC1D,OAAI;AAEH,WADcH,QAAG,YAAY,IAAI,CACpB,KAAK,SAAS,CAC1B,MACA,EAAE,aAAa,YAAYG,UAAK,KAAK,KAAK,KAAK,CAAC,EAAE,CAClD,CAAC;WACK;AACP,WAAO,EAAE;;;EAGX;;;;;;;;AC7BF,IAAa,mBAAb,cAAsC,MAAM;CAC3C,YACC,AAAgB,SAChB,OACC;AACD,QAAM,kBAAkB,QAAQ,YAAY,MAAM,UAAU;EAH5C;AAIhB,OAAK,OAAO;;;;;;ACnEd,MAAMC,4FAA2C,WAAW;AAE5D,eAAsB,oBACrB,OACA,KACA,UAAU,OACM;AAChB,KAAI;EAEH,MAAM,cAAcA,UADCA,UAAQ,QAAQ,eAAe,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAC5B;AAEzC,MAAI;GACH,MAAM,cAAcC,UAAK,QACxBD,UAAQ,QAAQ,4BAA4B,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAC7D;GAED,MAAM,eAAeA,UACpBC,UAAK,KAAK,aAAa,OAAO,OAAO,oBAAoB,CACzD;GACD,MAAM,sBAAsBD,UAC3BC,UAAK,KAAK,aAAa,OAAO,OAAO,gBAAgB,CACrD;AAED,SAAM,UAAU;IACf,aAAa;KACZ,SAAS,MAAM,WAAW;KAC1B,QAAQ;KACR;IACD,KAAK;KACJ,eAAe,EACd,QACC,oBAAoB,mBAClB,MAAe,aAAsB,EAAE,GAC1C;KACD,eAAe,EACd,QAAQ,aAAa,eACrB;KACD,oBAAoB,EACnB,QAAQ,oBAAoB,oBAC5B;KACD;IACD;AAED,OAAI,QACH,SAAQ,IAAI,4BAA4B;WAEjC,UAAU;AAClB,OAAI,SAAS;IACZ,MAAM,UACL,oBAAoB,QAAQ,SAAS,UAAU,OAAO,SAAS;AAChE,YAAQ,IAAI,+CAA+C,UAAU;;AAGtE,SAAM,UAAU,EACf,aAAa;IACZ,SAAS,MAAM,WAAW;IAC1B,QAAQ;IACR,EACD;;AAGF,wBAAsB,MAAM;UACpB,OAAO;AACf,MAAI,iBAAiB,MACpB,OAAM,IAAI,iBAAiB,MAAM,MAAM;AAExC,QAAM,IAAI,MAAM,qCAAqC,OAAO,MAAM,GAAG;;;AAIvE,SAAS,sBAAsB,OAAoB;CAClD,MAAM,EAAE,WAAW;AACnB,KAAI,CAAC,UAAU,OAAO,WAAW,SAAU;CAE3C,MAAM,QAAS,OAAmC;AAGlD,OAAM,UAAU,OAAO,KACrB,OAAO,WAAuC,EAAE,CACjD;AACD,OAAM,YAAa,OAAO,aAAsC,EAAE;AAElE,KAAI,OAAO,YAAY,OAAO,OAAO,aAAa,SACjD,OAAM,WAAW,OAAO,KAAK,OAAO,SAAS,CAAC,KAAK,UAAU;EAC5D;EACA,QAAQ,EAAE;EACV,aAAa;EACb,SAAS;EACT,iBAAiB,EAAE;EACnB,EAAE;AAGJ,KAAI,OAAO,YACV,OAAM,cAAc,MAAM,QAAQ,OAAO,YAAY,GACjD,OAAO,cACR,OAAO,KAAK,OAAO,YAAuC;;;;;AC9F/D,MAAMC,4FAA2C,WAAW;AAE5D,SAASC,aAAW,UAA2B;AAC9C,KAAI;AACH,SAAOC,QAAG,WAAW,SAAS;SACvB;AACP,SAAO;;;AAIT,SAASC,eAAa,UAA0B;AAC/C,KAAI,CAAC,YAAY,OAAO,aAAa,SACpC,OAAM,IAAI,UAAU,uCAAuC;AAE5D,QAAOD,QAAG,aAAa,UAAU,QAAQ;;AAG1C,eAAsB,mBACrB,OACA,KACA,YACA,UAAU,OACM;AAChB,KAAI;EAEH,MAAM,cAAcF,UADCA,UAAQ,QAAQ,eAAe,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAC5B;AAEzC,MACC,gBAAgB,QAChB,gBAAgB,WACf,OAAO,gBAAgB,YAAY,OAAO,gBAAgB,eAC3D,kCAAkC,eAClC,OAAO,YAAY,iCAAiC,YACnD;GACD,IAAI;GACJ,MAAM,WAAWI,UAAK,QAAQ,WAAW;AAEzC,OAAIH,aAAW,WAAW,CACzB,cAAaE,eAAa,YAAY,KAAK;OAE3C,cAAa;GAed,MAAM,mBACL,YAAY;GAEb,MAAM,eAAe,MAAM,iBAAiB,YAAY;IACvD,MAAM;IACN,MAAM,eACL,KACA,MACA,SAC6C;AAC7C,SAAI,QACH,QAAO;MAAE;MAAM;MAAS;AAGzB,SAAI,CAAC,IAAI,WAAW,IAAI,IAAI,CAAC,IAAI,WAAW,IAAI,CAC/C,KAAI;MACH,MAAM,cAAcH,UAAQ,QAAQ,GAAG,IAAI,gBAAgB,EAC1D,OAAO,CAAC,MAAM,IAAI,EAClB,CAAC;MACF,MAAM,SAASI,UAAK,QAAQ,YAAY;MACxC,MAAM,UAAUA,UAAK,KAAK,QAAQ,YAAY;AAC9C,UAAIH,aAAW,QAAQ,CACtB,QAAO;OACN,MAAM;OACN,SAASE,eAAa,SAAS,KAAK;OACpC;aAEK;KAGT,MAAM,WAAWC,UAAK,QAAQ,MAAM,IAAI;AACxC,SAAIH,aAAW,SAAS,CACvB,QAAO;MACN,MAAMG,UAAK,QAAQ,SAAS;MAC5B,SAASD,eAAa,UAAU,KAAK;MACrC;AAGF,YAAO;MAAE;MAAM,SAAS;MAAI;;IAE7B,CAAC;AAEF,UAAO,OAAO,cAAc;IAC3B,oCAAoB,IAAI,KAAa;IAErC,QAAQ,SAAgC;AAKvC,aAJgB,aAAa,kBAC1B,aAAa,gBAAgB,QAAQ,GACrC,aAAa,kBAAkB,QAAQ,IAAI,EAAE,EAEjC,KAAK,WAAoB;AACvC,UAAI,MAAM,QAAQ,OAAO,CACxB,QAAO;AAER,UAAI,WAAW,KACd,QAAO,EAAE;AAEV,aAAO,EAAE;OACR;;IAEH,CAAC;AAGF,SAAM,eAAe;AAErB,OAAI,CAAC,MAAM,WACV,OAAM,aAAa,EAClB,SAAS,EAAE,EACX;AAGF,OAAI,QACH,SAAQ,IAAI,8BAA8B;QAM3C,OAAM,IAAI,iBAAiB,sBAHb,IAAI,MACjB,+GACA,CACsC;UAEhC,OAAO;AACf,MAAI,iBAAiB,iBACpB,OAAM;AAEP,MAAI,iBAAiB,MACpB,OAAM,IAAI,iBAAiB,MAAM,MAAM;AAExC,QAAM,IAAI,MAAM,oCAAoC,OAAO,MAAM,GAAG;;;;;;ACtItE,MAAME,4FAA2C,WAAW;AAE5D,SAASC,aAAW,UAA2B;AAC9C,KAAI;AACH,SAAOC,QAAG,WAAW,SAAS;SACvB;AACP,SAAO;;;AAIT,SAASC,eAAa,UAA0B;AAC/C,KAAI,CAAC,YAAY,OAAO,aAAa,SACpC,OAAM,IAAI,UAAU,uCAAuC;AAE5D,QAAOD,QAAG,aAAa,UAAU,QAAQ;;AAG1C,SAAS,mBAAmB,KAAiC;AAC5D,KAAI;EACH,MAAM,sBAAsBF,UAAQ,QAAQ,4BAA4B,EACvE,OAAO,CAAC,IAAI,EACZ,CAAC;AAIF,SAHY,KAAK,MAAME,QAAG,aAAa,qBAAqB,QAAQ,CAAC,CAG1D;SACJ;AACP;;;AAIF,SAAS,WAAW,SAAsC;AACzD,QAAO,SAAS,WAAW,KAAK,IAAI;;AAGrC,SAASE,kBAAgB,UAA2B;AACnD,QAAO,SAAS,SAAS,OAAO;;AAGjC,eAAeC,qBAAmB,YAA6C;AAC9E,KAAID,kBAAgB,WAAW,CAC9B,QAAO,EAAE;AAGV,KAAI,CAACE,UAAK,WAAW,WAAW,CAC/B,OAAM,IAAI,MACT,sDAAsD,aACtD;AAGF,KAAI;AACH,SAAON,UAAQ,MAAM;EAErB,MAAM,eAAeA,UAAQ,WAAW;EAGxC,MAAM,SACL,aAAa,eAAe,aAAa,UAAU;AAGpD,MAAI,OAAO,WAAW,YAAY,WAAW,KAC5C,OAAM,IAAI,MAAM,2BAA2B;AAG5C,SAAO;UACC,OAAO;EACf,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QAAM,IAAI,MACT,8BAA8B,WAAW,IAAI,eAC7C;;;AAIH,eAAeO,yBACd,KACA,YACyB;AACzB,KAAI,YAAY;EACf,MAAM,WAAWD,UAAK,WAAW,WAAW,GACzC,aACAA,UAAK,QAAQ,KAAK,WAAW;AAChC,SAAOL,aAAW,SAAS,GAAG,WAAW;;AAG1C,MAAK,MAAM,KAAKO,mCAAiB;EAChC,MAAM,WAAWF,UAAK,KAAK,KAAK,EAAE;AAClC,MAAIL,aAAW,SAAS,CACvB,QAAO;;CAIT,MAAM,UAAUQ,iCAAe,SAAS,WACvCC,+BAAa,KAAK,SAASJ,UAAK,KAAK,QAAQ,KAAK,CAAC,CACnD;AAED,MAAK,MAAM,KAAK,SAAS;EACxB,MAAM,WAAWA,UAAK,KAAK,KAAK,EAAE;AAClC,MAAIL,aAAW,SAAS,CACvB,KAAI;GACH,MAAM,UAAUE,eAAa,SAAS;AACtC,OACC,QAAQ,SAAS,0BAAwB,IACzC,QAAQ,SAAS,wBAAwB,CAEzC,QAAO;UAED;;AAIV,QAAO;;AAGR,SAAS,oBAAoB,KAAa,WAA4B;CACrE,MAAM,QAAQ,YAAY,CAAC,WAAW,IAAI,GAAG,CAAC,IAAI;AAClD,KAAI;AACH,SAAOH,UAAQ,QAAQ,eAAe,EAAE,OAAO,CAAC;SACzC;AACP,QAAM,IAAI,MACT,6CAA6C,MAAM,KAAK,OAAO,GAC/D;;;AAIH,eAAsB,YACrB,KACA,YACA,UAAU,OACO;CACjB,MAAM,qBAAqB,MAAMO,yBAAuB,KAAK,WAAW;AAExE,KAAI,CAAC,mBACJ,OAAM,IAAI,MAAM,qDAAqD;CAGtE,MAAM,cAAcH,kBAAgB,mBAAmB;CAIvD,MAAM,cAAcJ,UAFC,oBAAoB,KADvBM,UAAK,QAAQ,mBAAmB,CACM,CAEf;CAIzC,MAAM,UAAU,mBAAmB,IAAI;CACvC,MAAM,OAAO,WAAW,QAAQ;AAEhC,KAAI,SAAS;AACZ,UAAQ,IAAI,uBAAuB,WAAW,YAAY;AAC1D,UAAQ,IAAI,kBAAkB,cAAc,aAAa,eAAe;AACxE,UAAQ,IAAI,kBAAkB,qBAAqB;;CAGpD,IAAI,SAAyB,EAAE;CAC/B,IAAI,iBAAyC,EAAE,WAAW,KAAK;AAE/D,KAAI,CAAC,aAAa;AACjB,WAAS,MAAMD,qBAAmB,mBAAmB;AACrD,mBAAiB;GAChB,GAAG;GACH,WAAW,OAAO,aAAaM;GAC/B;AACD,MAAI,YAAY,cACf,kBAAiB,YAAY,cAC5B,OACA;;CAIH,MAAM,QAAe;EACpB,SAAS;EACT,YAAY;EACZ,QAAQ;EACR;EACA,IAAI,QAAQ;EACZ,WAAW,eAAe,aAAaA;EACvC,SAAS,EAAE;EACX,UAAU,EAAE;EACZ,YAAY;EACZ,WAAW;EACX,SAAS;EACT,WAAW,EAAE;EACb,QAAQ,kBAAkB,IAAI;EAC9B,UAAU,CAAC,cAAc;EACzB;AAED,KAAI,QAAQ,YACX,OAAM,mBAAmB,OAAO,KAAK,oBAAoB,QAAQ;KAEjE,OAAM,oBAAoB,OAAO,KAAK,QAAQ;AAG/C,QAAO;;;;;AC9LR,SAAS,WAAW,UAA2B;AAC9C,KAAI;AACH,SAAO,QAAQ,UAAU,CAAC,WAAW,SAAS;SACvC;AACP,SAAO;;;AAIT,SAAS,aAAa,UAA0B;AAC/C,KAAI,CAAC,YAAY,OAAO,aAAa,SACpC,OAAM,IAAI,UAAU,uCAAuC;AAE5D,QAAO,QAAQ,UAAU,CAAC,aAAa,UAAU,QAAQ;;AAG1D,SAAS,cAAc,UAAkB,SAAuB;AAC/D,KAAI,CAAC,YAAY,OAAO,aAAa,SACpC,OAAM,IAAI,UAAU,uCAAuC;AAE5D,KAAI,OAAO,YAAY,SACtB,OAAM,IAAI,UAAU,2BAA2B;AAEhD,SAAQ,UAAU,CAAC,cAAc,UAAU,SAAS,QAAQ;;AAG7D,SAAS,qBACR,aACyB;AACzB,QAAO,YAAY,KAAK,gBAAgB;EACvC,OAAO;GACN,OAAO;IACN,MAAM,WAAW,MAAM,MAAM;IAC7B,WAAW,WAAW,MAAM,MAAM;IAClC;GACD,KAAK;IACJ,MAAM,WAAW,MAAM,IAAI;IAC3B,WAAW,WAAW,MAAM,IAAI;IAChC;GACD;EACD,UAAU,WAAW,YAAY;EACjC,SAAS,WAAW;EACpB,MAAM,WAAW,MAAM,UAAU;EACjC,QAAQ,WAAW;EACnB,EAAE;;AAGJ,SAAS,cAAc,UAA0B;AAuBhD,QAtB6C;EAC5C,UAAU;EACV,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,SAAS;EACT,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,SAAS;EACT,SAAS;EACT,WAAW;EACX,OAAO;EACP,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,CACWC,UAAK,QAAQ,SAAS,CAAC,aAAa,KACpB;;AAG7B,eAAe,iBACd,OACA,UACA,SACkC;AAClC,KAAI;AACH,MAAI,CAAC,MACJ,OAAM,IAAI,MAAM,2BAA2B;AAG5C,MAAI,MAAM,MAAM,CAAC,MAAM,aACtB,OAAM,IAAI,MACT,4FACA;AAGF,MAAI,CAAC,MAAM,MAAM,CAAC,MAAM,SAAS,YAChC,OAAM,IAAI,MACT,+FACA;EAGF,MAAM,aAAa,cAAc,SAAS;EAC1C,MAAM,MAAM,UAAU;AAKtB,SAAO,qBAFa,oDAAiB,OAFpBC,gDAAa,OAAO,KAAK,YAAY,GAAG,QAAQ,CAEZ,CAEb;UAChC,OAAO;EACf,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,QAAM,IAAI,MAAM,+BAA+B,SAAS,IAAI,UAAU;;;AAIxE,eAAe,uBACd,KACA,YACyB;CACzB,MAAM,EAAE,iBAAiB,gBAAgB,iBAAiB,2CAAM;AAIhE,KAAI,YAAY;EACf,MAAM,WAAWD,UAAK,WAAW,WAAW,GACzC,aACAA,UAAK,QAAQ,KAAK,WAAW;AAChC,SAAO,WAAW,SAAS,GAAG,WAAW;;AAG1C,MAAK,MAAM,KAAK,iBAAiB;EAChC,MAAM,WAAWA,UAAK,KAAK,KAAK,EAAE;AAClC,MAAI,WAAW,SAAS,CACvB,QAAO;;CAIT,MAAM,UAAU,eAAe,SAAS,WACvC,aAAa,KAAK,SAASA,UAAK,KAAK,QAAQ,KAAK,CAAC,CACnD;AAED,MAAK,MAAM,KAAK,SAAS;EACxB,MAAM,WAAWA,UAAK,KAAK,KAAK,EAAE;AAClC,MAAI,WAAW,SAAS,CACvB,KAAI;GACH,MAAM,UAAU,aAAa,SAAS;AACtC,OACC,QAAQ,SAAS,0BAAwB,IACzC,QAAQ,SAAS,wBAAwB,CAEzC,QAAO;UAED;;AAIV,QAAO;;AAGR,SAAS,gBAAgB,UAA2B;AACnD,QAAO,SAAS,SAAS,OAAO;;AAGjC,eAAe,mBAAmB,YAA6C;AAC9E,KAAI,gBAAgB,WAAW,CAC9B,QAAO,EAAE;AAGV,KAAI,CAACA,UAAK,WAAW,WAAW,CAC/B,OAAM,IAAI,MACT,sDAAsD,aACtD;AAGF,KAAI;EACH,MAAM,EAAE,kBAAkB,MAAM,OAAO;EACvC,MAAM,UAAU,+DAAiC,WAAW;AAC5D,SAAO,QAAQ,MAAM;EAErB,MAAM,eAAe,QAAQ,WAAW;EAGxC,MAAM,SACL,aAAa,eAAe,aAAa,UAAU;AAGpD,MAAI,OAAO,WAAW,YAAY,WAAW,KAC5C,OAAM,IAAI,MAAM,2BAA2B;AAG5C,SAAO;UACC,OAAO;EACf,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QAAM,IAAI,MACT,8BAA8B,WAAW,IAAI,eAC7C;;;AAIH,eAAe,cACd,KACA,UACA,YACA,cACoB;AACpB,KAAI,aACH,QAAO,wBAAwB,KAAK,WAAW;AAEhD,QAAO,eAAe,KAAK,SAAS;;AAGrC,eAAe,eACd,KACA,UACoB;CACpB,MAAM,gBAA0B,EAAE;CAClC,MAAM,eAAyB,EAAE;AAEjC,MAAK,MAAM,WAAW,SACrB,KACC,QAAQ,SAAS,IAAI,IACrB,QAAQ,SAAS,IAAI,IACrB,QAAQ,SAAS,IAAI,CAErB,cAAa,KAAK,QAAQ;UAGtB,WADaA,UAAK,QAAQ,KAAK,QAAQ,CACnB,CACvB,eAAc,KAAK,QAAQ;AAK9B,KAAI,aAAa,WAAW,EAC3B,QAAO;CAGR,MAAM,cAAc,6BAAW,cAAc;EAC5C;EACA,UAAU;EACV,QAAQE;EACR,CAAC;AAEF,KAAI,cAAc,WAAW,EAC5B,QAAO;CAGR,MAAM,UAAU,IAAI,IAAI,cAAc;AACtC,MAAK,MAAM,QAAQ,YAClB,SAAQ,IAAI,KAAK;AAElB,QAAO,MAAM,KAAK,QAAQ;;AAG3B,eAAe,wBACd,KACA,YACoB;CACpB,MAAM,iBAAiB,MAAM,uBAAuB,KAAK,WAAW;AAEpE,KAAI,CAAC,eACJ,OAAM,IAAI,MAAM,iCAAiC;AAGlD,KAAI,CAAC,gBAAgB,eAAe,EAAE;EACrC,MAAM,SAAS,MAAM,mBAAmB,eAAe;AAEvD,MAAI,CAAC,UAAU,CAAC,OAAO,QACtB,OAAM,IAAI,MACT,mEACA;EAGF,MAAM,WAAW,uBAAuB,OAAO;AAE/C,MAAI,SAAS,WAAW,EACvB,OAAM,IAAI,MAAM,+CAA+C;AAGhE,SAAO,eAAe,KAAK,SAAS;;AAGrC,OAAM,IAAI,MACT,4FACA;;AAGF,SAAS,uBAAuB,QAAkC;AACjE,KAAI,CAAC,OAAO,QAAS,QAAO,EAAE;AAE9B,KAAI,MAAM,QAAQ,OAAO,QAAQ,CAChC,QAAO,OAAO,QAAQ,QAAQ,MAAmB,OAAO,MAAM,SAAS;AAGxE,KAAI,OAAO,QAAQ,MAClB,QAAO,OAAO,QAAQ,MAAM,QAC1B,MAAmB,OAAO,MAAM,SACjC;AAGF,QAAO,EAAE;;AAGV,eAAe,aACd,OACA,KACA,OACA,KACA,YAC4B;CAC5B,MAAM,UAA4B,EAAE;AAEpC,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,MAAI,WACH,YAAW,IAAI,GAAG,MAAM,QAAQ,MAAM,GAAG;EAG1C,MAAM,SAAS,MAAM,YAAY,OAAO,KAAK,MAAM,IAAI,IAAI;AAC3D,MAAI,OACH,SAAQ,KAAK,OAAO;;AAItB,QAAO;;AAGR,eAAe,YACd,OACA,KACA,UACA,KACiC;CACjC,MAAM,eAAeF,UAAK,WAAW,SAAS,GAC3C,WACAA,UAAK,QAAQ,KAAK,SAAS;AAE9B,KAAI,CAAC,WAAW,aAAa,CAC5B,QAAO;CAGR,IAAI,UAAU,aAAa,aAAa;CACxC,IAAI,cAAc,MAAM,iBAAiB,OAAO,cAAc,QAAQ;CAEtE,IAAI,aAAa;CACjB,IAAI,WAAW;AAEf,KAAI,OAAO,YAAY,SAAS,GAAG;EAClC,MAAM,YAAY,MAAM,iBACvB,OACA,cACA,SACA,YACA;AAED,MAAI,UAAU,SAAS;AACtB,iBAAc,cAAc,UAAU,QAAQ;AAC9C,aAAU,UAAU;AACpB,cAAW;AACX,gBAAa,UAAU;AAGvB,iBAAc,MAAM,iBAAiB,OAAO,cAAc,QAAQ;;;AAIpE,QAAO;EACN,MAAMA,UAAK,SAAS,KAAK,aAAa;EACtC;EACA,OAAO;EACP;EACA;;AAEF,eAAe,gBACd,KACA,YACA,UAAU,OACT;AACD,KAAI;AACH,MAAI,QACH,SAAQ,IAAI,kDAAkD;EAE/D,MAAM,QAAQ,MAAM,YAAY,KAAK,YAAY,QAAQ;AACzD,MAAI,QACH,SAAQ,IAAI,uCAAuC;AAEpD,SAAO;UACC,OAAO;EACf,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,QAAM,IAAI,MAAM,wCAAwC,UAAU;;;AAMpE,eAAsB,KAAK,EAC1B,KACA,UACA,YACA,cACA,MAAM,OACN,UAAU,OACV,cACoC;CACpC,MAAM,QAAQ,MAAM,cAAc,KAAK,UAAU,YAAY,aAAa;AAE1E,KAAI,QACH,SAAQ,IACP,gBAAgB,MAAM,OAAO,OAAO,MAAM,WAAW,IAAI,MAAM,GAAG,UAClE;AAGF,KAAI,MAAM,WAAW,EACpB,QAAO;EAAE,OAAO,EAAE;EAAE,qBAAqB;EAAG;AAM7C,QAAO;EACN,QAHe,MAAM,aADR,MAAM,gBAAgB,KAAK,YAAY,QAAQ,EACnB,KAAK,OAAO,KAAK,WAAW,EAGtD,QACb,WAAW,OAAO,YAAY,SAAS,KAAK,OAAO,MACpD;EACD,qBAAqB,MAAM;EAC3B"}
|