tailwind-lint 0.9.1 → 0.9.2

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,21 +1,19 @@
1
1
  #!/usr/bin/env node
2
- const require_state = require('./state-CeRvUDZb.cjs');
3
- const require_linter = require('./linter.cjs');
2
+ const require_linter = require("./linter-CEnSDkMA.cjs");
4
3
  let node_path = require("node:path");
5
- node_path = require_state.__toESM(node_path);
4
+ node_path = require_linter.__toESM(node_path);
6
5
  let ansis = require("ansis");
7
- ansis = require_state.__toESM(ansis);
6
+ ansis = require_linter.__toESM(ansis);
8
7
  let node_fs = require("node:fs");
9
- node_fs = require_state.__toESM(node_fs);
8
+ node_fs = require_linter.__toESM(node_fs);
10
9
  let commander = require("commander");
11
-
12
10
  //#region src/output.ts
13
11
  function countBySeverity(diagnostics) {
14
12
  let errors = 0;
15
13
  let warnings = 0;
16
14
  for (const diagnostic of diagnostics) {
17
- if (diagnostic.severity === require_state.SEVERITY.ERROR) errors++;
18
- if (diagnostic.severity === require_state.SEVERITY.WARNING) warnings++;
15
+ if (diagnostic.severity === require_linter.SEVERITY.ERROR) errors++;
16
+ if (diagnostic.severity === require_linter.SEVERITY.WARNING) warnings++;
19
17
  }
20
18
  return {
21
19
  errors,
@@ -23,8 +21,8 @@ function countBySeverity(diagnostics) {
23
21
  };
24
22
  }
25
23
  function toJsonSeverity(severity) {
26
- if (severity === require_state.SEVERITY.ERROR) return "error";
27
- if (severity === require_state.SEVERITY.WARNING) return "warning";
24
+ if (severity === require_linter.SEVERITY.ERROR) return "error";
25
+ if (severity === require_linter.SEVERITY.WARNING) return "warning";
28
26
  return "info";
29
27
  }
30
28
  function toJsonDiagnostic(diagnostic) {
@@ -76,7 +74,6 @@ function createJsonOutput({ files, totalFilesProcessed, cwd, configPath, autoDis
76
74
  files: mappedFiles
77
75
  };
78
76
  }
79
-
80
77
  //#endregion
81
78
  //#region src/cli.ts
82
79
  const MAX_FILENAME_DISPLAY_LENGTH = 50;
@@ -91,7 +88,7 @@ function resolveOptions(files, options) {
91
88
  const absoluteConfigPath = node_path.isAbsolute(options.config) ? options.config : node_path.resolve(process.cwd(), options.config);
92
89
  cwd = node_path.dirname(absoluteConfigPath);
93
90
  configPath = node_path.basename(absoluteConfigPath);
94
- patterns = [require_state.DEFAULT_FILE_PATTERN];
91
+ patterns = [require_linter.DEFAULT_FILE_PATTERN];
95
92
  }
96
93
  const autoDiscover = hasAutoFlag;
97
94
  return {
@@ -130,8 +127,8 @@ async function displayResults(files, fixMode) {
130
127
  for (const diagnostic of file.diagnostics) {
131
128
  const line = diagnostic.range.start.line + 1;
132
129
  const char = diagnostic.range.start.character + 1;
133
- const severity = diagnostic.severity === require_state.SEVERITY.ERROR ? "error" : "warning";
134
- const severityColor = diagnostic.severity === require_state.SEVERITY.ERROR ? ansis.default.red(severity) : ansis.default.yellow(severity);
130
+ const severity = diagnostic.severity === require_linter.SEVERITY.ERROR ? "error" : "warning";
131
+ const severityColor = diagnostic.severity === require_linter.SEVERITY.ERROR ? ansis.default.red(severity) : ansis.default.yellow(severity);
135
132
  const code = diagnostic.code ? ansis.default.dim(` (${diagnostic.code})`) : "";
136
133
  console.log(` ${ansis.default.dim(`${line}:${char}`)} ${severityColor} ${diagnostic.message}${code}`);
137
134
  }
@@ -158,9 +155,9 @@ const program = new commander.Command();
158
155
  const getVersion = () => {
159
156
  const packageJsonPath = node_path.join(__dirname, "../package.json");
160
157
  try {
161
- return JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8")).version || require_state.DEFAULT_VERSION;
158
+ return JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8")).version || "0.0.1";
162
159
  } catch {
163
- return require_state.DEFAULT_VERSION;
160
+ return require_linter.DEFAULT_VERSION;
164
161
  }
165
162
  };
166
163
  program.configureHelp({ formatHelp: (cmd, helper) => {
@@ -224,11 +221,11 @@ ${ansis.default.bold.cyan("Notes:")}
224
221
  if (isJsonOutput) return;
225
222
  if (process.stdout.isTTY && !resolved.verbose) {
226
223
  const displayFile = truncateFilename(file);
227
- process.stdout.write(`\r${ansis.default.cyan("→")} Linting files... ${ansis.default.dim(`(${current}/${total})`)} ${ansis.default.dim(displayFile)}${" ".repeat(require_state.TERMINAL_PADDING)}`);
224
+ process.stdout.write(`\r${ansis.default.cyan("→")} Linting files... ${ansis.default.dim(`(${current}/${total})`)} ${ansis.default.dim(displayFile)}${" ".repeat(10)}`);
228
225
  } else if (resolved.verbose) console.log(ansis.default.dim(` [${current}/${total}] Linting ${file}`));
229
226
  }
230
227
  });
231
- if (process.stdout.isTTY && !resolved.verbose && !isJsonOutput) process.stdout.write(`\r${" ".repeat(require_state.TERMINAL_WIDTH)}\r`);
228
+ if (process.stdout.isTTY && !resolved.verbose && !isJsonOutput) process.stdout.write(`\r${" ".repeat(80)}\r`);
232
229
  if (results.totalFilesProcessed === 0) {
233
230
  if (isJsonOutput) console.log(JSON.stringify(createJsonOutput({
234
231
  ...resolved,
@@ -256,7 +253,7 @@ ${ansis.default.bold.cyan("Notes:")}
256
253
  totalFilesProcessed: results.totalFilesProcessed
257
254
  })));
258
255
  else await displayResults(results.files, resolved.fix);
259
- const hasErrors = results.files.some((file) => file.diagnostics.some((d) => d.severity === require_state.SEVERITY.ERROR));
256
+ const hasErrors = results.files.some((file) => file.diagnostics.some((d) => d.severity === require_linter.SEVERITY.ERROR));
260
257
  process.exit(hasErrors ? 1 : 0);
261
258
  } catch (error) {
262
259
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -273,5 +270,4 @@ ${ansis.default.bold.cyan("Notes:")}
273
270
  }
274
271
  });
275
272
  program.parse();
276
-
277
- //#endregion
273
+ //#endregion
@@ -6,16 +6,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) {
13
- __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- }
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
19
15
  }
