eslint-plugin-tailwindcss icon indicating copy to clipboard operation
eslint-plugin-tailwindcss copied to clipboard

[Feature request] Support for `eslint` `v9.1.1`

Open cewald opened this issue 10 months ago • 5 comments

Is your feature request related to a problem? Please describe. I'm using nuxt and the latest @nuxt/eslint module which utilizes eslint version 9 and I couldn't make it work. If I import the eslint-plugin-tailwindcss index file in the new flat-config syntax e.g. an eslint.config.mjs, I'll get an error:

[Error - 13:47:05] Request textDocument/formatting failed.
  Message: Request textDocument/formatting failed with message: Config (unnamed): Key "rules": Key "classnames-order": Expected severity of "off", 0, "warn", 1, "error", or 2.
  Code: -32603 

And here the config file (eslint.config.mjs):

// @ts-check
import withNuxt from './.nuxt/eslint.config.mjs'
import pluginVue from 'eslint-plugin-vue'
import pluginTailwindCSS from 'eslint-plugin-tailwindcss'

export default withNuxt([
  ...pluginVue.configs['flat/recommended'],
  pluginTailwindCSS,
  {
    rules: {
      // ...
    }
  }
])

Describe the solution you'd like My guess is to update to the new flat-config syntax or at least describe in the documentation how to properly implement it for the new configuration syntax.

cewald avatar Apr 25 '24 11:04 cewald

Hey @cewald, I am not familiar with Nuxt, but I am in the process of migrating to flat config and I managed to get eslint-plugin-tailwindcss working with it in my migration testing repository.

Here is my config object for the tailwind plugin:

https://github.com/virtuallyunknown/eslint-flat-config-migration/blob/master/configs/tailwind.js

Here is my main config file:

https://github.com/virtuallyunknown/eslint-flat-config-migration/blob/master/eslint.config.js#L5

This isn't a "it works for me, so it should work for everyone" type of comment, just thought this working setup might give you a hint or idea on how to solve your issue.

https://github.com/francoismassart/eslint-plugin-tailwindcss/assets/24871108/45bb6892-36d0-42fc-8b92-33044e82f3d7

If we look at what the plugin exports, this isn't directly flat config compatible (parserOptions for example is no longer root level key, it's child property of languageOptions), but you can easily build this yourself like in my tailwind.js config file, with the plugins, languageOptions and rules keys.

Cheers.

virtuallyunknown avatar Apr 25 '24 16:04 virtuallyunknown

using eslint v8 (which also uses the flat-config), you can do this:

// @ts-check
import { FlatCompat } from '@eslint/eslintrc'
import withNuxt from './.nuxt/eslint.config.mjs'

const compat = new FlatCompat()

export default withNuxt(
	{
		rules: {
			// ...
		}
	}, ...compat.config({
		extends: ['plugin:tailwindcss/recommended'],
		rules: {
			'tailwindcss/no-custom-classname': 'off',
			'tailwindcss/migration-from-tailwind-2': 'off',
		},
	})
)

this doesn't seem to work with v9 anymore however. i'd recomment sticking to v8 for now.

codeflorist avatar Apr 26 '24 10:04 codeflorist

Regarding eslint v9 support: This comment describes the current source of incompatibility: https://github.com/eslint/eslint/issues/18405#issuecomment-2084982903 It's the usage of the deprecated context.parserServices property.

codeflorist avatar Apr 30 '24 15:04 codeflorist

I made a beta version which may work with eslint v9 npm i [email protected] -D

Can you try it ?

francoismassart avatar May 17 '24 12:05 francoismassart

Greetings @francoismassart. I installed the 3.15.3-beta.9 and it appears that every single rule is detecting errors where it should, the plugin is working as expected.

That said, I am not sure if this is intended or not, but the recommended config is still using the eslintrc format, rather than the flat config format. So for example, a config like this won't work out of the box:

import eslintPluginTailwindCss from 'eslint-plugin-tailwindcss';

