francoismassart / eslint-plugin-tailwindcss

ESLint plugin for Tailwind CSS usage
https://www.npmjs.com/package/eslint-plugin-tailwindcss
MIT License
1.44k stars 66 forks source link

[BUG] Prettier class order don't match with eslint-plugin-tailwindcss #231

Open snikoletopoulos opened 1 year ago

snikoletopoulos commented 1 year ago

Describe the bug With the prettier and eslint plugin installed in some cases the class order don't match.

To Reproduce Steps to reproduce the behavior: In a div element add the classes top-0 left-0 prettier will not change the class orders but there will be an eslint error applying eslint fix will satisfy both eslint and prettier plugin the class names should now be left-0 top-0

Expected behavior when I format with prettier, this error should go away

Screenshots If applicable, add screenshots to help explain your problem. With prettier formating: image

With eslint fix applied (prettier is ok as well with this one): image

francoismassart commented 1 year ago

Notes for self: absolute left-0 top-0 transition-transform group-hover:scale-110

francoismassart commented 1 year ago

@snikoletopoulos Using the "Tidy" button from https://play.tailwindcss.com/0Fyv3SDjWC

The order is <div class="absolute left-0 top-0 transition-transform group-hover:scale-110"></div>

And if I add this exact snippet in the test cases of the classname-order rule, it passes as valid order...

Maybe could you share a minimalistic project demonstrating your specific issue so I can debunk it. thx

snikoletopoulos commented 1 year ago

Here it conflicts both ways, brandPrimary is a custom color

prettier outline-brandPrimary p-2

eslint-config-tailwindcss p-2 outline-brandPrimary

I'll look if i can find an example with no custom themes

anup-a commented 1 year ago

Getting similar issues for the following -

focus:outline-none focus:ring-2 focus:ring-primary-500/25 focus:ring-offset-2

data-[state=open]:bg-light-grey disabled:pointer-events-none

focus:outline-none focus-visible:ring focus-visible:ring-primary-500/25

nikitastryuk commented 1 year ago

+1 conflicting mx-2 flex vs flex mx-2

matheins commented 1 year ago

Having the same issue

JaKXz commented 1 year ago

Curious if anyone has a workaround for this? I am probably going to disable the rule for now, but I would prefer to default to [the recommended] eslint [config via plugin:tailwindcss/recommended]. I am using v3.12 (latest at time of writing)

Here are some examples from me: before prettier, sorted via eslint --fix:

        <div className="mx-auto space-y-4 bg-background p-8 shadow sm:w-full sm:rounded-lg md:mt-24 md:max-w-lg">
            <span className="text-sm text-accent">
              <span className="float-right rounded-full bg-tertiary px-2 text-sm font-semibold leading-5 text-accent">

after prettier:

        <div className="bg-background mx-auto space-y-4 p-8 shadow sm:w-full sm:rounded-lg md:mt-24 md:max-w-lg">
            <span className="text-accent text-sm">
              <span className="bg-tertiary text-accent float-right rounded-full px-2 text-sm font-semibold leading-5">
adonaicandido commented 1 year ago

having the same issue, but when using before:

birtles commented 1 year ago

conflicting mx-2 flex vs flex mx-2

Similarly block mt-8 (eslint-plugin-tailwindcss) vs mt-8 block (prettier)

pdlug commented 1 year ago

I'm seeing the same issue w/ brand colors (ex: border border-primary-500 gets reordered to border-primary-500 ... border by eslint-plugin-react but preserved as original by prettier-plugin-tailwindcss.

mamlzy commented 7 months ago

Here it conflicts both ways, brandPrimary is a custom color

prettier outline-brandPrimary p-2

eslint-config-tailwindcss p-2 outline-brandPrimary

I'll look if i can find an example with no custom themes

i'm facing the same issue..

Ouckah commented 7 months ago

Having a similar issue:

On save: min-w-96 flex h-full w-full

What ESLint wants: flex h-full w-full min-w-96

Any way to fix this?

ryanlonstein commented 7 months ago

I am having the same issue.

Prettier wants:

size-full absolute

ESLint wants:

absolute size-full
scr2em commented 7 months ago

any updates ?

liamlows commented 5 months ago

Is there any solution to this other than removing the prettier-plugin-tailwindcss plugin from the .prettierrc file?