20
16
  return to;
21
17
  };
@@ -23,7 +19,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
19
  value: mod,
24
20
  enumerable: true
25
21
  }) : target, mod));
26
-
27
22
  //#endregion
28
23
  let node_path = require("node:path");
29
24
  node_path = __toESM(node_path);
@@ -37,7 +32,6 @@ let node_fs = require("node:fs");
37
32
  node_fs = __toESM(node_fs);
38
33
  let postcss = require("postcss");
39
34
  postcss = __toESM(postcss);
40
-
41
35
  //#region src/constants.ts
42
36
  const DEFAULT_IGNORE_PATTERNS = [
43
37
  "**/node_modules/**",
@@ -110,23 +104,14 @@ const LANGUAGE_MAP = {
110
104
  ".vue": "vue"
111
105
  };
112
106
  const DEFAULT_VERSION = "0.0.1";
113
- const DEFAULT_TAB_SIZE = 2;
114
- const DEFAULT_SEPARATOR = ":";
115
- const DEFAULT_ROOT_FONT_SIZE = 16;
116
- const CONCURRENT_FILES = 10;
117
107
  const SEVERITY = {
118
108
  ERROR: 1,
119
109
  WARNING: 2
120
110
  };
121
- const TERMINAL_WIDTH = 80;
122
- const TERMINAL_PADDING = 10;
123
- const MAX_FIX_ITERATIONS = 100;
124
- const QUICKFIX_ACTION_KIND = "quickfix";
125
111
  const TAILWIND_V4_IMPORT_REGEX = /@import\s+["']tailwindcss(?:["'\s/]|$)/;
126
112
  function getLanguageId(filePath) {
127
113
  return LANGUAGE_MAP[filePath.substring(filePath.lastIndexOf(".")).toLowerCase()] || "html";
128
114
  }
129
-
130
115
  //#endregion
131
116
  //#region src/code-actions.ts
132
117
  async function getQuickfixes(state, document, uri, diagnostics) {
@@ -150,7 +135,7 @@ async function getQuickfixes(state, document, uri, diagnostics) {
150
135
  }
151
136
  },
152
137
  context: { diagnostics: lspDiagnostics }
153
- }, document)).filter((action) => action.kind === QUICKFIX_ACTION_KIND || action.kind?.startsWith(`${QUICKFIX_ACTION_KIND}.`));
138
+ }, document)).filter((action) => action.kind === "quickfix" || action.kind?.startsWith(`quickfix.`));
154
139
  }
