Skip to content

kaustubh03/oxlint-plugin-tailwindcss

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oxlint-plugin-tailwindcss

Performant Tailwind CSS linting rules for OxLint. 5 rules ported from eslint-plugin-tailwindcss with pre-computed class matching — 425x faster.

Zero runtime Tailwind compilation. Works out of the box with default Tailwind v3/v4.

Why?

Running eslint-plugin-tailwindcss through OxLint's JS plugin API takes 39 minutes on a 37K file monorepo because it compiles the entire Tailwind class registry at runtime for every file.

This plugin uses pre-computed regex matching against Tailwind's class taxonomy instead. Same rules, same detections, 5 seconds instead of 39 minutes.

Approach 37K files Per file
eslint-plugin-tailwindcss via OxLint jsPlugin 39 min 63ms
oxlint-plugin-tailwindcss 5s 0.13ms

Rules

Rule What it catches Auto-fix
enforces-shorthand mx-3 my-3m-3 Yes
enforces-negative-arbitrary-values Invalid -top-[400px] syntax No
migration-from-tailwind-2 Deprecated TW2 classes (filter, flex-grow, overflow-clip) Partial
no-contradicting-classname w-3 w-5, text-red-500 text-blue-500 No
no-custom-classname Non-Tailwind classes No

Installation

npm install -D oxlint-plugin-tailwindcss
# or
pnpm add -D oxlint-plugin-tailwindcss

Configuration

Add to your .oxlintrc.json:

{
  "jsPlugins": [
    { "name": "tailwindcss", "specifier": "oxlint-plugin-tailwindcss" }
  ],
  "rules": {
    "tailwindcss/enforces-shorthand": "warn",
    "tailwindcss/enforces-negative-arbitrary-values": "warn",
    "tailwindcss/migration-from-tailwind-2": "warn",
    "tailwindcss/no-contradicting-classname": "warn",
    "tailwindcss/no-custom-classname": "warn"
  }
}

Custom class utility functions

By default, the plugin checks className attributes and calls to classnames, clsx, ctl, and twClassNames. To add your own:

{
  "settings": {
    "tailwindcss": {
      "callees": ["twClassNames", "cx", "myClassHelper"]
    }
  }
}

How it works

The original eslint-plugin-tailwindcss calls tailwindcss.createContext() to generate all possible Tailwind classes at runtime. This is thorough but extremely slow.

This plugin takes a different approach:

  1. Static class taxonomy — a 1,400+ line regex pattern map covering every Tailwind utility class (layout, spacing, typography, colors, etc.). Sourced from eslint-plugin-tailwindcss's groups.js (MIT, by François Massart).

  2. Compact color regex — instead of listing every color shade (slate-50|slate-100|...|rose-950), uses a pattern matching Tailwind's naming convention: [a-z]+-<shade> with optional /<opacity>. This keeps V8's regex engine happy while covering all color classes.

  3. Cached config resolution — Tailwind config is resolved once and cached for the entire lint run. No per-file compilation.

  4. Standard ESLint plugin API — works with OxLint's JS plugin system. Same context.report(), visitor pattern, and fixer API.

Detections

enforces-shorthand

// Before
<div className="mx-3 my-3" />        // → "m-3"
<div className="pt-2 pr-2 pb-2 pl-2" /> // → "p-2"

// Detects shorthand opportunities for:
// padding, margin, gap, overflow, border-radius,
// border-width, border-color, border-spacing, scale

no-contradicting-classname

// Caught
<div className="w-3 w-5" />                    // width conflict
<div className="text-red-500 text-blue-500" />  // color conflict
<div className="p-4 p-8" />                     // padding conflict

migration-from-tailwind-2

// Deprecated in Tailwind v3
<div className="filter" />          // removed — no longer needed
<div className="flex-grow" />       // → "grow"
<div className="overflow-clip" />   // → "text-clip"
<div className="decoration-clone" /> // → "box-decoration-clone"

no-custom-classname

// Caught — not a Tailwind class
<div className="my-bogus-class" />
<div className="custom-padding" />

// OK — valid Tailwind
<div className="p-4 text-red-500 hover:bg-blue-200" />

enforces-negative-arbitrary-values

// Caught — invalid syntax
<div className="-top-[400px]" />   // should use negative modifier differently
<div className="-scale-[1.5]" />

Known limitations

  • Color regex approximation — uses [a-z]+-<shade> pattern instead of listing every Tailwind color name. May match non-standard names like foo-500. In practice, false positives are rare.
  • No tailwind.config.js custom theme — custom colors/spacing added via extend.theme are not detected by no-custom-classname. Add them to the whitelist setting.
  • No classnames-order rule — class ordering is better handled by formatters like OxFmt (sortTailwindcss) or Prettier (prettier-plugin-tailwindcss).

Credits

License

MIT

About

Performant Tailwind CSS linting rules for OxLint. 5 rules ported from eslint-plugin-tailwindcss with pre-computed class matching 425x faster. Detects conflicting classes (including colors), shorthand opportunities, deprecated TW2 utilities, invalid negative arbitrary values, and non-Tailwind classnames. Zero runtime Tailwind compilation.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors