tailwind-lint 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_linter = require("./linter-
|
|
2
|
+
const require_linter = require("./linter-DQMo7IYe.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
|
}
|
|
@@ -628,7 +628,17 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
|
|
|
628
628
|
//#region src/utils/config.ts
|
|
629
629
|
const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
|
|
630
630
|
const CONFIG_DISCOVERY_MAX_DEPTH = 8;
|
|
631
|
+
const PROJECT_ROOT_MARKERS = ["package.json", ".git"];
|
|
631
632
|
const isCssConfigFile = (filePath) => filePath.endsWith(".css");
|
|
633
|
+
function findProjectRoot(startDir) {
|
|
634
|
+
let current = node_path.resolve(startDir);
|
|
635
|
+
while (true) {
|
|
636
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => fileExists(node_path.join(current, marker)))) return current;
|
|
637
|
+
const parent = node_path.dirname(current);
|
|
638
|
+
if (parent === current) return node_path.resolve(startDir);
|
|
639
|
+
current = parent;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
632
642
|
function syntheticViteCssConfigPath(viteConfigPath) {
|
|
633
643
|
return node_path.join(node_path.dirname(viteConfigPath), SYNTHETIC_VITE_CSS_CONFIG_NAME);
|
|
634
644
|
}
|
|
@@ -653,17 +663,6 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
653
663
|
const resolved = node_path.isAbsolute(configPath) ? configPath : node_path.resolve(cwd, configPath);
|
|
654
664
|
return fileExists(resolved) ? resolved : null;
|
|
655
665
|
}
|
|
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
666
|
const v4Paths = V4_CSS_FOLDERS.flatMap((folder) => V4_CSS_NAMES.map((name) => node_path.join(folder, name)));
|
|
668
667
|
for (const p of v4Paths) {
|
|
669
668
|
const fullPath = node_path.join(cwd, p);
|
|
@@ -672,6 +671,10 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
672
671
|
if (TAILWIND_V4_IMPORT_REGEX.test(content)) return fullPath;
|
|
673
672
|
} catch {}
|
|
674
673
|
}
|
|
674
|
+
for (const p of V3_CONFIG_PATHS) {
|
|
675
|
+
const fullPath = node_path.join(cwd, p);
|
|
676
|
+
if (fileExists(fullPath)) return fullPath;
|
|
677
|
+
}
|
|
675
678
|
const cssCandidates = await (0, tinyglobby.glob)("**/*.css", {
|
|
676
679
|
cwd,
|
|
677
680
|
absolute: true,
|
|
@@ -684,6 +687,13 @@ async function findTailwindConfigPath(cwd, configPath) {
|
|
|
684
687
|
if (TAILWIND_V4_IMPORT_REGEX.test(content)) v4Matches.push(candidate);
|
|
685
688
|
} catch {}
|
|
686
689
|
if (v4Matches.length > 0) return sortCssCandidates(cwd, v4Matches)[0];
|
|
690
|
+
const v3Recursive = await (0, tinyglobby.glob)(V3_CONFIG_PATHS.map((p) => `**/${p}`), {
|
|
691
|
+
cwd,
|
|
692
|
+
absolute: true,
|
|
693
|
+
ignore: DEFAULT_IGNORE_PATTERNS,
|
|
694
|
+
deep: CONFIG_DISCOVERY_MAX_DEPTH
|
|
695
|
+
});
|
|
696
|
+
if (v3Recursive.length > 0) return sortByPathDepth(v3Recursive)[0];
|
|
687
697
|
const viteConfigPath = await findTailwindViteConfigPath(cwd);
|
|
688
698
|
if (viteConfigPath) return syntheticViteCssConfigPath(viteConfigPath);
|
|
689
699
|
return null;
|
|
@@ -810,6 +820,8 @@ async function createState(cwd, configPath, verbose = false) {
|
|
|
810
820
|
}
|
|
811
821
|
//#endregion
|
|
812
822
|
//#region src/linter.ts
|
|
823
|
+
const SOURCE_FILE_PATTERN = "**/*.{js,jsx,ts,tsx,html,vue,svelte,astro,mdx}";
|
|
824
|
+
const GLOB_PATTERN_REGEX = /[*?[\]{}]/;
|
|
813
825
|
async function validateDocument(state, filePath, content) {
|
|
814
826
|
try {
|
|
815
827
|
if (!state) throw new Error("State is not initialized");
|
|
@@ -843,33 +855,41 @@ async function expandPatterns(cwd, patterns, extraIgnore = []) {
|
|
|
843
855
|
async function discoverFilesFromConfig(cwd, configPath) {
|
|
844
856
|
const configFilePath = await findTailwindConfigPath(cwd, configPath);
|
|
845
857
|
if (!configFilePath) throw new Error("Could not find Tailwind config for auto-discovery.\nUse --config to specify the path, or provide file patterns directly.");
|
|
858
|
+
const discoveryCwd = isCssConfigFile(configFilePath) ? findProjectRoot(node_path.dirname(configFilePath)) : cwd;
|
|
846
859
|
if (!isCssConfigFile(configFilePath)) {
|
|
847
860
|
const config = await loadTailwindConfig(configFilePath);
|
|
848
861
|
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
862
|
const patterns = extractContentPatterns(config);
|
|
850
863
|
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(
|
|
864
|
+
return expandPatterns(discoveryCwd, patterns);
|
|
852
865
|
}
|
|
853
866
|
const configDir = node_path.dirname(configFilePath);
|
|
854
867
|
const cssContent = fileExists(configFilePath) ? readFileSync(configFilePath) : SYNTHETIC_VITE_CSS_CONFIG_CONTENT;
|
|
855
868
|
const includeConfigFile = (files) => {
|
|
856
869
|
if (!fileExists(configFilePath)) return files;
|
|
857
|
-
const relativeConfigPath = node_path.relative(
|
|
870
|
+
const relativeConfigPath = node_path.relative(discoveryCwd, configFilePath);
|
|
858
871
|
return [...new Set([relativeConfigPath, ...files])].sort((a, b) => a.localeCompare(b));
|
|
859
872
|
};
|
|
873
|
+
const resolveDiscoveredFiles = (files) => discoveryCwd === cwd ? files : files.map((file) => node_path.resolve(discoveryCwd, file)).sort((a, b) => a.localeCompare(b));
|
|
860
874
|
const { include, exclude } = extractSourcePatterns(cssContent);
|
|
861
875
|
const importSource = extractImportSourceDirectives(cssContent);
|
|
862
876
|
const resolveFromConfig = (pattern) => {
|
|
863
877
|
const absolutePattern = node_path.resolve(configDir, pattern);
|
|
864
|
-
return node_path.relative(
|
|
878
|
+
return node_path.relative(discoveryCwd, absolutePattern);
|
|
865
879
|
};
|
|
866
880
|
const resolvedExclude = exclude.map(resolveFromConfig);
|
|
867
|
-
const gitignorePatterns = readGitignorePatterns(
|
|
881
|
+
const gitignorePatterns = readGitignorePatterns(discoveryCwd);
|
|
868
882
|
const extraIgnore = [...resolvedExclude, ...gitignorePatterns];
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
if (importSource.disableAutoSource)
|
|
872
|
-
|
|
883
|
+
const explicitSourcePatterns = include.map((source) => resolveFromConfig(normalizeSourcePattern(source)));
|
|
884
|
+
let autoPatterns = [];
|
|
885
|
+
if (!importSource.disableAutoSource) autoPatterns = importSource.roots.length > 0 ? importSource.roots.map((root) => resolveFromConfig(normalizeSourcePattern(root))) : [DEFAULT_FILE_PATTERN];
|
|
886
|
+
const autoFiles = autoPatterns.length > 0 ? await expandPatterns(discoveryCwd, autoPatterns, extraIgnore) : [];
|
|
887
|
+
const explicitFiles = explicitSourcePatterns.length > 0 ? await expandPatterns(discoveryCwd, explicitSourcePatterns, resolvedExclude) : [];
|
|
888
|
+
return resolveDiscoveredFiles(includeConfigFile([...new Set([...autoFiles, ...explicitFiles])].sort((a, b) => a.localeCompare(b))));
|
|
889
|
+
}
|
|
890
|
+
function normalizeSourcePattern(pattern) {
|
|
891
|
+
if (GLOB_PATTERN_REGEX.test(pattern) || node_path.extname(pattern)) return pattern;
|
|
892
|
+
return node_path.join(pattern, SOURCE_FILE_PATTERN);
|
|
873
893
|
}
|
|
874
894
|
function extractContentPatterns(config) {
|
|
875
895
|
if (!config.content) return [];
|
|
@@ -954,7 +974,7 @@ async function initializeState(cwd, configPath, verbose = false) {
|
|
|
954
974
|
async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verbose = false, onProgress }) {
|
|
955
975
|
const state = await initializeState(cwd, configPath, verbose);
|
|
956
976
|
const discoveredFiles = await discoverFiles(cwd, patterns, configPath, autoDiscover);
|
|
957
|
-
const files = state.configPath && isCssConfigFile(state.configPath) && fileExists(state.configPath) ? [
|
|
977
|
+
const files = uniqueFilesByResolvedPath(cwd, state.configPath && isCssConfigFile(state.configPath) && fileExists(state.configPath) ? [node_path.relative(cwd, state.configPath), ...discoveredFiles] : discoveredFiles);
|
|
958
978
|
const skippedFiles = [];
|
|
959
979
|
const lintableFiles = files.filter((file) => {
|
|
960
980
|
if (getFileSize(node_path.isAbsolute(file) ? file : node_path.resolve(cwd, file)) > 524288) {
|
|
@@ -978,6 +998,17 @@ async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verb
|
|
|
978
998
|
skippedFiles
|
|
979
999
|
};
|
|
980
1000
|
}
|
|
1001
|
+
function uniqueFilesByResolvedPath(cwd, files) {
|
|
1002
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1003
|
+
const unique = [];
|
|
1004
|
+
for (const file of files) {
|
|
1005
|
+
const absolutePath = node_path.isAbsolute(file) ? file : node_path.resolve(cwd, file);
|
|
1006
|
+
if (seen.has(absolutePath)) continue;
|
|
1007
|
+
seen.add(absolutePath);
|
|
1008
|
+
unique.push(file);
|
|
1009
|
+
}
|
|
1010
|
+
return unique.sort((a, b) => a.localeCompare(b));
|
|
1011
|
+
}
|
|
981
1012
|
//#endregion
|
|
982
1013
|
Object.defineProperty(exports, "DEFAULT_FILE_PATTERN", {
|
|
983
1014
|
enumerable: true,
|
|
@@ -1015,6 +1046,18 @@ Object.defineProperty(exports, "extractSourcePatterns", {
|
|
|
1015
1046
|
return extractSourcePatterns;
|
|
1016
1047
|
}
|
|
1017
1048
|
});
|
|
1049
|
+
Object.defineProperty(exports, "findProjectRoot", {
|
|
1050
|
+
enumerable: true,
|
|
1051
|
+
get: function() {
|
|
1052
|
+
return findProjectRoot;
|
|
1053
|
+
}
|
|
1054
|
+
});
|
|
1055
|
+
Object.defineProperty(exports, "isCssConfigFile", {
|
|
1056
|
+
enumerable: true,
|
|
1057
|
+
get: function() {
|
|
1058
|
+
return isCssConfigFile;
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1018
1061
|
Object.defineProperty(exports, "lint", {
|
|
1019
1062
|
enumerable: true,
|
|
1020
1063
|
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-DQMo7IYe.cjs");
|
|
3
3
|
exports.extractImportSourceDirectives = require_linter.extractImportSourceDirectives;
|
|
4
4
|
exports.extractSourcePatterns = require_linter.extractSourcePatterns;
|
|
5
5
|
exports.lint = require_linter.lint;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwind-lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "A command-line tool that uses the Tailwind CSS IntelliSense plugin to show linting suggestions for your Tailwind CSS classes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@types/node": "^25.9.
|
|
70
|
-
"oxfmt": "^0.
|
|
71
|
-
"oxlint": "^1.
|
|
69
|
+
"@types/node": "^25.9.3",
|
|
70
|
+
"oxfmt": "^0.54.0",
|
|
71
|
+
"oxlint": "^1.69.0",
|
|
72
72
|
"tsdown": "^0.22.2",
|
|
73
73
|
"typescript": "^6.0.3",
|
|
74
74
|
"vitest": "^4.1.8"
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"node": ">=22.0.0",
|
|
78
78
|
"pnpm": ">=10.0.0"
|
|
79
79
|
},
|
|
80
|
-
"packageManager": "pnpm@11.5.
|
|
80
|
+
"packageManager": "pnpm@11.5.3"
|
|
81
81
|
}
|