155
140
  function applyFirstQuickfix(action, uri, document, content) {
156
141
  if (!action.edit?.changes?.[uri]) return null;
@@ -179,7 +164,7 @@ async function applyCodeActions(state, filePath, content, diagnostics) {
179
164
  let currentDocument = vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content);
180
165
  let currentContent = content;
181
166
  let totalFixed = 0;
182
- for (let iteration = 0; iteration < MAX_FIX_ITERATIONS; iteration++) {
167
+ for (let iteration = 0; iteration < 100; iteration++) {
183
168
  const currentDiagnostics = await (0, _tailwindcss_language_service.doValidate)(state, currentDocument);
184
169
  if (currentDiagnostics.length === 0) break;
185
170
  const quickfixes = await getQuickfixes(state, currentDocument, uri, currentDiagnostics);
@@ -189,7 +174,7 @@ async function applyCodeActions(state, filePath, content, diagnostics) {
189
174
  currentContent = fixResult.content;
190
175
  currentDocument = vscode_languageserver_textdocument.TextDocument.create(uri, languageId, currentDocument.version + 1, currentContent);
191
176
  totalFixed++;
192
- if (iteration === MAX_FIX_ITERATIONS - 1) console.warn(`Warning: Reached maximum fix iterations (${MAX_FIX_ITERATIONS}) for ${filePath}. Some issues may remain unfixed.`);
177
+ if (iteration === 99) console.warn(`Warning: Reached maximum fix iterations (100) for ${filePath}. Some issues may remain unfixed.`);
193
178
  }
194
179
  return {
195
180
  content: currentContent,
@@ -209,7 +194,6 @@ async function applyCodeActions(state, filePath, content, diagnostics) {
209
194
  throw error;
210
195
  }
211
196
  }
212
-
213
197
  //#endregion
214
198
  //#region src/adapters/editor-state-adapter.ts
215
199
  function isDirectory(filePath) {
@@ -221,7 +205,7 @@ function isDirectory(filePath) {
221
205
  }
222
206
  function createEditorState(cwd) {
223
207
  const settings = {
224
- editor: { tabSize: DEFAULT_TAB_SIZE },
208
+ editor: { tabSize: 2 },
225
209
  tailwindCSS: {
226
210
  validate: true,
227
211
  inspectPort: null,
@@ -244,7 +228,7 @@ function createEditorState(cwd) {
244
228
  codeLens: false,
245
229
  suggestions: true,
246
230
  colorDecorators: true,
247
- rootFontSize: DEFAULT_ROOT_FONT_SIZE,
231
+ rootFontSize: 16,
248
232
  showPixelEquivalents: true,
249
233
  files: { exclude: [
250
234
  "**/.git/**",
@@ -292,7 +276,6 @@ function createEditorState(cwd) {
292
276
  }
293
277
  };
294
278
  }
295
-
296
279
  //#endregion
297
280
  //#region src/types.ts
298
281
  /**
@@ -305,7 +288,6 @@ var AdapterLoadError = class extends Error {
305
288
  this.name = "AdapterLoadError";
306
289
  }
307
290
  };
308
-
309
291
  //#endregion
310
292
  //#region src/adapters/v3-adapter.ts
311
293
  const require$4 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
@@ -372,7 +354,6 @@ function extractConfigMetadata(state) {
372
354
  }));
373
355
  if (config.corePlugins) state.corePlugins = Array.isArray(config.corePlugins) ? config.corePlugins : Object.keys(config.corePlugins);
374
356
  }
375
-
376
357
  //#endregion
377
358
  //#region src/utils/fs.ts
378
359
  function fileExists(filePath) {
@@ -404,7 +385,6 @@ function readGitignorePatterns(cwd) {
404
385
  return [];
405
386
  }
406
387
  }
407
-
408
388
  //#endregion
409
389
  //#region src/adapters/v4-adapter.ts
410
390
  const require$3 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
@@ -480,7 +460,6 @@ async function loadV4DesignSystem(state, cwd, configPath, verbose = false) {
480
460
  throw new Error(`Failed to load v4 design system: ${String(error)}`);
481
461
  }
482
462
  }
483
-
484
463
  //#endregion
485
464
  //#region src/utils/config.ts
486
465
  const require$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
@@ -572,7 +551,6 @@ function isPreferredCssFolder(relativePath) {
572
551
  function splitDepth(value) {
573
552
  return value.split(/[\\/]/).filter(Boolean).length;
574
553
  }
575
-
576
554
  //#endregion
577
555
  //#region src/state.ts
578
556
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href || __filename);
@@ -615,7 +593,7 @@ async function createState(cwd, configPath, verbose = false) {
615
593
  config = await loadTailwindConfig(resolvedConfigPath);
616
594
  resolvedConfig = {
617
595
  ...config,
618
- separator: config.separator ?? DEFAULT_SEPARATOR
596
+ separator: config.separator ?? ":"
619
597
  };
620
598
  if (tailwindcss.resolveConfig) resolvedConfig = tailwindcss.resolveConfig(config);
621
599
  }
@@ -625,7 +603,7 @@ async function createState(cwd, configPath, verbose = false) {
625
603
  config: resolvedConfig,
626
604
  version,
627
605
  v4: isV4 || void 0,
628
- separator: resolvedConfig.separator || DEFAULT_SEPARATOR,
606
+ separator: resolvedConfig.separator || ":",
629
607
  screens: [],
630
608
  variants: [],
631
609
  classNames: void 0,
@@ -639,113 +617,200 @@ async function createState(cwd, configPath, verbose = false) {
639
617
  else await loadV3ClassMetadata(state, cwd, verbose);
640
618
  return state;
641
619
  }
642
-
643
620
  //#endregion
644
- Object.defineProperty(exports, 'CONCURRENT_FILES', {
645
- enumerable: true,
646
- get: function () {
647
- return CONCURRENT_FILES;
648
- }
649
- });
650
- Object.defineProperty(exports, 'DEFAULT_FILE_PATTERN', {
651
- enumerable: true,
652
- get: function () {
653
- return DEFAULT_FILE_PATTERN;
654
- }
655
- });
656
- Object.defineProperty(exports, 'DEFAULT_IGNORE_PATTERNS', {
657
- enumerable: true,
658
- get: function () {
659
- return DEFAULT_IGNORE_PATTERNS;
660
- }
661
- });
662
- Object.defineProperty(exports, 'DEFAULT_VERSION', {
663
- enumerable: true,
664
- get: function () {
665
- return DEFAULT_VERSION;
666
- }
667
- });
668
- Object.defineProperty(exports, 'SEVERITY', {
669
- enumerable: true,
670
- get: function () {
671
- return SEVERITY;
672
- }
673
- });
674
- Object.defineProperty(exports, 'TERMINAL_PADDING', {
675
- enumerable: true,
676
- get: function () {
677
- return TERMINAL_PADDING;
678
- }
679
- });
680
- Object.defineProperty(exports, 'TERMINAL_WIDTH', {
681
- enumerable: true,
682
- get: function () {
683
- return TERMINAL_WIDTH;
684
- }
685
- });
686
- Object.defineProperty(exports, '__toESM', {
687
- enumerable: true,
688
- get: function () {
689
- return __toESM;
690
- }
691
- });
692
- Object.defineProperty(exports, 'applyCodeActions', {
693
- enumerable: true,
694
- get: function () {
695
- return applyCodeActions;
696
- }
697
- });
698
- Object.defineProperty(exports, 'createState', {
699
- enumerable: true,
700
- get: function () {
701
- return createState;
702
- }
703
- });
704
- Object.defineProperty(exports, 'fileExists', {
705
- enumerable: true,
706
- get: function () {
707
- return fileExists;
708
- }
621
+ //#region src/linter.ts
622
+ async function validateDocument(state, filePath, content) {
623
+ try {
624
+ if (!state) throw new Error("State is not initialized");
625
+ if (state.v4 && !state.designSystem) throw new Error("Design system not initialized for Tailwind v4. This might indicate a configuration issue.");
626
+ if (!state.v4 && !state.modules?.tailwindcss) throw new Error("Tailwind modules not initialized for Tailwind v3. This might indicate a configuration issue.");
627
+ const languageId = getLanguageId(filePath);
628
+ const uri = `file://${filePath}`;
629
+ return await (0, _tailwindcss_language_service.doValidate)(state, vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content));
630
+ } catch (error) {
631
+ const message = error instanceof Error ? error.message : String(error);
632
+ if (message.includes("Cannot read") || message.includes("undefined")) {
633
+ if (process.env.DEBUG) console.error(`Debug: Language service error for ${filePath}:`, error);
634
+ console.warn(`Warning: Language service crashed while validating ${filePath}. Skipping this file.`);
635
+ return [];
636
+ }
637
+ throw new Error(`Failed to validate document ${filePath}: ${message}`);
638
+ }
639
+ }
640
+ async function discoverFiles(cwd, patterns, configPath, autoDiscover) {
641
+ if (autoDiscover) return discoverFilesFromConfig(cwd, configPath);
642
+ return expandPatterns(cwd, patterns);
643
+ }
644
+ async function expandPatterns(cwd, patterns, extraIgnore = []) {
645
+ const files = await (0, tinyglobby.glob)(patterns, {
646
+ cwd,
647
+ absolute: false,
648
+ ignore: [...DEFAULT_IGNORE_PATTERNS, ...extraIgnore]
649
+ });
650
+ return [...new Set(files)].sort((a, b) => a.localeCompare(b));
651
+ }
652
+ async function discoverFilesFromConfig(cwd, configPath) {
653
+ const configFilePath = await findTailwindConfigPath(cwd, configPath);
654
+ if (!configFilePath) throw new Error("Could not find Tailwind config for auto-discovery.\nUse --config to specify the path, or provide file patterns directly.");
655
+ if (!isCssConfigFile(configFilePath)) {
656
+ const config = await loadTailwindConfig(configFilePath);
657
+ 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}']");
658
+ const patterns = extractContentPatterns(config);
659
+ if (patterns.length === 0) throw new Error("No content patterns found in Tailwind config.\nEnsure your config has a content array with file patterns.");
660
+ return expandPatterns(cwd, patterns);
661
+ }
662
+ const configDir = node_path.dirname(configFilePath);
663
+ const cssContent = readFileSync(configFilePath);
664
+ const { include, exclude } = extractSourcePatterns(cssContent);
665
+ const importSource = extractImportSourceDirectives(cssContent);
666
+ const resolveFromConfig = (pattern) => {
667
+ const absolutePattern = node_path.resolve(configDir, pattern);
668
+ return node_path.relative(cwd, absolutePattern);
669
+ };
670
+ const resolvedExclude = exclude.map(resolveFromConfig);
671
+ const gitignorePatterns = readGitignorePatterns(cwd);
672
+ const extraIgnore = [...resolvedExclude, ...gitignorePatterns];
673
+ if (include.length > 0) return expandPatterns(cwd, include.map(resolveFromConfig), extraIgnore);
674
+ if (importSource.roots.length > 0) return expandPatterns(cwd, importSource.roots.map((root) => resolveFromConfig(node_path.join(root, "**/*.{js,jsx,ts,tsx,html,vue,svelte,astro,mdx}"))), extraIgnore);
675
+ if (importSource.disableAutoSource) return [];
676
+ return expandPatterns(cwd, [DEFAULT_FILE_PATTERN], extraIgnore);
677
+ }
678
+ function extractContentPatterns(config) {
679
+ if (!config.content) return [];
680
+ return (Array.isArray(config.content) ? config.content : config.content.files || []).filter((p) => typeof p === "string");
681
+ }
682
+ function extractSourcePatterns(cssContent) {
683
+ const include = [];
684
+ const exclude = [];
685
+ for (const match of cssContent.matchAll(/@source\s+(not\s+)?(?:inline\(|["']([^"']+)["'])/g)) {
686
+ const isNot = !!match[1];
687
+ const filePath = match[2];
688
+ if (!filePath) continue;
689
+ if (isNot) exclude.push(filePath);
690
+ else include.push(filePath);
691
+ }
692
+ return {
693
+ include,
694
+ exclude
695
+ };
696
+ }
697
+ function extractImportSourceDirectives(cssContent) {
698
+ const roots = [];
699
+ let disableAutoSource = false;
700
+ for (const match of cssContent.matchAll(/@import\s+["']tailwindcss(?:[^;]*?)\ssource\(\s*(none|["'][^"']+["'])\s*\)/g)) {
701
+ const raw = match[1];
702
+ if (!raw) continue;
703
+ if (raw === "none") {
704
+ disableAutoSource = true;
705
+ continue;
706
+ }
707
+ const sourceRoot = raw.slice(1, -1).trim();
708
+ if (sourceRoot.length > 0) roots.push(sourceRoot);
709
+ }
710
+ return {
711
+ roots: [...new Set(roots)],
712
+ disableAutoSource
713
+ };
714
+ }
715
+ async function processFiles(state, cwd, files, fix, onProgress) {
716
+ const results = [];
717
+ for (let i = 0; i < files.length; i += 10) {
718
+ const batch = files.slice(i, i + 10);
719
+ const batchResults = await Promise.all(batch.map(async (file, batchIndex) => {
720
+ if (onProgress) onProgress(i + batchIndex + 1, files.length, file);
721
+ return processFile(state, cwd, file, fix);
722
+ }));
723
+ results.push(...batchResults.filter((r) => r !== null));
724
+ }
725
+ return results;
726
+ }
727
+ async function processFile(state, cwd, filePath, fix) {
728
+ const absolutePath = node_path.isAbsolute(filePath) ? filePath : node_path.resolve(cwd, filePath);
729
+ if (!fileExists(absolutePath)) return null;
730
+ const content = readFileSync(absolutePath);
731
+ let diagnostics = await validateDocument(state, absolutePath, content);
732
+ let fixedCount = 0;
733
+ if (fix && diagnostics.length > 0) {
734
+ const fixResult = await applyCodeActions(state, absolutePath, content, diagnostics);
735
+ if (fixResult.changed) {
736
+ writeFileSync(absolutePath, fixResult.content);
737
+ fixedCount = fixResult.fixedCount;
738
+ diagnostics = await validateDocument(state, absolutePath, fixResult.content);
739
+ }
740
+ }
741
+ return {
742
+ path: node_path.relative(cwd, absolutePath),
743
+ diagnostics,
744
+ fixed: fixedCount > 0,
745
+ fixedCount
746
+ };
747
+ }
748
+ async function initializeState(cwd, configPath, verbose = false) {
749
+ try {
750
+ const state = await createState(cwd, configPath, verbose);
751
+ if (verbose) console.log();
752
+ return state;
753
+ } catch (error) {
754
+ const message = error instanceof Error ? error.message : String(error);
755
+ throw new Error(`Failed to initialize Tailwind state: ${message}`);
756
+ }
757
+ }
758
+ async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verbose = false, onProgress }) {
759
+ const state = await initializeState(cwd, configPath, verbose);
760
+ const files = await discoverFiles(cwd, patterns, configPath, autoDiscover);
761
+ if (verbose) {
762
+ console.log(ansis.default.cyan.bold(`→ Discovered ${files.length} file${files.length !== 1 ? "s" : ""} to lint`));
763
+ console.log();
764
+ }
765
+ if (files.length === 0) return {
766
+ files: [],
767
+ totalFilesProcessed: 0
768
+ };
769
+ return {
770
+ files: (await processFiles(state, cwd, files, fix, onProgress)).filter((result) => result.diagnostics.length > 0 || result.fixed),
771
+ totalFilesProcessed: files.length
772
+ };
773
+ }
774
+ //#endregion
775
+ Object.defineProperty(exports, "DEFAULT_FILE_PATTERN", {
776
+ enumerable: true,
777
+ get: function() {
778
+ return DEFAULT_FILE_PATTERN;
779
+ }
709
780
  });
710
- Object.defineProperty(exports, 'findTailwindConfigPath', {
711
- enumerable: true,
712
- get: function () {
713
- return findTailwindConfigPath;
714
- }
781
+ Object.defineProperty(exports, "DEFAULT_VERSION", {
782
+ enumerable: true,
783
+ get: function() {
784
+ return DEFAULT_VERSION;
785
+ }
715
786
  });
716
- Object.defineProperty(exports, 'getLanguageId', {
717
- enumerable: true,
718
- get: function () {
719
- return getLanguageId;
720
- }
787
+ Object.defineProperty(exports, "SEVERITY", {
788
+ enumerable: true,
789
+ get: function() {
790
+ return SEVERITY;
791
+ }
721
792
  });
722
- Object.defineProperty(exports, 'isCssConfigFile', {
723
- enumerable: true,
724
- get: function () {
725
- return isCssConfigFile;
726
- }
793
+ Object.defineProperty(exports, "__toESM", {
794
+ enumerable: true,
795
+ get: function() {
796
+ return __toESM;
797
+ }
727
798
  });
728
- Object.defineProperty(exports, 'loadTailwindConfig', {
729
- enumerable: true,
730
- get: function () {
731
- return loadTailwindConfig;
732
- }
799
+ Object.defineProperty(exports, "extractImportSourceDirectives", {
800
+ enumerable: true,
801
+ get: function() {
802
+ return extractImportSourceDirectives;
803
+ }
733
804
  });
734
- Object.defineProperty(exports, 'readFileSync', {
735
- enumerable: true,
736
- get: function () {
737
- return readFileSync;
738
- }
805
+ Object.defineProperty(exports, "extractSourcePatterns", {
806
+ enumerable: true,
807
+ get: function() {
808
+ return extractSourcePatterns;
809
+ }
739
810
  });
740
- Object.defineProperty(exports, 'readGitignorePatterns', {
741
- enumerable: true,
742
- get: function () {
743
- return readGitignorePatterns;
744
- }
811
+ Object.defineProperty(exports, "lint", {
812
+ enumerable: true,
813
+ get: function() {
814
+ return lint;
815
+ }
745
816
  });
746
- Object.defineProperty(exports, 'writeFileSync', {
747
- enumerable: true,
748
- get: function () {
749
- return writeFileSync;
750
- }
751
- });
package/dist/linter.cjs CHANGED
@@ -1,168 +1,5 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_state = require('./state-CeRvUDZb.cjs');
3
- let node_path = require("node:path");
4
- node_path = require_state.__toESM(node_path);
5
- let _tailwindcss_language_service = require("@tailwindcss/language-service");
6
- let ansis = require("ansis");
7
- ansis = require_state.__toESM(ansis);
8
- let tinyglobby = require("tinyglobby");
9
- let vscode_languageserver_textdocument = require("vscode-languageserver-textdocument");
10
-
11
- //#region src/linter.ts
12
- async function validateDocument(state, filePath, content) {
13
- try {
14
- if (!state) throw new Error("State is not initialized");
15
- if (state.v4 && !state.designSystem) throw new Error("Design system not initialized for Tailwind v4. This might indicate a configuration issue.");
16
- if (!state.v4 && !state.modules?.tailwindcss) throw new Error("Tailwind modules not initialized for Tailwind v3. This might indicate a configuration issue.");
17
- const languageId = require_state.getLanguageId(filePath);
18
- const uri = `file://${filePath}`;
19
- return await (0, _tailwindcss_language_service.doValidate)(state, vscode_languageserver_textdocument.TextDocument.create(uri, languageId, 1, content));
20
- } catch (error) {
21
- const message = error instanceof Error ? error.message : String(error);
22
- if (message.includes("Cannot read") || message.includes("undefined")) {
23
- if (process.env.DEBUG) console.error(`Debug: Language service error for ${filePath}:`, error);
24
- console.warn(`Warning: Language service crashed while validating ${filePath}. Skipping this file.`);
25
- return [];
26
- }
27
- throw new Error(`Failed to validate document ${filePath}: ${message}`);
28
- }
29
- }
30
- async function discoverFiles(cwd, patterns, configPath, autoDiscover) {
31
- if (autoDiscover) return discoverFilesFromConfig(cwd, configPath);
32
- return expandPatterns(cwd, patterns);
33
- }
34
- async function expandPatterns(cwd, patterns, extraIgnore = []) {
35
- const files = await (0, tinyglobby.glob)(patterns, {
36
- cwd,
37
- absolute: false,
38
- ignore: [...require_state.DEFAULT_IGNORE_PATTERNS, ...extraIgnore]
39
- });
40
- return [...new Set(files)].sort((a, b) => a.localeCompare(b));
41
- }
42
- async function discoverFilesFromConfig(cwd, configPath) {
43
- const configFilePath = await require_state.findTailwindConfigPath(cwd, configPath);
44
- if (!configFilePath) throw new Error("Could not find Tailwind config for auto-discovery.\nUse --config to specify the path, or provide file patterns directly.");
45
- if (!require_state.isCssConfigFile(configFilePath)) {
46
- const config = await require_state.loadTailwindConfig(configFilePath);
47
- 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}']");
48
- const patterns = extractContentPatterns(config);
49
- if (patterns.length === 0) throw new Error("No content patterns found in Tailwind config.\nEnsure your config has a content array with file patterns.");
50
- return expandPatterns(cwd, patterns);
51
- }
52
- const configDir = node_path.dirname(configFilePath);
53
- const cssContent = require_state.readFileSync(configFilePath);
54
- const { include, exclude } = extractSourcePatterns(cssContent);
55
- const importSource = extractImportSourceDirectives(cssContent);
56
- const resolveFromConfig = (pattern) => {
57
- const absolutePattern = node_path.resolve(configDir, pattern);
58
- return node_path.relative(cwd, absolutePattern);
59
- };
60
- const resolvedExclude = exclude.map(resolveFromConfig);
61
- const gitignorePatterns = require_state.readGitignorePatterns(cwd);
62
- const extraIgnore = [...resolvedExclude, ...gitignorePatterns];
63
- if (include.length > 0) return expandPatterns(cwd, include.map(resolveFromConfig), extraIgnore);
64
- if (importSource.roots.length > 0) return expandPatterns(cwd, importSource.roots.map((root) => resolveFromConfig(node_path.join(root, "**/*.{js,jsx,ts,tsx,html,vue,svelte,astro,mdx}"))), extraIgnore);
65
- if (importSource.disableAutoSource) return [];
66
- return expandPatterns(cwd, [require_state.DEFAULT_FILE_PATTERN], extraIgnore);
67
- }
68
- function extractContentPatterns(config) {
69
- if (!config.content) return [];
70
- return (Array.isArray(config.content) ? config.content : config.content.files || []).filter((p) => typeof p === "string");
71
- }
72
- function extractSourcePatterns(cssContent) {
73
- const include = [];
74
- const exclude = [];
75
- for (const match of cssContent.matchAll(/@source\s+(not\s+)?(?:inline\(|["']([^"']+)["'])/g)) {
76
- const isNot = !!match[1];
77
- const filePath = match[2];
78
- if (!filePath) continue;
79
- if (isNot) exclude.push(filePath);
80
- else include.push(filePath);
81
- }
82
- return {
83
- include,
84
- exclude
85
- };
86
- }
87
- function extractImportSourceDirectives(cssContent) {
88
- const roots = [];
89
- let disableAutoSource = false;
90
- for (const match of cssContent.matchAll(/@import\s+["']tailwindcss(?:[^;]*?)\ssource\(\s*(none|["'][^"']+["'])\s*\)/g)) {
91
- const raw = match[1];
92
- if (!raw) continue;
93
- if (raw === "none") {
94
- disableAutoSource = true;
95
- continue;
96
- }
97
- const sourceRoot = raw.slice(1, -1).trim();
98
- if (sourceRoot.length > 0) roots.push(sourceRoot);
99
- }
100
- return {
101
- roots: [...new Set(roots)],
102
- disableAutoSource
103
- };
104
- }
105
- async function processFiles(state, cwd, files, fix, onProgress) {
106
- const results = [];
107
- for (let i = 0; i < files.length; i += require_state.CONCURRENT_FILES) {
108
- const batch = files.slice(i, i + require_state.CONCURRENT_FILES);
109
- const batchResults = await Promise.all(batch.map(async (file, batchIndex) => {
110
- if (onProgress) onProgress(i + batchIndex + 1, files.length, file);
111
- return processFile(state, cwd, file, fix);
112
- }));
113
- results.push(...batchResults.filter((r) => r !== null));
114
- }
115
- return results;
116
- }
117
- async function processFile(state, cwd, filePath, fix) {
118
- const absolutePath = node_path.isAbsolute(filePath) ? filePath : node_path.resolve(cwd, filePath);
119
- if (!require_state.fileExists(absolutePath)) return null;
120
- const content = require_state.readFileSync(absolutePath);
121
- let diagnostics = await validateDocument(state, absolutePath, content);
122
- let fixedCount = 0;
123
- if (fix && diagnostics.length > 0) {
124
- const fixResult = await require_state.applyCodeActions(state, absolutePath, content, diagnostics);
125
- if (fixResult.changed) {
126
- require_state.writeFileSync(absolutePath, fixResult.content);
127
- fixedCount = fixResult.fixedCount;
128
- diagnostics = await validateDocument(state, absolutePath, fixResult.content);
129
- }
130
- }
131
- return {
132
- path: node_path.relative(cwd, absolutePath),
133
- diagnostics,
134
- fixed: fixedCount > 0,
135
- fixedCount
136
- };
137
- }
138
- async function initializeState(cwd, configPath, verbose = false) {
139
- try {
140
- const state = await require_state.createState(cwd, configPath, verbose);
141
- if (verbose) console.log();
142
- return state;
143
- } catch (error) {
144
- const message = error instanceof Error ? error.message : String(error);
145
- throw new Error(`Failed to initialize Tailwind state: ${message}`);
146
- }
147
- }
148
- async function lint({ cwd, patterns, configPath, autoDiscover, fix = false, verbose = false, onProgress }) {
149
- const state = await initializeState(cwd, configPath, verbose);
150
- const files = await discoverFiles(cwd, patterns, configPath, autoDiscover);
151
- if (verbose) {
152
- console.log(ansis.default.cyan.bold(`→ Discovered ${files.length} file${files.length !== 1 ? "s" : ""} to lint`));
153
- console.log();
154
- }
155
- if (files.length === 0) return {
156
- files: [],
157
- totalFilesProcessed: 0
158
- };
159
- return {
160
- files: (await processFiles(state, cwd, files, fix, onProgress)).filter((result) => result.diagnostics.length > 0 || result.fixed),
161
- totalFilesProcessed: files.length
162
- };
163
- }
164
-
165
- //#endregion
166
- exports.extractImportSourceDirectives = extractImportSourceDirectives;
167
- exports.extractSourcePatterns = extractSourcePatterns;
168
- exports.lint = lint;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_linter = require("./linter-CEnSDkMA.cjs");
3
+ exports.extractImportSourceDirectives = require_linter.extractImportSourceDirectives;
4
+ exports.extractSourcePatterns = require_linter.extractSourcePatterns;
5
+ exports.lint = require_linter.lint;
package/dist/linter.d.cts CHANGED
@@ -1,5 +1,357 @@
1
- import { Diagnostic } from "vscode-languageserver";
2
-
1
+ //#region node_modules/.pnpm/vscode-languageserver-types@3.17.3/node_modules/vscode-languageserver-types/lib/umd/main.d.ts
2
+ /**
3
+ * A tagging type for string properties that are actually document URIs.
4
+ */
5
+ declare type DocumentUri = string;
6
+ declare namespace DocumentUri {
7
+ function is(value: any): value is DocumentUri;
8
+ }
9
+ /**
10
+ * A tagging type for string properties that are actually URIs
11
+ *
12
+ * @since 3.16.0
13
+ */
14
+ declare type URI = string;
15
+ declare namespace URI {
16
+ function is(value: any): value is URI;
17
+ }
18
+ /**
19
+ * Defines an integer in the range of -2^31 to 2^31 - 1.
20
+ */
21
+ declare type integer = number;
22
+ declare namespace integer {
23
+ const MIN_VALUE = -2147483648;
24
+ const MAX_VALUE = 2147483647;
25
+ function is(value: any): value is integer;
26
+ }
27
+ /**
28
+ * Defines an unsigned integer in the range of 0 to 2^31 - 1.
29
+ */
30
+ declare type uinteger = number;
31
+ declare namespace uinteger {
32
+ const MIN_VALUE = 0;
33
+ const MAX_VALUE = 2147483647;
34
+ function is(value: any): value is uinteger;
35
+ }
36
+ /**
37
+ * The LSP any type.
38
+ *
39
+ * In the current implementation we map LSPAny to any. This is due to the fact
40
+ * that the TypeScript compilers can't infer string access signatures for
41
+ * interface correctly (it can though for types). See the following issue for
42
+ * details: https://github.com/microsoft/TypeScript/issues/15300.
43
+ *
44
+ * When the issue is addressed LSPAny can be defined as follows:
45
+ *
46
+ * ```ts
47
+ * export type LSPAny = LSPObject | LSPArray | string | integer | uinteger | decimal | boolean | null | undefined;
48
+ * export type LSPObject = { [key: string]: LSPAny };
49
+ * export type LSPArray = LSPAny[];
50
+ * ```
51
+ *
52
+ * Please note that strictly speaking a property with the value `undefined`
53
+ * can't be converted into JSON preserving the property name. However for
54
+ * convenience it is allowed and assumed that all these properties are
55
+ * optional as well.
56
+ *
57
+ * @since 3.17.0
58
+ */
59
+ declare type LSPAny = any;
60
+ /**
61
+ * Position in a text document expressed as zero-based line and character
62
+ * offset. Prior to 3.17 the offsets were always based on a UTF-16 string
63
+ * representation. So a string of the form `a𐐀b` the character offset of the
64
+ * character `a` is 0, the character offset of `𐐀` is 1 and the character
65
+ * offset of b is 3 since `𐐀` is represented using two code units in UTF-16.
66
+ * Since 3.17 clients and servers can agree on a different string encoding
67
+ * representation (e.g. UTF-8). The client announces it's supported encoding
68
+ * via the client capability [`general.positionEncodings`](#clientCapabilities).
69
+ * The value is an array of position encodings the client supports, with
70
+ * decreasing preference (e.g. the encoding at index `0` is the most preferred
71
+ * one). To stay backwards compatible the only mandatory encoding is UTF-16
72
+ * represented via the string `utf-16`. The server can pick one of the
73
+ * encodings offered by the client and signals that encoding back to the
74
+ * client via the initialize result's property
75
+ * [`capabilities.positionEncoding`](#serverCapabilities). If the string value
76
+ * `utf-16` is missing from the client's capability `general.positionEncodings`
77
+ * servers can safely assume that the client supports UTF-16. If the server
78
+ * omits the position encoding in its initialize result the encoding defaults
79
+ * to the string value `utf-16`. Implementation considerations: since the
80
+ * conversion from one encoding into another requires the content of the
81
+ * file / line the conversion is best done where the file is read which is
82
+ * usually on the server side.
83
+ *
84
+ * Positions are line end character agnostic. So you can not specify a position
85
+ * that denotes `\r|\n` or `\n|` where `|` represents the character offset.
86
+ *
87
+ * @since 3.17.0 - support for negotiated position encoding.
88
+ */
89
+ interface Position {
90
+ /**
91
+ * Line position in a document (zero-based).
92
+ *
93
+ * If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document.
94
+ * If a line number is negative, it defaults to 0.
95
+ */
96
+ line: uinteger;
97
+ /**
98
+ * Character offset on a line in a document (zero-based).
99
+ *
100
+ * The meaning of this offset is determined by the negotiated
101
+ * `PositionEncodingKind`.
102
+ *
103
+ * If the character value is greater than the line length it defaults back to the
104
+ * line length.
105
+ */
106
+ character: uinteger;
107
+ }
108
+ /**
109
+ * The Position namespace provides helper functions to work with
110
+ * {@link Position} literals.
111
+ */
112
+ declare namespace Position {
113
+ /**
114
+ * Creates a new Position literal from the given line and character.
115
+ * @param line The position's line.
116
+ * @param character The position's character.
117
+ */
118
+ function create(line: uinteger, character: uinteger): Position;
119
+ /**
120
+ * Checks whether the given literal conforms to the {@link Position} interface.
121
+ */
122
+ function is(value: any): value is Position;
123
+ }
124
+ /**
125
+ * A range in a text document expressed as (zero-based) start and end positions.
126
+ *
127
+ * If you want to specify a range that contains a line including the line ending
128
+ * character(s) then use an end position denoting the start of the next line.
129
+ * For example:
130
+ * ```ts
131
+ * {
132
+ * start: { line: 5, character: 23 }
133
+ * end : { line 6, character : 0 }
134
+ * }
135
+ * ```
136
+ */
137
+ interface Range {
138
+ /**
139
+ * The range's start position.
140
+ */
141
+ start: Position;
142
+ /**
143
+ * The range's end position.
144
+ */
145
+ end: Position;
146
+ }
147
+ /**
148
+ * The Range namespace provides helper functions to work with
149
+ * {@link Range} literals.
150
+ */
151
+ declare namespace Range {
152
+ /**
153
+ * Create a new Range literal.
154
+ * @param start The range's start position.
155
+ * @param end The range's end position.
156
+ */
157
+ function create(start: Position, end: Position): Range;
158
+ /**
159
+ * Create a new Range literal.
160
+ * @param startLine The start line number.
161
+ * @param startCharacter The start character.
162
+ * @param endLine The end line number.
163
+ * @param endCharacter The end character.
164
+ */
165
+ function create(startLine: uinteger, startCharacter: uinteger, endLine: uinteger, endCharacter: uinteger): Range;
166
+ /**
167
+ * Checks whether the given literal conforms to the {@link Range} interface.
168
+ */
169
+ function is(value: any): value is Range;
170
+ }
171
+ /**
172
+ * Represents a location inside a resource, such as a line
173
+ * inside a text file.
174
+ */
175
+ interface Location {
176
+ uri: DocumentUri;
177
+ range: Range;
178
+ }
179
+ /**
180
+ * The Location namespace provides helper functions to work with
181
+ * {@link Location} literals.
182
+ */
183
+ declare namespace Location {
184
+ /**
185
+ * Creates a Location literal.
186
+ * @param uri The location's uri.
187
+ * @param range The location's range.
188
+ */
189
+ function create(uri: DocumentUri, range: Range): Location;
190
+ /**
191
+ * Checks whether the given literal conforms to the {@link Location} interface.
192
+ */
193
+ function is(value: any): value is Location;
194
+ }
195
+ /**
196
+ * Represents a related message and source code location for a diagnostic. This should be
197
+ * used to point to code locations that cause or related to a diagnostics, e.g when duplicating
198
+ * a symbol in a scope.
199
+ */
200
+ interface DiagnosticRelatedInformation {
201
+ /**
202
+ * The location of this related diagnostic information.
203
+ */
204
+ location: Location;
205
+ /**
206
+ * The message of this related diagnostic information.
207
+ */
208
+ message: string;
209
+ }
210
+ /**
211
+ * The DiagnosticRelatedInformation namespace provides helper functions to work with
212
+ * {@link DiagnosticRelatedInformation} literals.
213
+ */
214
+ declare namespace DiagnosticRelatedInformation {
215
+ /**
216
+ * Creates a new DiagnosticRelatedInformation literal.
217
+ */
218
+ function create(location: Location, message: string): DiagnosticRelatedInformation;
219
+ /**
220
+ * Checks whether the given literal conforms to the {@link DiagnosticRelatedInformation} interface.
221
+ */
222
+ function is(value: any): value is DiagnosticRelatedInformation;
223
+ }
224
+ /**
225
+ * The diagnostic's severity.
226
+ */
227
+ declare namespace DiagnosticSeverity {
228
+ /**
229
+ * Reports an error.
230
+ */
231
+ const Error: 1;
232
+ /**
233
+ * Reports a warning.
234
+ */
235
+ const Warning: 2;
236
+ /**
237
+ * Reports an information.
238
+ */
239
+ const Information: 3;
240
+ /**
241
+ * Reports a hint.
242
+ */
243
+ const Hint: 4;
244
+ }
245
+ declare type DiagnosticSeverity = 1 | 2 | 3 | 4;
246
+ /**
247
+ * The diagnostic tags.
248
+ *
249
+ * @since 3.15.0
250
+ */
251
+ declare namespace DiagnosticTag {
252
+ /**
253
+ * Unused or unnecessary code.
254
+ *
255
+ * Clients are allowed to render diagnostics with this tag faded out instead of having
256
+ * an error squiggle.
257
+ */
258
+ const Unnecessary: 1;
259
+ /**
260
+ * Deprecated or obsolete code.
261
+ *
262
+ * Clients are allowed to rendered diagnostics with this tag strike through.
263
+ */
264
+ const Deprecated: 2;
265
+ }
266
+ declare type DiagnosticTag = 1 | 2;
267
+ /**
268
+ * Structure to capture a description for an error code.
269
+ *
270
+ * @since 3.16.0
271
+ */
272
+ interface CodeDescription {
273
+ /**
274
+ * An URI to open with more information about the diagnostic error.
275
+ */
276
+ href: URI;
277
+ }
278
+ /**
279
+ * The CodeDescription namespace provides functions to deal with descriptions for diagnostic codes.
280
+ *
281
+ * @since 3.16.0
282
+ */
283
+ declare namespace CodeDescription {
284
+ function is(value: any): value is CodeDescription;
285
+ }
286
+ /**
287
+ * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects
288
+ * are only valid in the scope of a resource.
289
+ */
290
+ interface Diagnostic {
291
+ /**
292
+ * The range at which the message applies
293
+ */
294
+ range: Range;
295
+ /**
296
+ * The diagnostic's severity. Can be omitted. If omitted it is up to the
297
+ * client to interpret diagnostics as error, warning, info or hint.
298
+ */
299
+ severity?: DiagnosticSeverity;
300
+ /**
301
+ * The diagnostic's code, which usually appear in the user interface.
302
+ */
303
+ code?: integer | string;
304
+ /**
305
+ * An optional property to describe the error code.
306
+ * Requires the code field (above) to be present/not null.
307
+ *
308
+ * @since 3.16.0
309
+ */
310
+ codeDescription?: CodeDescription;
311
+ /**
312
+ * A human-readable string describing the source of this
313
+ * diagnostic, e.g. 'typescript' or 'super lint'. It usually
314
+ * appears in the user interface.
315
+ */
316
+ source?: string;
317
+ /**
318
+ * The diagnostic's message. It usually appears in the user interface
319
+ */
320
+ message: string;
321
+ /**
322
+ * Additional metadata about the diagnostic.
323
+ *
324
+ * @since 3.15.0
325
+ */
326
+ tags?: DiagnosticTag[];
327
+ /**
328
+ * An array of related diagnostic information, e.g. when symbol-names within
329
+ * a scope collide all definitions can be marked via this property.
330
+ */
331
+ relatedInformation?: DiagnosticRelatedInformation[];
332
+ /**
333
+ * A data entry field that is preserved between a `textDocument/publishDiagnostics`
334
+ * notification and `textDocument/codeAction` request.
335
+ *
336
+ * @since 3.16.0
337
+ */
338
+ data?: LSPAny;
339
+ }
340
+ /**
341
+ * The Diagnostic namespace provides helper functions to work with
342
+ * {@link Diagnostic} literals.
343
+ */
344
+ declare namespace Diagnostic {
345
+ /**
346
+ * Creates a new Diagnostic literal.
347
+ */
348
+ function create(range: Range, message: string, severity?: DiagnosticSeverity, code?: integer | string, source?: string, relatedInformation?: DiagnosticRelatedInformation[]): Diagnostic;
349
+ /**
350
+ * Checks whether the given literal conforms to the {@link Diagnostic} interface.
351
+ */
352
+ function is(value: any): value is Diagnostic;
353
+ }
354
+ //#endregion
3
355
  //#region src/types.d.ts
4
356
  interface LintFileResult {
5
357
  path: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-lint",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
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,16 +66,16 @@
66
66
  "vscode-languageserver-textdocument": "^1.0.12"
67
67
  },
68
68
  "devDependencies": {
69
- "@types/node": "^25.3.3",
70
- "oxfmt": "^0.36.0",
71
- "oxlint": "^1.51.0",
72
- "tsdown": "^0.20.3",
69
+ "@types/node": "^25.5.0",
70
+ "oxfmt": "^0.40.0",
71
+ "oxlint": "^1.55.0",
72
+ "tsdown": "^0.21.2",
73
73
  "typescript": "^5.9.3",
74
- "vitest": "^4.0.18"
74
+ "vitest": "^4.1.0"
75
75
  },
76
76
  "engines": {
77
77
  "node": ">=22.0.0",
78
78
  "pnpm": ">=10.0.0"
79
79
  },
80
- "packageManager": "pnpm@10.30.3"
80
+ "packageManager": "pnpm@10.32.1"
81
81
  }