tailwind-lint 0.12.1 → 0.13.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/README.md CHANGED
@@ -60,7 +60,15 @@ tailwind-lint --verbose
60
60
  **Tailwind CSS v3:**
61
61
 
62
62
  - Finds JavaScript config files: `tailwind.config.js`, `tailwind.config.cjs`, `tailwind.config.mjs`, `tailwind.config.ts`
63
- - Uses file patterns from the `content` array in your config
63
+ - Uses file patterns from the `content` array in your config, resolved from the package root (or from the config file with `content.relative: true`)
64
+
65
+ **Monorepos:**
66
+
67
+ - Workspace packages from `package.json` `workspaces` or `pnpm-workspace.yaml` are detected; without a workspace definition every directory with a `package.json` is treated as a package
68
+ - Each package gets its own config detected; packages without one fall back to the closest parent config
69
+ - Each file is linted with the config of the closest package that contains it, so apps with different themes or Tailwind versions (v3 and v4 side by side) are linted correctly
70
+ - `tailwindcss` is resolved from the config's package first, falling back to the working directory
71
+ - Use `--verbose` to see which config each package uses
64
72
 
65
73
  ### Options
66
74
 
package/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_linter = require("./linter-BP0uKBfa.cjs");
2
+ const require_linter = require("./linter-gjoSGNMw.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");
@@ -101,15 +101,13 @@ function createJsonErrorOutput({ error, cwd, configPath, autoDiscover, fix, patt
101
101
  //#region src/cli.ts
102
102
  const MAX_FILENAME_DISPLAY_LENGTH = 50;
103
103
  function resolveOptions(files, options) {
104
- const hasConfigFlag = !!options.config;
105
104
  const hasAutoFlag = !!options.auto;
106
105
  const hasFiles = files.length > 0;
107
106
  let cwd = process.cwd();
108
- let configPath = options.config;
107
+ const configPath = options.config && node_path.resolve(options.config);
109
108
  let patterns = files;
110
109
  let autoDiscover = hasAutoFlag;
111
- if (hasConfigFlag && options.config) configPath = node_path.isAbsolute(options.config) ? options.config : node_path.resolve(process.cwd(), options.config);
112
- if (hasConfigFlag && options.config && !hasFiles) {
110
+ if (configPath && !hasFiles) {
113
111
  const configDir = node_path.dirname(configPath);
114
112
  cwd = require_linter.isCssConfigFile(configPath) ? require_linter.findProjectRoot(configDir) : configDir;
115
113
  patterns = [];
@@ -158,11 +156,12 @@ async function displayResults(files, fixMode) {
158
156
  }
159
157
  }
160
158
  console.log();
161
- if (totalErrors === 0 && totalWarnings === 0) if (totalFixed > 0) {
162
- const issueText = `${totalFixed} issue${totalFixed !== 1 ? "s" : ""}`;
163
- console.log(ansis.default.green.bold(`✔ Fixed ${issueText}`));
164
- } else console.log(ansis.default.green.bold("✔ No issues found"));
165
- else {
159
+ if (totalErrors === 0 && totalWarnings === 0) {
160
+ if (totalFixed > 0) {
161
+ const issueText = `${totalFixed} issue${totalFixed !== 1 ? "s" : ""}`;
162
+ console.log(ansis.default.green.bold(`✔ Fixed ${issueText}`));
163
+ } else console.log(ansis.default.green.bold("✔ No issues found"));
164
+ } else {
166
165
  const parts = [];
167
166
  if (totalErrors > 0) parts.push(`${totalErrors} error${totalErrors !== 1 ? "s" : ""}`);
168
167
  if (totalWarnings > 0) parts.push(`${totalWarnings} warning${totalWarnings !== 1 ? "s" : ""}`);
package/dist/cli.d.cts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
@@ -15,7 +15,7 @@ var __copyProps = (to, from, except, desc) => {
15
15
  }
16
16
  return to;
17
17
  };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
19
  value: mod,
20
20
  enumerable: true
21
21
  }) : target, mod));
@@ -32,6 +32,7 @@ let node_fs = require("node:fs");
32
32
  node_fs = __toESM(node_fs, 1);
33
33
  let postcss = require("postcss");
34
34
  postcss = __toESM(postcss, 1);
35
+ let node_fs_promises = require("node:fs/promises");
35
36
  //#region src/constants.ts
36
37
  const DEFAULT_IGNORE_PATTERNS = [
37
38
  "**/node_modules/**",
@@ -90,7 +91,6 @@ const VITE_CONFIG_PATHS = [
90
91
  "vite.config.mts",
91
92
  "vite.config.cts"
92
93
  ];
93
- const SYNTHETIC_VITE_CSS_CONFIG_NAME = ".tailwind-lint.vite.css";
94
94
  const SYNTHETIC_VITE_CSS_CONFIG_CONTENT = "@import \"tailwindcss\";";
95
95
  const LANGUAGE_MAP = {
96
96
  ".astro": "astro",
@@ -134,7 +134,7 @@ async function getQuickfixes(state, document, uri, diagnostics) {
134
134
  code: diag.code,
135
135
  source: diag.source || "tailwindcss"
136
136
  }));
137
- return (await (0, _tailwindcss_language_service.doCodeActions)(state, {
137
+ const params = {
138
138
  textDocument: { uri },
139
139
  range: {
140
140
  start: {
@@ -147,7 +147,8 @@ async function getQuickfixes(state, document, uri, diagnostics) {
147
147
  }
148
148
  },
149
149
  context: { diagnostics: lspDiagnostics }
150
- }, document)).filter((action) => action.kind === "quickfix" || action.kind?.startsWith(`quickfix.`));
150
+ };
151
+ return (await (0, _tailwindcss_language_service.doCodeActions)(state, params, document)).filter((action) => action.kind === "quickfix" || action.kind?.startsWith(`quickfix.`));
151
152
  }
152
153
  function applyFirstQuickfix(action, uri, document, content) {
153
154
  if (!action.edit?.changes?.[uri]) return null;
@@ -257,7 +258,7 @@ function readVsCodeTailwindSettings(cwd) {
257
258
  const files = readNestedObject(raw, "tailwindCSS.files");
258
259
  const lint = readNestedObject(raw, "tailwindCSS.lint");
259
260
  return {
260
- includeLanguages: asRecord(raw["tailwindCSS.includeLanguages"]),
261
+ includeLanguages: asStringRecord(raw["tailwindCSS.includeLanguages"]),
261
262
  classAttributes: asStringArray(raw["tailwindCSS.classAttributes"]),
262
263
  classFunctions: asStringArray(raw["tailwindCSS.classFunctions"]),
263
264
  experimental: {
@@ -275,7 +276,7 @@ function readZedTailwindSettings(cwd) {
275
276
  const normalized = asRecord(serverSettings?.tailwindCSS) ?? serverSettings;
276
277
  if (!normalized) return {};
277
278
  return {
278
- includeLanguages: asRecord(normalized.includeLanguages),
279
+ includeLanguages: asStringRecord(normalized.includeLanguages),
279
280
  classAttributes: asStringArray(normalized.classAttributes),
280
281
  classFunctions: asStringArray(normalized.classFunctions),
281
282
  experimental: {
@@ -303,6 +304,11 @@ function readNestedObject(input, key) {
303
304
  function asRecord(value) {
304
305
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
305
306
  }
307
+ function asStringRecord(value) {
308
+ const record = asRecord(value);
309
+ if (!record) return;
310
+ return Object.fromEntries(Object.entries(record).filter((entry) => typeof entry[1] === "string"));
311
+ }
306
312
  function asStringArray(value) {
307
313
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
308
314
  }
@@ -440,6 +446,7 @@ function createEditorState(cwd) {
440
446
  invalidApply: "error",
441
447
  invalidScreen: "error",
442
448
  invalidVariant: "error",
449
+ deprecatedAtRule: "warning",
443
450
  invalidConfigPath: "error",
444
451
  invalidTailwindDirective: "error",
445
452
  invalidSourceDirective: "error",
@@ -456,6 +463,7 @@ function createEditorState(cwd) {
456
463
  capabilities: {
457
464
  configuration: true,
458
465
  diagnosticRelatedInformation: true,
466
+ diagnosticTagSupport: false,
459
467
  itemDefaults: []
460
468
  },
461
469
  getConfiguration: async () => settings,
@@ -487,50 +495,40 @@ var AdapterLoadError = class extends Error {
487
495
  //#endregion
488
496
  //#region src/adapters/v3-adapter.ts
489
497
  const require$4 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
490
- async function loadV3ClassMetadata(state, cwd, verbose = false) {
498
+ function interopDefault(module) {
499
+ return module && typeof module === "object" && "default" in module ? module.default : module;
500
+ }
501
+ async function loadV3ClassMetadata(state, resolvePaths, verbose = false) {
491
502
  try {
492
- const tailwindPath = require$4.resolve("tailwindcss", { paths: [cwd] });
493
- const tailwindcss = require$4(tailwindPath);
494
- try {
495
- const tailwindDir = node_path.dirname(require$4.resolve("tailwindcss/package.json", { paths: [cwd] }));
496
- const contextUtils = require$4(node_path.join(tailwindDir, "lib", "lib", "setupContextUtils"));
497
- const generateRulesModule = require$4(node_path.join(tailwindDir, "lib", "lib", "generateRules"));
498
- state.modules = {
499
- tailwindcss: {
500
- version: state.version || "unknown",
501
- module: tailwindcss
502
- },
503
- jit: {
504
- generateRules: { module: generateRulesModule.generateRules || ((_set, _context) => []) },
505
- createContext: { module: contextUtils.createContext },
506
- expandApplyAtRules: { module: generateRulesModule.expandApplyAtRules }
507
- }
508
- };
509
- if (verbose) console.log(ansis.default.dim(" ✓ Loaded v3 JIT modules"));
510
- } catch (jitError) {
511
- if (verbose) {
512
- const message = jitError instanceof Error ? jitError.message : String(jitError);
513
- console.log(ansis.default.yellow(` ⚠ Warning: Could not load v3 JIT modules: ${message}`));
514
- }
515
- state.modules = { tailwindcss: {
503
+ const tailwindDir = node_path.dirname(require$4.resolve("tailwindcss/package.json", { paths: resolvePaths }));
504
+ const load = (id) => require$4(require$4.resolve(id, { paths: [tailwindDir] }));
505
+ const loadLib = (name) => require$4(node_path.join(tailwindDir, "lib", "lib", name));
506
+ const { createContext } = loadLib("setupContextUtils");
507
+ const { generateRules } = loadLib("generateRules");
508
+ state.jit = true;
509
+ state.modules = {
510
+ tailwindcss: {
516
511
  version: state.version || "unknown",
517
- module: tailwindcss
518
- } };
519
- }
520
- extractConfigMetadata(state);
521
- if (!state.classNames) state.classNames = {
522
- context: {},
523
- classNames: {}
524
- };
525
- if (state.modules?.jit?.createContext && state.config) try {
526
- state.jitContext = state.modules.jit.createContext.module(state.config);
527
- if (verbose) console.log(ansis.default.dim(" ✓ Created JIT context"));
528
- } catch (contextError) {
529
- if (verbose) {
530
- const message = contextError instanceof Error ? contextError.message : String(contextError);
531
- console.log(ansis.default.yellow(` ⚠ Warning: Could not create JIT context: ${message}`));
512
+ module: load("tailwindcss")
513
+ },
514
+ postcss: {
515
+ version: load("postcss/package.json").version,
516
+ module: load("postcss")
517
+ },
518
+ postcssSelectorParser: { module: load("postcss-selector-parser") },
519
+ jit: {
520
+ generateRules: { module: generateRules },
521
+ createContext: { module: createContext },
522
+ expandApplyAtRules: { module: interopDefault(loadLib("expandApplyAtRules")) },
523
+ evaluateTailwindFunctions: { module: interopDefault(loadLib("evaluateTailwindFunctions")) }
532
524
  }
533
- }
525
+ };
526
+ extractConfigMetadata(state);
527
+ const jitContext = createContext(state.config);
528
+ state.jitContext = jitContext;
529
+ state.classList = jitContext.getClassList?.({ includeMetadata: true });
530
+ state.variants = jitContext.getVariants?.() ?? [];
531
+ if (verbose) console.log(ansis.default.dim(" ✓ Created v3 JIT context"));
534
532
  } catch (error) {
535
533
  if (error instanceof Error) throw new AdapterLoadError("v3", error);
536
534
  throw new Error(`Failed to load v3 class metadata: ${String(error)}`);
@@ -542,33 +540,50 @@ function extractConfigMetadata(state) {
542
540
  const theme = config.theme;
543
541
  state.screens = Object.keys(theme?.screens ?? {});
544
542
  state.blocklist = config.blocklist ?? [];
545
- if (config.variants && typeof config.variants === "object") state.variants = Object.keys(config.variants).map((name) => ({
546
- name,
547
- values: [],
548
- isArbitrary: false,
549
- hasDash: true,
550
- selectors: () => []
551
- }));
552
543
  if (config.corePlugins) state.corePlugins = Array.isArray(config.corePlugins) ? config.corePlugins : Object.keys(config.corePlugins);
553
544
  }
554
545
  //#endregion
555
546
  //#region src/adapters/v4-adapter.ts
556
547
  const require$3 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
557
- async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
548
+ function fromPostcss(nodes) {
549
+ return nodes.map((node) => {
550
+ switch (node.type) {
551
+ case "rule": return {
552
+ kind: "rule",
553
+ selector: node.selector,
554
+ nodes: fromPostcss(node.nodes)
555
+ };
556
+ case "atrule": return {
557
+ kind: "at-rule",
558
+ name: node.name,
559
+ params: node.params,
560
+ nodes: node.nodes ? fromPostcss(node.nodes) : null
561
+ };
562
+ case "decl": return {
563
+ kind: "declaration",
564
+ property: node.prop,
565
+ value: node.value,
566
+ important: node.important
567
+ };
568
+ default: return {
569
+ kind: "comment",
570
+ value: node.text
571
+ };
572
+ }
573
+ });
574
+ }
575
+ async function loadV4DesignSystem(state, resolvePaths, target, verbose = false) {
558
576
  try {
559
- const tailwindPath = require$3.resolve("tailwindcss", { paths: [cwd] });
577
+ const tailwindPath = require$3.resolve("tailwindcss", { paths: resolvePaths });
560
578
  const tailwindcss = require$3(tailwindPath);
561
579
  if (tailwindcss !== null && tailwindcss !== void 0 && (typeof tailwindcss === "object" || typeof tailwindcss === "function") && "__unstable__loadDesignSystem" in tailwindcss && typeof tailwindcss.__unstable__loadDesignSystem === "function") {
562
- let cssContent;
563
- const basePath = node_path.dirname(configPath);
564
- if (fileExists(configPath)) cssContent = readFileSync(configPath);
565
- else cssContent = SYNTHETIC_VITE_CSS_CONFIG_CONTENT;
580
+ const cssContent = target.kind === "vite" ? SYNTHETIC_VITE_CSS_CONFIG_CONTENT : readFileSync(target.path);
566
581
  const loadDesignSystem = tailwindcss.__unstable__loadDesignSystem;
567
582
  const designSystem = await loadDesignSystem(cssContent, {
568
- base: basePath,
583
+ base: node_path.dirname(target.path),
569
584
  async loadModule(id, base, _type) {
570
585
  try {
571
- const modulePath = require$3.resolve(id, { paths: [base, cwd] });
586
+ const modulePath = require$3.resolve(id, { paths: [base, ...resolvePaths] });
572
587
  const module = require$3(modulePath);
573
588
  return {
574
589
  base: node_path.dirname(modulePath),
@@ -584,7 +599,7 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
584
599
  content
585
600
  };
586
601
  if (!_id.startsWith(".") && !_id.startsWith("/")) try {
587
- const pkgJsonPath = require$3.resolve(`${_id}/package.json`, { paths: [base, cwd] });
602
+ const pkgJsonPath = require$3.resolve(`${_id}/package.json`, { paths: [base, ...resolvePaths] });
588
603
  const pkgDir = node_path.dirname(pkgJsonPath);
589
604
  const cssPath = node_path.join(pkgDir, "index.css");
590
605
  if (fileExists(cssPath)) return {
@@ -606,15 +621,16 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
606
621
  Object.assign(designSystem, {
607
622
  dependencies: () => /* @__PURE__ */ new Set(),
608
623
  compile(classes) {
609
- if (designSystem.candidatesToCss) return designSystem.candidatesToCss(classes).map((result) => {
610
- if (typeof result === "string" && result.length > 0) try {
611
- return postcss.default.parse(result);
624
+ if (designSystem.candidatesToAst) return designSystem.candidatesToAst(classes);
625
+ if (designSystem.candidatesToCss) return designSystem.candidatesToCss(classes).map((css) => {
626
+ if (!css) return [];
627
+ try {
628
+ return fromPostcss(postcss.default.parse(css).nodes);
612
629
  } catch {
613
- return postcss.default.root();
630
+ return [];
614
631
  }
615
- return postcss.default.root();
616
632
  });
617
- return classes.map(() => postcss.default.root());
633
+ return classes.map(() => []);
618
634
  }
619
635
  });
620
636
  state.designSystem = designSystem;
@@ -632,6 +648,7 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
632
648
  const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
633
649
  const CONFIG_DISCOVERY_MAX_DEPTH = 8;
634
650
  const PROJECT_ROOT_MARKERS = ["package.json", ".git"];
651
+ const VITE_CONFIG_NAME_REGEX = /^vite\.config\.[cm]?[jt]s$/;
635
652
  const isCssConfigFile = (filePath) => filePath.endsWith(".css");
636
653
  function findProjectRoot(startDir) {
637
654
  let current = node_path.resolve(startDir);
@@ -642,9 +659,6 @@ function findProjectRoot(startDir) {
642
659
  current = parent;
643
660
  }
644
661
  }
645
- function syntheticViteCssConfigPath(viteConfigPath) {
646
- return node_path.join(node_path.dirname(viteConfigPath), SYNTHETIC_VITE_CSS_CONFIG_NAME);
647
- }
648
662
  async function loadTailwindConfig(configPath) {
649
663
  if (isCssConfigFile(configPath)) return {};
650
664
  if (!node_path.isAbsolute(configPath)) throw new Error(`Config path must be absolute for security reasons: ${configPath}`);
@@ -661,66 +675,116 @@ async function loadTailwindConfig(configPath) {
661
675
  throw new Error(`Failed to load config from ${configPath}: ${errorMessage}`);
662
676
  }
663
677
  }
664
- async function findTailwindConfigPath(cwd, configPath) {
665
- if (configPath) {
666
- const resolved = node_path.isAbsolute(configPath) ? configPath : node_path.resolve(cwd, configPath);
667
- return fileExists(resolved) ? resolved : null;
668
- }
669
- const v4Paths = V4_CSS_FOLDERS.flatMap((folder) => V4_CSS_NAMES.map((name) => node_path.join(folder, name)));
670
- for (const p of v4Paths) {
671
- const fullPath = node_path.join(cwd, p);
672
- if (fileExists(fullPath)) try {
673
- const content = readFileSync(fullPath);
674
- if (TAILWIND_V4_IMPORT_REGEX.test(content)) return fullPath;
675
- } catch {}
676
- }
677
- for (const p of V3_CONFIG_PATHS) {
678
- const fullPath = node_path.join(cwd, p);
679
- if (fileExists(fullPath)) return fullPath;
680
- }
681
- const cssCandidates = await (0, tinyglobby.glob)("**/*.css", {
682
- cwd,
678
+ function toConfigTarget(configPath) {
679
+ return {
680
+ kind: configKind(configPath),
681
+ path: configPath,
682
+ root: findProjectRoot(node_path.dirname(configPath))
683
+ };
684
+ }
685
+ function configKind(configPath) {
686
+ if (isCssConfigFile(configPath)) return "css";
687
+ return VITE_CONFIG_NAME_REGEX.test(node_path.basename(configPath)) ? "vite" : "js";
688
+ }
689
+ async function findTailwindConfigs(cwd) {
690
+ const root = node_path.resolve(cwd);
691
+ const files = await (0, tinyglobby.glob)([
692
+ "**/package.json",
693
+ "**/*.css",
694
+ ...[...V3_CONFIG_PATHS, ...VITE_CONFIG_PATHS].map((p) => `**/${p}`)
695
+ ], {
696
+ cwd: root,
683
697
  absolute: true,
684
698
  ignore: DEFAULT_IGNORE_PATTERNS,
685
699
  deep: CONFIG_DISCOVERY_MAX_DEPTH
686
700
  });
687
- const v4Matches = [];
688
- for (const candidate of cssCandidates) try {
689
- const content = readFileSync(candidate);
690
- if (TAILWIND_V4_IMPORT_REGEX.test(content)) v4Matches.push(candidate);
691
- } catch {}
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,
701
+ const isPackageJson = (file) => node_path.basename(file) === "package.json";
702
+ const packageRoots = await findPackageRoots(root, files.filter(isPackageJson).map(node_path.dirname));
703
+ const deepestFirst = [...packageRoots].sort((a, b) => b.length - a.length);
704
+ const candidatesByRoot = new Map(packageRoots.map((packageRoot) => [packageRoot, []]));
705
+ for (const file of files) {
706
+ if (isPackageJson(file)) continue;
707
+ const owner = deepestFirst.find((packageRoot) => isInsideDir(packageRoot, file));
708
+ if (owner) candidatesByRoot.get(owner)?.push(file);
709
+ }
710
+ return {
711
+ targets: (await Promise.all([...candidatesByRoot].map(([packageRoot, candidates]) => pickConfig(packageRoot, candidates)))).filter((target) => target !== void 0),
712
+ packageRoots
713
+ };
714
+ }
715
+ async function findPackageRoots(root, packageDirs) {
716
+ const workspaces = await readWorkspacePatterns(root);
717
+ if (!workspaces) return [.../* @__PURE__ */ new Set([root, ...packageDirs])];
718
+ const toPackageJson = (pattern) => `${pattern.replace(/\/+$/, "")}/package.json`;
719
+ const workspacePackageJsons = await (0, tinyglobby.glob)(workspaces.filter((p) => !p.startsWith("!")).map(toPackageJson), {
720
+ cwd: root,
695
721
  absolute: true,
696
- ignore: DEFAULT_IGNORE_PATTERNS,
697
- deep: CONFIG_DISCOVERY_MAX_DEPTH
722
+ ignore: [...DEFAULT_IGNORE_PATTERNS, ...workspaces.filter((p) => p.startsWith("!")).map((p) => toPackageJson(p.slice(1)))]
698
723
  });
699
- if (v3Recursive.length > 0) return sortByPathDepth(v3Recursive)[0];
700
- const viteConfigPath = await findTailwindViteConfigPath(cwd);
701
- if (viteConfigPath) return syntheticViteCssConfigPath(viteConfigPath);
702
- return null;
703
- }
704
- async function findTailwindViteConfigPath(cwd) {
705
- for (const p of VITE_CONFIG_PATHS) {
706
- const fullPath = node_path.join(cwd, p);
707
- if (isTailwindViteConfig(fullPath)) return fullPath;
724
+ return [.../* @__PURE__ */ new Set([root, ...workspacePackageJsons.map(node_path.dirname)])];
725
+ }
726
+ async function readWorkspacePatterns(root) {
727
+ const [packageJson, pnpmWorkspace] = await Promise.all([readText(node_path.join(root, "package.json")), readText(node_path.join(root, "pnpm-workspace.yaml"))]);
728
+ const patterns = [...parsePackageJsonWorkspaces(packageJson), ...parsePnpmWorkspacePackages(pnpmWorkspace)];
729
+ return patterns.length > 0 ? patterns : void 0;
730
+ }
731
+ function parsePackageJsonWorkspaces(content) {
732
+ try {
733
+ const { workspaces } = JSON.parse(content);
734
+ return ((Array.isArray(workspaces) ? workspaces : workspaces?.packages) ?? []).filter((p) => typeof p === "string");
735
+ } catch {
736
+ return [];
708
737
  }
709
- const matches = (await (0, tinyglobby.glob)(VITE_CONFIG_PATHS.map((p) => `**/${p}`), {
710
- cwd,
711
- absolute: true,
712
- ignore: DEFAULT_IGNORE_PATTERNS,
713
- deep: CONFIG_DISCOVERY_MAX_DEPTH
714
- })).filter(isTailwindViteConfig);
715
- if (matches.length === 0) return null;
716
- return sortByPathDepth(matches)[0];
717
738
  }
718
- function isTailwindViteConfig(filePath) {
719
- if (!fileExists(filePath)) return false;
739
+ function parsePnpmWorkspacePackages(content) {
740
+ const patterns = [];
741
+ let inPackages = false;
742
+ for (const line of content.split(/\r?\n/)) if (/^packages\s*:/.test(line)) inPackages = true;
743
+ else if (/^[^\s#]/.test(line)) inPackages = false;
744
+ else if (inPackages) {
745
+ const item = line.match(/^\s*-\s*["']?([^"'#\s]+)["']?/);
746
+ if (item) patterns.push(item[1]);
747
+ }
748
+ return patterns;
749
+ }
750
+ function nestedRootIgnores(root, roots) {
751
+ return roots.filter((other) => other !== root && isInsideDir(root, other)).map((other) => `${node_path.relative(root, other)}/**`);
752
+ }
753
+ function isInsideDir(dir, filePath) {
754
+ const relative = node_path.relative(dir, filePath);
755
+ return !relative.startsWith("..") && !node_path.isAbsolute(relative);
756
+ }
757
+ async function pickConfig(root, candidates) {
758
+ const target = (kind, configPath) => ({
759
+ kind,
760
+ path: configPath,
761
+ root
762
+ });
763
+ const candidateSet = new Set(candidates);
764
+ const existing = (paths) => paths.map((p) => node_path.join(root, p)).filter((p) => candidateSet.has(p));
765
+ const byName = (names) => candidates.filter((c) => names.includes(node_path.basename(c)));
766
+ const preferredCss = existing(V4_CSS_FOLDERS.flatMap((folder) => V4_CSS_NAMES.map((name) => node_path.join(folder, name))));
767
+ const preferredCssMatch = await findFirstMatch(preferredCss, TAILWIND_V4_IMPORT_REGEX);
768
+ if (preferredCssMatch) return target("css", preferredCssMatch);
769
+ const rootV3 = existing(V3_CONFIG_PATHS)[0];
770
+ if (rootV3) return target("js", rootV3);
771
+ const cssMatch = await findFirstMatch(sortCssCandidates(root, candidates.filter((c) => isCssConfigFile(c) && !preferredCss.includes(c))), TAILWIND_V4_IMPORT_REGEX);
772
+ if (cssMatch) return target("css", cssMatch);
773
+ const nestedV3 = sortByPathDepth(byName(V3_CONFIG_PATHS))[0];
774
+ if (nestedV3) return target("js", nestedV3);
775
+ const viteConfigs = [...existing(VITE_CONFIG_PATHS), ...sortByPathDepth(byName(VITE_CONFIG_PATHS))];
776
+ const viteMatch = await findFirstMatch([...new Set(viteConfigs)], TAILWIND_VITE_PLUGIN_REGEX);
777
+ if (viteMatch) return target("vite", viteMatch);
778
+ }
779
+ async function findFirstMatch(paths, regex) {
780
+ const contents = await Promise.all(paths.map(readText));
781
+ return paths.find((_, index) => regex.test(contents[index]));
782
+ }
783
+ async function readText(filePath) {
720
784
  try {
721
- return TAILWIND_VITE_PLUGIN_REGEX.test(readFileSync(filePath));
785
+ return await (0, node_fs_promises.readFile)(filePath, "utf-8");
722
786
  } catch {
723
- return false;
787
+ return "";
724
788
  }
725
789
  }
726
790
  function sortByPathDepth(paths) {
@@ -758,9 +822,9 @@ function splitDepth(value) {
758
822
  //#endregion
759
823
  //#region src/state.ts
760
824
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
761
- function getTailwindVersion(cwd) {
825
+ function getTailwindVersion(paths) {
762
826
  try {
763
- const tailwindPackageJson = require$1.resolve("tailwindcss/package.json", { paths: [cwd] });
827
+ const tailwindPackageJson = require$1.resolve("tailwindcss/package.json", { paths });
764
828
  const { readFileSync } = require$1("node:fs");
765
829
  return JSON.parse(readFileSync(tailwindPackageJson, "utf-8")).version;
766
830
  } catch {
@@ -770,41 +834,52 @@ function getTailwindVersion(cwd) {
770
834
  function isV4Config(version) {
771
835
  return version?.startsWith("4.") ?? false;
772
836
  }
773
- function resolveTailwindPath(cwd, configDir) {
774
- const paths = configDir ? [configDir, cwd] : [cwd];
837
+ function resolveTailwindPath(paths) {
775
838
  try {
776
839
  return require$1.resolve("tailwindcss", { paths });
777
840
  } catch {
778
841
  throw new Error(`Could not find tailwindcss module in ${paths.join(" or ")}.\nInstall it with: npm install -D tailwindcss`);
779
842
  }
780
843
  }
781
- async function createState(cwd, configPath, verbose = false) {
782
- const resolvedConfigPath = await findTailwindConfigPath(cwd, configPath);
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.");
784
- const isCssConfig = isCssConfigFile(resolvedConfigPath);
785
- const tailwindPath = resolveTailwindPath(cwd, node_path.dirname(resolvedConfigPath));
786
- const tailwindcss = require$1(tailwindPath);
787
- const version = getTailwindVersion(cwd);
844
+ function loadResolveConfig(paths) {
845
+ try {
846
+ const module = require$1(require$1.resolve("tailwindcss/resolveConfig", { paths }));
847
+ return typeof module === "function" ? module : module.default;
848
+ } catch {
849
+ return;
850
+ }
851
+ }
852
+ const CONFIG_TYPE_LABELS = {
853
+ css: "CSS (v4)",
854
+ vite: "Vite (v4)",
855
+ js: "JavaScript"
856
+ };
857
+ async function createState(cwd, target, verbose = false) {
858
+ const isCssConfig = target.kind !== "js";
859
+ const resolvePaths = [node_path.dirname(target.path), cwd];
860
+ resolveTailwindPath(resolvePaths);
861
+ const version = getTailwindVersion(resolvePaths);
788
862
  const isV4 = isV4Config(version);
789
863
  if (verbose) {
790
864
  console.log(ansis.default.cyan.bold("→ Tailwind Configuration"));
791
865
  console.log(ansis.default.dim(` Version: ${version || "unknown"}`));
792
- console.log(ansis.default.dim(` Config type: ${isCssConfig ? "CSS (v4)" : "JavaScript"}`));
793
- console.log(ansis.default.dim(` Config path: ${resolvedConfigPath}`));
866
+ console.log(ansis.default.dim(` Config type: ${CONFIG_TYPE_LABELS[target.kind]}`));
867
+ console.log(ansis.default.dim(` Config path: ${target.path}`));
794
868
  }
795
869
  let config = {};
796
870
  let resolvedConfig = { separator: ":" };
797
871
  if (!isCssConfig) {
798
- config = await loadTailwindConfig(resolvedConfigPath);
872
+ config = await loadTailwindConfig(target.path);
799
873
  resolvedConfig = {
800
874
  ...config,
801
875
  separator: config.separator ?? ":"
802
876
  };
803
- if (tailwindcss.resolveConfig) resolvedConfig = tailwindcss.resolveConfig(config);
877
+ const resolveConfig = loadResolveConfig(resolvePaths);
878
+ if (resolveConfig) resolvedConfig = resolveConfig(config);
804
879
  }
805
880
  const state = {
806
881
  enabled: true,
807
- configPath: resolvedConfigPath,
882
+ configPath: target.path,
808
883
  config: resolvedConfig,
809
884
  version,
810
885
  v4: isV4 || void 0,
@@ -818,14 +893,15 @@ async function createState(cwd, configPath, verbose = false) {
818
893
  editor: createEditorState(cwd),
819
894
  features: ["diagnostics"]
820
895
  };
821
- if (isV4 || isCssConfig) await loadV4DesignSystem(state, cwd, resolvedConfigPath, verbose);
822
- else await loadV3ClassMetadata(state, cwd, verbose);
896
+ if (isV4 || isCssConfig) await loadV4DesignSystem(state, resolvePaths, target, verbose);
897
+ else await loadV3ClassMetadata(state, resolvePaths, verbose);
823
898
  return state;
824
899
  }
825
900
  //#endregion
826
901
  //#region src/linter.ts
827
902
  const SOURCE_FILE_PATTERN = "**/*.{js,jsx,ts,tsx,html,vue,svelte,astro,mdx}";
828
903
  const GLOB_PATTERN_REGEX = /[*?[\]{}]/;
904
+ const MAX_LISTED_PACKAGES = 10;
829
905
  async function validateDocument(state, filePath, content) {
830
906
  try {
831
907
  if (!state) throw new Error("State is not initialized");
@@ -833,7 +909,8 @@ async function validateDocument(state, filePath, content) {
833
909
  if (!state.v4 && !state.modules?.tailwindcss) throw new Error("Tailwind modules not initialized for Tailwind v3. This might indicate a configuration issue.");
834
910
  const languageId = getLanguageId(filePath);
835
911
  const uri = `file://${filePath}`;
836
- return await (0, _tailwindcss_language_service.doValidate)(state, vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content));
912
+ const document = vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content);
913
+ return await (0, _tailwindcss_language_service.doValidate)(state, document);
837
914
  } catch (error) {
838
915
  const message = error instanceof Error ? error.message : String(error);
839
916
  if (message.includes("Cannot read") || message.includes("undefined")) {
@@ -844,52 +921,43 @@ async function validateDocument(state, filePath, content) {
844
921
  throw new Error(`Failed to validate document ${filePath}: ${message}`);
845
922
  }
846
923
  }
847
- async function discoverFiles(cwd, patterns, configPath, autoDiscover) {
848
- if (autoDiscover) return discoverFilesFromConfig(cwd, configPath);
849
- return expandPatterns(cwd, patterns);
850
- }
851
924
  async function expandPatterns(cwd, patterns, extraIgnore = []) {
852
- const files = await (0, tinyglobby.glob)(patterns, {
925
+ return (0, tinyglobby.glob)(patterns, {
853
926
  cwd,
854
- absolute: false,
927
+ absolute: true,
855
928
  ignore: [...DEFAULT_IGNORE_PATTERNS, ...extraIgnore]
856
929
  });
857
- return [...new Set(files)].sort((a, b) => a.localeCompare(b));
858
- }
859
- async function discoverFilesFromConfig(cwd, configPath) {
860
- const configFilePath = await findTailwindConfigPath(cwd, configPath);
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;
863
- if (!isCssConfigFile(configFilePath)) {
864
- const config = await loadTailwindConfig(configFilePath);
930
+ }
931
+ async function discoverFilesFromConfig(target, configRoots) {
932
+ if (target.kind === "js") {
933
+ const config = await loadTailwindConfig(target.path);
865
934
  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}']");
866
935
  const patterns = extractContentPatterns(config);
867
936
  if (patterns.length === 0) throw new Error("No content patterns found in Tailwind config.\nEnsure your config has a content array with file patterns.");
868
- return expandPatterns(discoveryCwd, patterns);
937
+ return expandPatterns(!Array.isArray(config.content) && config.content.relative === true ? node_path.dirname(target.path) : target.root, patterns);
869
938
  }
870
- const configDir = node_path.dirname(configFilePath);
871
- const cssContent = fileExists(configFilePath) ? readFileSync(configFilePath) : SYNTHETIC_VITE_CSS_CONFIG_CONTENT;
872
- const includeConfigFile = (files) => {
873
- if (!fileExists(configFilePath)) return files;
874
- const relativeConfigPath = node_path.relative(discoveryCwd, configFilePath);
875
- return [.../* @__PURE__ */ new Set([relativeConfigPath, ...files])].sort((a, b) => a.localeCompare(b));
876
- };
877
- const resolveDiscoveredFiles = (files) => discoveryCwd === cwd ? files : files.map((file) => node_path.resolve(discoveryCwd, file)).sort((a, b) => a.localeCompare(b));
939
+ const { root } = target;
940
+ const configDir = node_path.dirname(target.path);
941
+ const cssContent = target.kind === "vite" ? SYNTHETIC_VITE_CSS_CONFIG_CONTENT : readFileSync(target.path);
878
942
  const { include, exclude } = extractSourcePatterns(cssContent);
879
943
  const importSource = extractImportSourceDirectives(cssContent);
880
- const resolveFromConfig = (pattern) => {
881
- const absolutePattern = node_path.resolve(configDir, pattern);
882
- return node_path.relative(discoveryCwd, absolutePattern);
883
- };
944
+ const resolveFromConfig = (pattern) => node_path.relative(root, node_path.resolve(configDir, pattern));
884
945
  const resolvedExclude = exclude.map(resolveFromConfig);
885
- const gitignorePatterns = readGitignorePatterns(discoveryCwd);
886
- const extraIgnore = [...resolvedExclude, ...gitignorePatterns];
946
+ const extraIgnore = [
947
+ ...resolvedExclude,
948
+ ...readGitignorePatterns(root),
949
+ ...nestedRootIgnores(root, configRoots)
950
+ ];
887
951
  const explicitSourcePatterns = include.map((source) => resolveFromConfig(normalizeSourcePattern(source)));
888
952
  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))));
953
+ if (!importSource.disableAutoSource) autoPatterns = importSource.roots.length > 0 ? importSource.roots.map((sourceRoot) => resolveFromConfig(normalizeSourcePattern(sourceRoot))) : [DEFAULT_FILE_PATTERN];
954
+ const [autoFiles, explicitFiles] = await Promise.all([autoPatterns.length > 0 ? expandPatterns(root, autoPatterns, extraIgnore) : [], explicitSourcePatterns.length > 0 ? expandPatterns(root, explicitSourcePatterns, resolvedExclude) : []]);
955
+ const configFile = target.kind === "css" ? [target.path] : [];
956
+ return [.../* @__PURE__ */ new Set([
957
+ ...configFile,
958
+ ...autoFiles,
959
+ ...explicitFiles
960
+ ])];
893
961
  }
894
962
  function normalizeSourcePattern(pattern) {
895
963
  if (GLOB_PATTERN_REGEX.test(pattern) || node_path.extname(pattern)) return pattern;
@@ -965,9 +1033,9 @@ async function processFile(state, cwd, filePath, fix) {
965
1033
  fixedCount
966
1034
  };
967
1035
  }
968
- async function initializeState(cwd, configPath, verbose = false) {
1036
+ async function initializeState(cwd, target, verbose = false) {
969
1037
  try {
970
- const state = await createState(cwd, configPath, verbose);
1038
+ const state = await createState(cwd, target, verbose);
971
1039
  if (verbose) console.log();
972
1040
  return state;
973
1041
  } catch (error) {
@@ -976,42 +1044,80 @@ async function initializeState(cwd, configPath, verbose = false) {
976
1044
  }
977
1045
  }
978
1046
  async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verbose = false, onProgress }) {
979
- const state = await initializeState(cwd, configPath, verbose);
980
- const discoveredFiles = await discoverFiles(cwd, patterns, configPath, autoDiscover);
981
- const files = uniqueFilesByResolvedPath(cwd, state.configPath && isCssConfigFile(state.configPath) && fileExists(state.configPath) ? [node_path.relative(cwd, state.configPath), ...discoveredFiles] : discoveredFiles);
1047
+ const targets = await resolveConfigTargets(cwd, configPath);
1048
+ if (verbose) logTargets(cwd, targets);
1049
+ const configRoots = targets.map((target) => target.root);
1050
+ const patternFiles = autoDiscover ? [] : await expandPatterns(cwd, patterns);
1051
+ const discoveredFilesByTarget = await Promise.all(targets.map((target) => autoDiscover ? discoverFilesFromConfig(target, configRoots) : patternFiles));
1052
+ const owners = /* @__PURE__ */ new Map();
1053
+ for (const [index, target] of targets.entries()) {
1054
+ const files = target.kind === "css" && !autoDiscover ? [target.path, ...discoveredFilesByTarget[index]] : discoveredFilesByTarget[index];
1055
+ for (const file of files) {
1056
+ const current = owners.get(file);
1057
+ if (!current || ownershipScore(target, file) > ownershipScore(current, file)) owners.set(file, target);
1058
+ }
1059
+ }
982
1060
  const skippedFiles = [];
983
- const lintableFiles = files.filter((file) => {
984
- if (getFileSize(node_path.isAbsolute(file) ? file : node_path.resolve(cwd, file)) > 524288) {
1061
+ const filesByTarget = /* @__PURE__ */ new Map();
1062
+ for (const [absolutePath, target] of owners) {
1063
+ const file = node_path.relative(cwd, absolutePath);
1064
+ if (getFileSize(absolutePath) > 524288) {
985
1065
  skippedFiles.push(file);
986
- return false;
1066
+ continue;
987
1067
  }
988
- return true;
989
- });
1068
+ const files = filesByTarget.get(target) ?? [];
1069
+ files.push(file);
1070
+ filesByTarget.set(target, files);
1071
+ }
1072
+ const totalFiles = owners.size - skippedFiles.length;
990
1073
  if (verbose) {
991
- console.log(ansis.default.cyan.bold(`→ Discovered ${lintableFiles.length} file${lintableFiles.length !== 1 ? "s" : ""} to lint`));
1074
+ console.log(ansis.default.cyan.bold(`→ Discovered ${totalFiles} file${totalFiles !== 1 ? "s" : ""} to lint`));
992
1075
  console.log();
993
1076
  }
994
- if (lintableFiles.length === 0) return {
995
- files: [],
996
- totalFilesProcessed: 0,
997
- skippedFiles
998
- };
1077
+ const results = [];
1078
+ let processedCount = 0;
1079
+ for (const target of targets) {
1080
+ const files = filesByTarget.get(target);
1081
+ if (!files) continue;
1082
+ const offset = processedCount;
1083
+ processedCount += files.length;
1084
+ const processed = await processFiles(await initializeState(cwd, target, verbose), cwd, files.sort((a, b) => a.localeCompare(b)), fix, onProgress && ((current, _total, file) => onProgress(offset + current, totalFiles, file)));
1085
+ results.push(...processed);
1086
+ }
999
1087
  return {
1000
- files: (await processFiles(state, cwd, lintableFiles, fix, onProgress)).filter((result) => result.diagnostics.length > 0 || result.fixed),
1001
- totalFilesProcessed: lintableFiles.length,
1002
- skippedFiles
1088
+ files: results.filter((result) => result.diagnostics.length > 0 || result.fixed).sort((a, b) => a.path.localeCompare(b.path)),
1089
+ totalFilesProcessed: totalFiles,
1090
+ skippedFiles: skippedFiles.sort((a, b) => a.localeCompare(b))
1003
1091
  };
1004
1092
  }
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);
1093
+ async function resolveConfigTargets(cwd, configPath) {
1094
+ if (configPath) {
1095
+ const absolutePath = node_path.resolve(cwd, configPath);
1096
+ if (!fileExists(absolutePath)) throw new Error(`Tailwind config file not found: ${absolutePath}`);
1097
+ return [toConfigTarget(absolutePath)];
1013
1098
  }
1014
- return unique.sort((a, b) => a.localeCompare(b));
1099
+ const { targets, packageRoots } = await findTailwindConfigs(cwd);
1100
+ if (targets.length === 0) throw new Error(noConfigMessage(cwd, packageRoots));
1101
+ return targets;
1102
+ }
1103
+ function noConfigMessage(cwd, packageRoots) {
1104
+ const packages = packageRoots.map((root) => node_path.relative(cwd, root)).filter(Boolean).sort((a, b) => a.localeCompare(b));
1105
+ const shown = packages.slice(0, MAX_LISTED_PACKAGES);
1106
+ const more = packages.length - shown.length;
1107
+ return `Could not find a Tailwind config in ${cwd}${packages.length > 0 ? ` or its packages:\n${shown.map((p) => ` • ${p}`).join("\n")}${more > 0 ? `\n …and ${more} more` : ""}` : ""}\nExpected one of:
1108
+ • Tailwind v4 (CSS): a CSS file with @import "tailwindcss", e.g. app.css or src/index.css
1109
+ • Tailwind v4 (Vite): vite.config.* with @tailwindcss/vite
1110
+ • Tailwind v3 (JS): tailwind.config.js, tailwind.config.ts
1111
+ Use --config to specify the path.`;
1112
+ }
1113
+ function logTargets(cwd, targets) {
1114
+ const display = (p) => node_path.relative(cwd, p) || ".";
1115
+ console.log(ansis.default.cyan.bold("→ Tailwind configs"));
1116
+ for (const target of targets) console.log(ansis.default.dim(` ${display(target.root)} → ${display(target.path)}`));
1117
+ console.log();
1118
+ }
1119
+ function ownershipScore(target, absolutePath) {
1120
+ return isInsideDir(target.root, absolutePath) ? target.root.length : -1;
1015
1121
  }
1016
1122
  //#endregion
1017
1123
  Object.defineProperty(exports, "DEFAULT_FILE_PATTERN", {
package/dist/linter.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_linter = require("./linter-BP0uKBfa.cjs");
2
+ const require_linter = require("./linter-gjoSGNMw.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,6 +383,6 @@ declare function extractImportSourceDirectives(cssContent: string): {
383
383
  roots: string[];
384
384
  disableAutoSource: boolean;
385
385
  };
386
- declare function lint({ cwd, patterns, configPath, autoDiscover, fix, verbose, onProgress }: LintOptions): Promise<LintResult>;
386
+ export declare function lint({ cwd, patterns, configPath, autoDiscover, fix, verbose, onProgress }: LintOptions): Promise<LintResult>;
387
387
  //#endregion
388
- export { type LintFileResult, type LintOptions, type LintResult, extractImportSourceDirectives, extractSourcePatterns, lint };
388
+ export { type LintFileResult, type LintOptions, type LintResult, extractImportSourceDirectives, extractSourcePatterns };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-lint",
3
- "version": "0.12.1",
3
+ "version": "0.13.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",
@@ -58,24 +58,25 @@
58
58
  "test:watch": "vitest"
59
59
  },
60
60
  "dependencies": {
61
- "@tailwindcss/language-service": "^0.14.29",
62
- "ansis": "^4.3.1",
61
+ "@tailwindcss/language-service": "^0.16.0",
62
+ "ansis": "^4.4.0",
63
63
  "commander": "^15.0.0",
64
- "postcss": "^8.5.19",
64
+ "postcss": "^8.5.28",
65
65
  "tinyglobby": "^0.2.17",
66
- "vscode-languageserver-textdocument": "^1.0.12"
66
+ "vscode-languageserver-textdocument": "^1.0.15"
67
67
  },
68
68
  "devDependencies": {
69
- "@types/node": "^26.1.1",
70
- "oxfmt": "^0.58.0",
71
- "oxlint": "^1.73.0",
72
- "tsdown": "^0.22.7",
69
+ "@types/node": "^26.6.4",
70
+ "oxfmt": "^0.71.0",
71
+ "oxlint": "^1.86.0",
72
+ "tsdown": "^0.23.0",
73
73
  "typescript": "^7.0.2",
74
- "vitest": "^4.1.10"
74
+ "vitest": "^5.0.3",
75
+ "vscode-languageserver": "8.1.0"
75
76
  },
76
77
  "engines": {
77
78
  "node": ">=22.0.0",
78
79
  "pnpm": ">=10.0.0"
79
80
  },
80
- "packageManager": "pnpm@11.13.0"
81
+ "packageManager": "pnpm@12.8.1"
81
82
  }