tailwind-lint 0.11.2 → 0.12.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 +3 -2
- package/dist/{linter-B9R7nuem.cjs → linter-BP0uKBfa.cjs} +72 -25
- package/dist/linter.cjs +1 -1
- package/dist/linter.d.cts +1 -9
- package/package.json +9 -9
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_linter = require("./linter-
|
|
2
|
+
const require_linter = require("./linter-BP0uKBfa.cjs");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_linter.__toESM(node_path, 1);
|
|
5
5
|
let ansis = require("ansis");
|
|
@@ -110,7 +110,8 @@ function resolveOptions(files, options) {
|
|
|
110
110
|
let autoDiscover = hasAutoFlag;
|
|
111
111
|
if (hasConfigFlag && options.config) configPath = node_path.isAbsolute(options.config) ? options.config : node_path.resolve(process.cwd(), options.config);
|
|
112
112
|
if (hasConfigFlag && options.config && !hasFiles) {
|
|
113
|
-
|
|
113
|
+
const configDir = node_path.dirname(configPath);
|
|
114
|
+
cwd = require_linter.isCssConfigFile(configPath) ? require_linter.findProjectRoot(configDir) : configDir;
|
|
114
115
|
patterns = [];
|
|
115
116
|
autoDiscover = true;
|
|
116
117
|
}
|
|
@@ -121,7 +121,8 @@ const SEVERITY = {
|
|
|
121
121
|
const TAILWIND_V4_IMPORT_REGEX = /@import\s+["']tailwindcss(?:["'\s/]|$)/;
|
|
122
122
|
const TAILWIND_VITE_PLUGIN_REGEX = /(?:from\s+["']@tailwindcss\/vite["']|require\(\s*["']@tailwindcss\/vite["']\s*\)|import\(\s*["']@tailwindcss\/vite["']\s*\))/;
|
|
123
123
|
function getLanguageId(filePath) {
|
|
124
|
-
|
|
124
|
+
const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
|
|
125
|
+
return LANGUAGE_MAP[ext] || "html";
|
|
125
126
|
}
|
|
126
127
|
//#endregion
|
|
127
128
|
//#region src/code-actions.ts
|
|
@@ -488,7 +489,8 @@ var AdapterLoadError = class extends Error {
|
|
|
488
489
|
const require$4 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
|
|
489
490
|
async function loadV3ClassMetadata(state, cwd, verbose = false) {
|
|
490
491
|
try {
|
|
491
|
-
const
|
|
492
|
+
const tailwindPath = require$4.resolve("tailwindcss", { paths: [cwd] });
|
|
493
|
+
const tailwindcss = require$4(tailwindPath);
|
|
492
494
|
try {
|
|
493
495
|
const tailwindDir = node_path.dirname(require$4.resolve("tailwindcss/package.json", { paths: [cwd] }));
|
|
494
496
|
const contextUtils = require$4(node_path.join(tailwindDir, "lib", "lib", "setupContextUtils"));
|
|
@@ -554,7 +556,8 @@ function extractConfigMetadata(state) {
|
|
|
554
556
|
const require$3 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
|
|
555
557
|
async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
|
|
556
558
|
try {
|
|
557
|
-
const
|
|
559
|
+
const tailwindPath = require$3.resolve("tailwindcss", { paths: [cwd] });
|
|
560
|
+
const tailwindcss = require$3(tailwindPath);
|
|
558
561
|
if (tailwindcss !== null && tailwindcss !== void 0 && (typeof tailwindcss === "object" || typeof tailwindcss === "function") && "__unstable__loadDesignSystem" in tailwindcss && typeof tailwindcss.__unstable__loadDesignSystem === "function") {
|
|
559
562
|
let cssContent;
|
|
560
563
|
const basePath = node_path.dirname(configPath);
|
|
@@ -628,7 +631,17 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
|
|
|
628
631
|
//#region src/utils/config.ts
|
|
629
632
|
const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
|
|
630
633
|
const CONFIG_DISCOVERY_MAX_DEPTH = 8;
|
|
634
|
+
const PROJECT_ROOT_MARKERS = ["package.json", ".git"];
|
|
631
635
|
const isCssConfigFile = (filePath) => filePath.endsWith(".css");
|
|
636
|
+
function findProjectRoot(startDir) {
|
|
637
|
+
let current = node_path.resolve(startDir);
|
|
638
|
+
while (true) {
|
|
639
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => fileExists(node_path.join(current, marker)))) return current;
|
|
640
|
+
const parent = node_path.dirname(current);
|
|
641
|
+
if (parent === current) return node_path.resolve(startDir);
|
|
642
|
+
current = parent;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
632
645
|
function syntheticViteCssConfigPath(viteConfigPath) {
|
|
633
646
|
return node_path.join(node_path.dirname(viteConfigPath), SYNTHETIC_VITE_CSS_CONFIG_NAME);
|
|
634
647
|
}
|
|
@@ -653,17 +666,6 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
653
666
|
const resolved = node_path.isAbsolute(configPath) ? configPath : node_path.resolve(cwd, configPath);
|
|
654
667
|
return fileExists(resolved) ? resolved : null;
|
|
655
668
|
}
|
|
656
|
-
for (const p of V3_CONFIG_PATHS) {
|
|
657
|
-
const fullPath = node_path.join(cwd, p);
|
|
658
|
-
if (fileExists(fullPath)) return fullPath;
|
|
659
|
-
}
|
|
660
|
-
const v3Recursive = await (0, tinyglobby.glob)(V3_CONFIG_PATHS.map((p) => `**/${p}`), {
|
|
661
|
-
cwd,
|
|
662
|
-
absolute: true,
|
|
663
|
-
ignore: DEFAULT_IGNORE_PATTERNS,
|
|
664
|
-
deep: CONFIG_DISCOVERY_MAX_DEPTH
|
|
665
|
-
});
|
|
666
|
-
if (v3Recursive.length > 0) return sortByPathDepth(v3Recursive)[0];
|
|
667
669
|
const v4Paths = V4_CSS_FOLDERS.flatMap((folder) => V4_CSS_NAMES.map((name) => node_path.join(folder, name)));
|
|
668
670
|
for (const p of v4Paths) {
|
|
669
671
|
const fullPath = node_path.join(cwd, p);
|
|
@@ -672,6 +674,10 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
672
674
|
if (TAILWIND_V4_IMPORT_REGEX.test(content)) return fullPath;
|
|
673
675
|
} catch {}
|
|
674
676
|
}
|
|
677
|
+
for (const p of V3_CONFIG_PATHS) {
|
|
678
|
+
const fullPath = node_path.join(cwd, p);
|
|
679
|
+
if (fileExists(fullPath)) return fullPath;
|
|
680
|
+
}
|
|
675
681
|
const cssCandidates = await (0, tinyglobby.glob)("**/*.css", {
|
|
676
682
|
cwd,
|
|
677
683
|
absolute: true,
|
|
@@ -684,6 +690,13 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
684
690
|
if (TAILWIND_V4_IMPORT_REGEX.test(content)) v4Matches.push(candidate);
|
|
685
691
|
} catch {}
|
|
686
692
|
if (v4Matches.length > 0) return sortCssCandidates(cwd, v4Matches)[0];
|
|
693
|
+
const v3Recursive = await (0, tinyglobby.glob)(V3_CONFIG_PATHS.map((p) => `**/${p}`), {
|
|
694
|
+
cwd,
|
|
695
|
+
absolute: true,
|
|
696
|
+
ignore: DEFAULT_IGNORE_PATTERNS,
|
|
697
|
+
deep: CONFIG_DISCOVERY_MAX_DEPTH
|
|
698
|
+
});
|
|
699
|
+
if (v3Recursive.length > 0) return sortByPathDepth(v3Recursive)[0];
|
|
687
700
|
const viteConfigPath = await findTailwindViteConfigPath(cwd);
|
|
688
701
|
if (viteConfigPath) return syntheticViteCssConfigPath(viteConfigPath);
|
|
689
702
|
return null;
|
|
@@ -769,7 +782,8 @@ async function createState(cwd, configPath, verbose = false) {
|
|
|
769
782
|
const resolvedConfigPath = await findTailwindConfigPath(cwd, configPath);
|
|
770
783
|
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 v4 (Vite): vite.config.* with @tailwindcss/vite\n • Tailwind v3 (JS): tailwind.config.js, tailwind.config.ts\nRun 'npx tailwindcss init' to create a config file.");
|
|
771
784
|
const isCssConfig = isCssConfigFile(resolvedConfigPath);
|
|
772
|
-
const
|
|
785
|
+
const tailwindPath = resolveTailwindPath(cwd, node_path.dirname(resolvedConfigPath));
|
|
786
|
+
const tailwindcss = require$1(tailwindPath);
|
|
773
787
|
const version = getTailwindVersion(cwd);
|
|
774
788
|
const isV4 = isV4Config(version);
|
|
775
789
|
if (verbose) {
|
|
@@ -810,6 +824,8 @@ async function createState(cwd, configPath, verbose = false) {
|
|
|
810
824
|
}
|
|
811
825
|
//#endregion
|
|
812
826
|
//#region src/linter.ts
|
|
827
|
+
const SOURCE_FILE_PATTERN = "**/*.{js,jsx,ts,tsx,html,vue,svelte,astro,mdx}";
|
|
828
|
+
const GLOB_PATTERN_REGEX = /[*?[\]{}]/;
|
|
813
829
|
async function validateDocument(state, filePath, content) {
|
|
814
830
|
try {
|
|
815
831
|
if (!state) throw new Error("State is not initialized");
|
|
@@ -843,33 +859,41 @@ async function expandPatterns(cwd, patterns, extraIgnore = []) {
|
|
|
843
859
|
async function discoverFilesFromConfig(cwd, configPath) {
|
|
844
860
|
const configFilePath = await findTailwindConfigPath(cwd, configPath);
|
|
845
861
|
if (!configFilePath) throw new Error("Could not find Tailwind config for auto-discovery.\nUse --config to specify the path, or provide file patterns directly.");
|
|
862
|
+
const discoveryCwd = isCssConfigFile(configFilePath) ? findProjectRoot(node_path.dirname(configFilePath)) : cwd;
|
|
846
863
|
if (!isCssConfigFile(configFilePath)) {
|
|
847
864
|
const config = await loadTailwindConfig(configFilePath);
|
|
848
865
|
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}']");
|
|
849
866
|
const patterns = extractContentPatterns(config);
|
|
850
867
|
if (patterns.length === 0) throw new Error("No content patterns found in Tailwind config.\nEnsure your config has a content array with file patterns.");
|
|
851
|
-
return expandPatterns(
|
|
868
|
+
return expandPatterns(discoveryCwd, patterns);
|
|
852
869
|
}
|
|
853
870
|
const configDir = node_path.dirname(configFilePath);
|
|
854
871
|
const cssContent = fileExists(configFilePath) ? readFileSync(configFilePath) : SYNTHETIC_VITE_CSS_CONFIG_CONTENT;
|
|
855
872
|
const includeConfigFile = (files) => {
|
|
856
873
|
if (!fileExists(configFilePath)) return files;
|
|
857
|
-
const relativeConfigPath = node_path.relative(
|
|
858
|
-
return [
|
|
874
|
+
const relativeConfigPath = node_path.relative(discoveryCwd, configFilePath);
|
|
875
|
+
return [.../* @__PURE__ */ new Set([relativeConfigPath, ...files])].sort((a, b) => a.localeCompare(b));
|
|
859
876
|
};
|
|
877
|
+
const resolveDiscoveredFiles = (files) => discoveryCwd === cwd ? files : files.map((file) => node_path.resolve(discoveryCwd, file)).sort((a, b) => a.localeCompare(b));
|
|
860
878
|
const { include, exclude } = extractSourcePatterns(cssContent);
|
|
861
879
|
const importSource = extractImportSourceDirectives(cssContent);
|
|
862
880
|
const resolveFromConfig = (pattern) => {
|
|
863
881
|
const absolutePattern = node_path.resolve(configDir, pattern);
|
|
864
|
-
return node_path.relative(
|
|
882
|
+
return node_path.relative(discoveryCwd, absolutePattern);
|
|
865
883
|
};
|
|
866
884
|
const resolvedExclude = exclude.map(resolveFromConfig);
|
|
867
|
-
const gitignorePatterns = readGitignorePatterns(
|
|
885
|
+
const gitignorePatterns = readGitignorePatterns(discoveryCwd);
|
|
868
886
|
const extraIgnore = [...resolvedExclude, ...gitignorePatterns];
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
if (importSource.disableAutoSource)
|
|
872
|
-
|
|
887
|
+
const explicitSourcePatterns = include.map((source) => resolveFromConfig(normalizeSourcePattern(source)));
|
|
888
|
+
let autoPatterns = [];
|
|
889
|
+
if (!importSource.disableAutoSource) autoPatterns = importSource.roots.length > 0 ? importSource.roots.map((root) => resolveFromConfig(normalizeSourcePattern(root))) : [DEFAULT_FILE_PATTERN];
|
|
890
|
+
const autoFiles = autoPatterns.length > 0 ? await expandPatterns(discoveryCwd, autoPatterns, extraIgnore) : [];
|
|
891
|
+
const explicitFiles = explicitSourcePatterns.length > 0 ? await expandPatterns(discoveryCwd, explicitSourcePatterns, resolvedExclude) : [];
|
|
892
|
+
return resolveDiscoveredFiles(includeConfigFile([.../* @__PURE__ */ new Set([...autoFiles, ...explicitFiles])].sort((a, b) => a.localeCompare(b))));
|
|
893
|
+
}
|
|
894
|
+
function normalizeSourcePattern(pattern) {
|
|
895
|
+
if (GLOB_PATTERN_REGEX.test(pattern) || node_path.extname(pattern)) return pattern;
|
|
896
|
+
return node_path.join(pattern, SOURCE_FILE_PATTERN);
|
|
873
897
|
}
|
|
874
898
|
function extractContentPatterns(config) {
|
|
875
899
|
if (!config.content) return [];
|
|
@@ -954,7 +978,7 @@ async function initializeState(cwd, configPath, verbose = false) {
|
|
|
954
978
|
async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verbose = false, onProgress }) {
|
|
955
979
|
const state = await initializeState(cwd, configPath, verbose);
|
|
956
980
|
const discoveredFiles = await discoverFiles(cwd, patterns, configPath, autoDiscover);
|
|
957
|
-
const files = state.configPath && isCssConfigFile(state.configPath) && fileExists(state.configPath) ? [
|
|
981
|
+
const files = uniqueFilesByResolvedPath(cwd, state.configPath && isCssConfigFile(state.configPath) && fileExists(state.configPath) ? [node_path.relative(cwd, state.configPath), ...discoveredFiles] : discoveredFiles);
|
|
958
982
|
const skippedFiles = [];
|
|
959
983
|
const lintableFiles = files.filter((file) => {
|
|
960
984
|
if (getFileSize(node_path.isAbsolute(file) ? file : node_path.resolve(cwd, file)) > 524288) {
|
|
@@ -978,6 +1002,17 @@ async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verb
|
|
|
978
1002
|
skippedFiles
|
|
979
1003
|
};
|
|
980
1004
|
}
|
|
1005
|
+
function uniqueFilesByResolvedPath(cwd, files) {
|
|
1006
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1007
|
+
const unique = [];
|
|
1008
|
+
for (const file of files) {
|
|
1009
|
+
const absolutePath = node_path.isAbsolute(file) ? file : node_path.resolve(cwd, file);
|
|
1010
|
+
if (seen.has(absolutePath)) continue;
|
|
1011
|
+
seen.add(absolutePath);
|
|
1012
|
+
unique.push(file);
|
|
1013
|
+
}
|
|
1014
|
+
return unique.sort((a, b) => a.localeCompare(b));
|
|
1015
|
+
}
|
|
981
1016
|
//#endregion
|
|
982
1017
|
Object.defineProperty(exports, "DEFAULT_FILE_PATTERN", {
|
|
983
1018
|
enumerable: true,
|
|
@@ -1015,6 +1050,18 @@ Object.defineProperty(exports, "extractSourcePatterns", {
|
|
|
1015
1050
|
return extractSourcePatterns;
|
|
1016
1051
|
}
|
|
1017
1052
|
});
|
|
1053
|
+
Object.defineProperty(exports, "findProjectRoot", {
|
|
1054
|
+
enumerable: true,
|
|
1055
|
+
get: function() {
|
|
1056
|
+
return findProjectRoot;
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
Object.defineProperty(exports, "isCssConfigFile", {
|
|
1060
|
+
enumerable: true,
|
|
1061
|
+
get: function() {
|
|
1062
|
+
return isCssConfigFile;
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1018
1065
|
Object.defineProperty(exports, "lint", {
|
|
1019
1066
|
enumerable: true,
|
|
1020
1067
|
get: function() {
|
package/dist/linter.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_linter = require("./linter-
|
|
2
|
+
const require_linter = require("./linter-BP0uKBfa.cjs");
|
|
3
3
|
exports.extractImportSourceDirectives = require_linter.extractImportSourceDirectives;
|
|
4
4
|
exports.extractSourcePatterns = require_linter.extractSourcePatterns;
|
|
5
5
|
exports.lint = require_linter.lint;
|
package/dist/linter.d.cts
CHANGED
|
@@ -383,14 +383,6 @@ declare function extractImportSourceDirectives(cssContent: string): {
|
|
|
383
383
|
roots: string[];
|
|
384
384
|
disableAutoSource: boolean;
|
|
385
385
|
};
|
|
386
|
-
declare function lint({
|
|
387
|
-
cwd,
|
|
388
|
-
patterns,
|
|
389
|
-
configPath,
|
|
390
|
-
autoDiscover,
|
|
391
|
-
fix,
|
|
392
|
-
verbose,
|
|
393
|
-
onProgress
|
|
394
|
-
}: LintOptions): Promise<LintResult>;
|
|
386
|
+
declare function lint({ cwd, patterns, configPath, autoDiscover, fix, verbose, onProgress }: LintOptions): Promise<LintResult>;
|
|
395
387
|
//#endregion
|
|
396
388
|
export { type LintFileResult, type LintOptions, type LintResult, extractImportSourceDirectives, extractSourcePatterns, lint };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwind-lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "A command-line tool that uses the Tailwind CSS IntelliSense plugin to show linting suggestions for your Tailwind CSS classes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -61,21 +61,21 @@
|
|
|
61
61
|
"@tailwindcss/language-service": "^0.14.29",
|
|
62
62
|
"ansis": "^4.3.1",
|
|
63
63
|
"commander": "^15.0.0",
|
|
64
|
-
"postcss": "^8.5.
|
|
64
|
+
"postcss": "^8.5.19",
|
|
65
65
|
"tinyglobby": "^0.2.17",
|
|
66
66
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@types/node": "^
|
|
70
|
-
"oxfmt": "^0.
|
|
71
|
-
"oxlint": "^1.
|
|
72
|
-
"tsdown": "^0.22.
|
|
73
|
-
"typescript": "^
|
|
74
|
-
"vitest": "^4.1.
|
|
69
|
+
"@types/node": "^26.1.1",
|
|
70
|
+
"oxfmt": "^0.58.0",
|
|
71
|
+
"oxlint": "^1.73.0",
|
|
72
|
+
"tsdown": "^0.22.7",
|
|
73
|
+
"typescript": "^7.0.2",
|
|
74
|
+
"vitest": "^4.1.10"
|
|
75
75
|
},
|
|
76
76
|
"engines": {
|
|
77
77
|
"node": ">=22.0.0",
|
|
78
78
|
"pnpm": ">=10.0.0"
|
|
79
79
|
},
|
|
80
|
-
"packageManager": "pnpm@11.
|
|
80
|
+
"packageManager": "pnpm@11.13.0"
|
|
81
81
|
}
|