Similar to what others have said when I have eslint-plugin-tailwindcss installed and extends: ['plugin:tailwindcss/recommended', ...] set up in the .eslintrc.js file and also have prettier-plugin-tailwindcss in the plugins array in .prettierrc and linter wants it ordered one way and prettier wants it another just like @ryanlonstein said.

kachkaev commented 5 months ago

There is no need for a Prettier plugin if this ESLint plugin is installed. But if you still want to use both, you can disable a ESLint rule that sorts class names:

// .eslintrc
module.exports = {
  extends: [
    "...",
    "plugin:tailwindcss/recommended",
  ],
  rules: {
    "...": "...",
    "tailwindcss/classnames-order": "off"
  }
};

Note that what prettier-plugin-tailwindcss does is outside the scope of Prettier:

Prettier only prints code. It does not transform it. This is to limit the scope of Prettier. Let’s focus on the printing and do it really well!

Here are a few examples of things that are out of scope for Prettier:

  • Turning single- or double-quoted strings into template literals or vice versa.
  • Using + to break long string literals into parts that fit the print width.
  • Adding/removing {} and return where they are optional.
  • Turning ?: into if-else statements.
  • Sorting/moving imports, object keys, class members, JSX keys, CSS properties or anything else. Apart from being a transform rather than just printing (as mentioned above), sorting is potentially unsafe because of side effects (for imports, as an example) and makes it difficult to verify the most important correctness goal.
liamlows commented 5 months ago

There is no need for a Prettier plugin if this ESLint plugin is installed. But if you still want to use both, you can disable a ESLint rule that sorts class names:

// .eslintrc
module.exports = {
  extends: [
    "...",
    "plugin:tailwindcss/recommended",
  ],
  rules: {
    "...": "...",
    "tailwindcss/classnames-order": "off"
  }
};

Note that what prettier-plugin-tailwindcss does is outside the scope of Prettier:

Prettier only prints code. It does not transform it. This is to limit the scope of Prettier. Let’s focus on the printing and do it really well! Here are a few examples of things that are out of scope for Prettier:

  • Turning single- or double-quoted strings into template literals or vice versa.
  • Using + to break long string literals into parts that fit the print width.
  • Adding/removing {} and return where they are optional.
  • Turning ?: into if-else statements.
  • Sorting/moving imports, object keys, class members, JSX keys, CSS properties or anything else. Apart from being a transform rather than just printing (as mentioned above), sorting is potentially unsafe because of side effects (for imports, as an example) and makes it difficult to verify the most important correctness goal.

Gotcha, I figured that was the case but wasn't for sure. It might be helpful to add a note to the readme when talking about installation that the prettier plugin and this plugin are not complimentary (or at least meant to be) to avoid confusion.

However, I am still curious though as to why the prettier plugin and this plugin had different correct ways the classnames should be ordered.

Thanks for the quick response btw!

mrleblanc101 commented 5 months ago

prettier-plugin-tailwindcss: class="h-14 w-full rounded-md border-white bg-tropical-50 bg-[url('/img/calendar.svg')] bg-[length:1.5rem] bg-[position:center_left_0.75rem] bg-no-repeat pl-12 text-left focus:border-tropical-50 focus:bg-white focus:ring-2 focus:ring-tropical-300 lg:w-1/4 lg:max-w-[252px]" eslint-plugin-tailwindcss: class="bg-tropical-50 focus:border-tropical-50 focus:ring-tropical-300 h-14 w-full rounded-md border-white bg-[url('/img/calendar.svg')] bg-[length:1.5rem] bg-[position:center_left_0.75rem] bg-no-repeat pl-12 text-left focus:bg-white focus:ring-2 lg:w-1/4 lg:max-w-[252px]"

For some reason, eslint-plugin-tailwindcss does not seem to recongnise custom colors in my tailwind.config.js.

export default {
    theme: {
        extend: {
            colors: {
                tropical: {
                    50: '#f0f9f5',
                    100: '#dbf0e5',
                    200: '#b6d6cc',
                    // 200: '#bae0d0',
                    300: '#78C7B0',
                    // 300: '#8cc9b2',
                    400: '#5bac90',
                    500: '#3a8f75',
                    600: '#2a7660',
                    700: '#215b4c',
                    800: '#1c493d',
                    900: '#183c34',
                    950: '#0c221d',
                },
            },
        },
    },
};