export const eslintPluginTailwindCssConfig = [
    {
        ...eslintPluginTailwindCss.configs.recommended,
    }
];

For me this is not an issue because of how I configure the plugin, but I thought it might be worth mentioning anyway.

Cheers!

virtuallyunknown avatar May 17 '24 17:05 virtuallyunknown

@francoismassart Thanks for your work!

Okay, I tested it and had a little hiccup with the different versions 3.16.0-beta.0 & 3.15.3-beta.9 but 3.15.3-beta.9 now seems to work if I use it like this:

import pluginTailwindCSS from 'eslint-plugin-tailwindcss'
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt([
  {
    plugins: { tailwindcss: pluginTailwindCSS },
    rules: pluginTailwindCSS.configs.recommended.rules,
  },
  // ...
])

This is the way it is intended to be, right?

cewald avatar May 21 '24 05:05 cewald

Here is a new version to test, I need feedback from user using:

  • ESLint < v9 + legacy config
  • ESLint < v9 + flat config
  • ESLint v9 + legacy config
  • ESLint v9 + flat config

The beta version to be tested is [email protected] which can be installed via

npm i [email protected] -D

francoismassart avatar May 21 '24 09:05 francoismassart

Thanks for the update. I've tested it with ESLint v9 + flat config and it seems to work just fine.

Here is my eslint.config.mjs:

//...
import eslintPluginTailwindCSS from 'eslint-plugin-tailwindcss'
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt([
  //...
  ...eslintPluginTailwindCSS.configs['flat/recommended'],
  //...
])

cewald avatar May 21 '24 09:05 cewald

Working fine with ESLint 8.57.0 + flat config + Nuxt + AntFu.

eslint.config.js:

import antfu from '@antfu/eslint-config'
import eslintPluginTailwindCSS from 'eslint-plugin-tailwindcss'
import withNuxt from './.nuxt/eslint.config.mjs'
//...

export default withNuxt(
  antfu(
    //...
    ...eslintPluginTailwindCSS.configs['flat/recommended'],
    {
      rules: {},
    },
  ),
)

vladimirsiljkovic avatar May 21 '24 14:05 vladimirsiljkovic

Working fine with ESLint 9.3.0 + Flat config repo link

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import pluginTailwindcss from 'eslint-plugin-tailwindcss'
import type { Linter } from 'eslint'

export default function tailwindcss(): Linter.FlatConfig[] {
  return [
    {
      name: 'tailwindcss/rules',
      plugins: {
        tailwindcss: pluginTailwindcss
      },
      rules: {
        'tailwindcss/classnames-order': 'error',
        'tailwindcss/no-contradicting-classname': 'error',
        'tailwindcss/enforces-shorthand': 'error',
        'tailwindcss/no-custom-classname': 'off',
        'tailwindcss/no-unnecessary-arbitrary-value': 'off',
      }
    }
  ]
}

HugoRCD avatar May 21 '24 15:05 HugoRCD

ESLint v9 + flat config + [email protected] all working good. Repo

virtuallyunknown avatar May 22 '24 06:05 virtuallyunknown

I also tried the latest beta with ESLint 8.15.0 and the legacy config 👍

francoismassart avatar May 22 '24 07:05 francoismassart

Latest version (3.16.0) support both flat config and ESLint 9

npm i [email protected] -D

francoismassart avatar May 22 '24 08:05 francoismassart

@francoismassart Thanks for your work!

Okay, I tested it and had a little hiccup with the different versions 3.16.0-beta.0 & 3.15.3-beta.9 but 3.15.3-beta.9 now seems to work if I use it like this:

import pluginTailwindCSS from 'eslint-plugin-tailwindcss'
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt([
  {
    plugins: { tailwindcss: pluginTailwindCSS },
    rules: pluginTailwindCSS.configs.recommended.rules,
  },
  // ...
])

This is the way it is intended to be, right?

Thank you! This config also work for me.

cvhau avatar Aug 16 '24 05:08 cvhau