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-B9R7nuem.cjs");
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
- cwd = node_path.dirname(configPath);
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(cwd, patterns);
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(cwd, configFilePath);
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(cwd, absolutePattern);
878
+ return node_path.relative(discoveryCwd, absolutePattern);
865
879
  };
866
880
  const resolvedExclude = exclude.map(resolveFromConfig);
867
- const gitignorePatterns = readGitignorePatterns(cwd);
881
+ const gitignorePatterns = readGitignorePatterns(discoveryCwd);
868
882
  const extraIgnore = [...resolvedExclude, ...gitignorePatterns];
869
- if (include.length > 0) return includeConfigFile(await expandPatterns(cwd, include.map(resolveFromConfig), extraIgnore));
870
- if (importSource.roots.length > 0) return includeConfigFile(await expandPatterns(cwd, importSource.roots.map((root) => resolveFromConfig(node_path.join(root, "**/*.{js,jsx,ts,tsx,html,vue,svelte,astro,mdx}"))), extraIgnore));
871
- if (importSource.disableAutoSource) return includeConfigFile([]);
872
- return includeConfigFile(await expandPatterns(cwd, [DEFAULT_FILE_PATTERN], extraIgnore));
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) ? [...new Set([node_path.relative(cwd, state.configPath), ...discoveredFiles])].sort((a, b) => a.localeCompare(b)) : discoveredFiles;
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-B9R7nuem.cjs");
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.11.2",
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.1",
70
- "oxfmt": "^0.53.0",
71
- "oxlint": "^1.68.0",
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.1"
80
+ "packageManager": "pnpm@11.5.3"
81
81
  }