prettier-plugin-classnames icon indicating copy to clipboard operation
prettier-plugin-classnames copied to clipboard

[FAQ] Compatibility with `prettier-plugin-tailwindcss`

Open ony3000 opened this issue 1 year ago • 25 comments

Can I use this plugin with prettier-plugin-tailwindcss?

Of course! However, there are a few notes.

  1. Languages that can be used with prettier-plugin-tailwindcss are limited to:

    • JavaScript
    • TypeScript
    • Vue (v0.3.0 or higher)
    • Astro (v0.6.0 or higher)
    • Angular, HTML, Svelte (v0.7.0 or higher)

    Support for other languages requires further development.

  2. You need to add prettier-plugin-merge to your Prettier configuration.

    This is because if two or more plugins are configured to format a particular language, Prettier will only use the last of those plugins.

    So, for example, if you configure it like this, only prettier-plugin-tailwindcss will be used.

    {
      "plugins": [
        "prettier-plugin-classnames", // ignored
        "prettier-plugin-tailwindcss"
      ]
    }
    

    By reordering the two plugins, now only prettier-plugin-classnames is used.

    {
      "plugins": [
        "prettier-plugin-tailwindcss", // ignored
        "prettier-plugin-classnames"
      ]
    }
    

    I created prettier-plugin-merge to overcome this limitation of Prettier.

    prettier-plugin-merge uses the plugins listed before it sequentially to format and merge them.

    So, to allow Prettier to use prettier-plugin-merge, change the configuration as follows:

    {
      "plugins": [
        "prettier-plugin-tailwindcss",
        "prettier-plugin-classnames",
        "prettier-plugin-merge"
      ]
    }
    

    Now Prettier will only use prettier-plugin-merge among the three plugins, but prettier-plugin-merge will use prettier-plugin-tailwindcss and prettier-plugin-classnames sequentially.

    So the class names will be sorted first and then wrapped.

ony3000 avatar Feb 07 '24 14:02 ony3000

I think it would be better to leave the issue open so that visitors can be more aware of how to use the plugin.

ony3000 avatar Feb 22 '24 12:02 ony3000

Hi @ony3000

Your plugin doesn't work for me. I put the following in my .prettierrc:

{
  "plugins": [
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-merge"
  ]
}

I then ran prettier . --write and all my files were reported unchanged. The only thing I noticed was that for some reason it took prettier 227ms to process my 75 LoC App.tsx, while normally (with prettier-plugin-tailwindcss only) it takes around 100ms.

ghost avatar Mar 08 '24 23:03 ghost

@dprkh Have you checked the Ending Position option? When this option is set to default(relative), line breaks are performed only for class names without considering the length of the code. Therefore, if the class name is short enough, the plugin may appear to not work because it remains a single-line class name.

If class names that are longer than the printWidth do not wrap, please report the issue with more detailed information and I will investigate.

Since prettier-plugin-merge sequentially uses the plugins listed before it, it could theoretically take more time than if only prettier-plugin-tailwindcss was used. But maybe the logic of this plugin is not optimized. :sweat_smile:

ony3000 avatar Mar 09 '24 04:03 ony3000

@dprkh Have you checked the Ending Position option? When this option is set to default(relative), line breaks are performed only for class names without considering the length of the code. Therefore, if the class name is short enough, the plugin may appear to not work because it remains a single-line class name.

If class names that are longer than the printWidth do not wrap, please report the issue with more detailed information and I will investigate.

I've tried adding --ending-position=relative when running prettier . --write and it did not seem to have changed anything. I'm not sure what the default printWidth is, but I have a fairly long class name right here, so I would expect this line and a couple of others to have been broken down. You can also find my .prettierrc and package.json for review.

Since prettier-plugin-merge sequentially uses the plugins listed before it, it could theoretically take more time than if only prettier-plugin-tailwindcss was used. But maybe the logic of this plugin is not optimized. 😅

Performance is fine, this is just a formatter after all. I was only pointing out that something is definitely happening there.

ghost avatar Mar 09 '24 09:03 ghost

Ah! The name that this plugin considers to be the default attribute for jsx (and tsx) is className.

So, in your case the customAttributes: ["class"] setting (--custom-attributes=class if you are using the CLI method) should be added.

ony3000 avatar Mar 09 '24 11:03 ony3000

Ah! The name that this plugin considers to be the default attribute for jsx (and tsx) is className.

So, in your case the customAttributes: ["class"] setting (--custom-attributes=class if you are using the CLI method) should be added.

Yep, this worked. Thank you.

ghost avatar Mar 09 '24 11:03 ghost

so, it doesn't work with SvelteKit, right?

SergiySev avatar Mar 13 '24 22:03 SergiySev

@SergiySev For now, yes. In this case, you can still configure Prettier as follows:

{
  "plugins": [
    "prettier-plugin-svelte",
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-merge"
  ]
}

However, among the above plugins, only prettier-plugin-svelte and prettier-plugin-tailwindcss support svelte formatting, so Prettier will use prettier-plugin-tailwindcss.

There is logic inside prettier-plugin-tailwindcss that enables compatibility with prettier-plugin-svelte, so class name sorting works.

ony3000 avatar Mar 14 '24 12:03 ony3000

I'm using this plugin and the merge plugin with angular with the following config:

/** @type {import("prettier").Config} */
const config = {
  plugins: [
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-merge",
  ],
  customAttributes: ["class", "className", "style"],
  endingPosition: "absolute-with-indent",
  printWidth: 80,
  overrides: [
    {
      files: "*.html",
      options: {
        parser: "angular",
      },
    },
  ],
};

export default config;

and I have the following html snippet:

    <button
      type="submit"
      class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 sm:w-auto dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
    >
      Submit
    </button>

When I run prettier with:

 npx prettier --write .

The class name does not get formated

lampewebdev avatar Mar 14 '24 18:03 lampewebdev

@lampewebdev As you can see in the first note, angular is also not currently supported. Further development is required.

ony3000 avatar Mar 15 '24 02:03 ony3000

@SergiySev For now, yes. In this case, you can still configure Prettier as follows:

{
  "plugins": [
    "prettier-plugin-svelte",
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-merge"
  ]
}

However, among the above plugins, only prettier-plugin-svelte and prettier-plugin-tailwindcss support svelte formatting, so Prettier will use prettier-plugin-tailwindcss.

There is logic inside prettier-plugin-tailwindcss that enables compatibility with prettier-plugin-svelte, so class name sorting works.

Just to double check, are you saying formatting through this plugin doesn't work in SvelteKit, right?!

yyijoo avatar Apr 16 '24 00:04 yyijoo

@yyijoo Strictly speaking, this plugin can work on components written in *.js (or *.ts) files even in SvelteKit projects.

But I haven't used SvelteKit, so I don't know if such a use case exists.

It's true that it doesn't currently work with *.svelte files, and I plan to include svelte support in the v0.7.0 release.

ony3000 avatar Apr 16 '24 11:04 ony3000

I see Thank you for your reply! @ony3000

yyijoo avatar May 02 '24 04:05 yyijoo

Finally, v0.7.0 has been released.

@SergiySev @yyijoo svelte is now supported!

@lampewebdev angular is now also supported!

ony3000 avatar Jun 08 '24 14:06 ony3000

Hi, Can we be compatible with the prettier-plugin-multiline-arrays plugin?

u3u avatar Jul 22 '24 08:07 u3u

@u3u I looked at prettier-plugin-multiline-arrays, and it appears to support five different parsers.

The intersection of prettier-plugin-multiline-arrays, this plugin, and prettier-plugin-merge is babel and typescript, so it is expected to be compatible with JavaScript and TypeScript.

ony3000 avatar Jul 22 '24 09:07 ony3000

@ony3000 Thank you! That's enough!

u3u avatar Jul 22 '24 12:07 u3u

Thanks for this plugin @ony3000. But the biggest pain still exists even with prettier-plugin-merge: the Format on save option in many editors takes the classNames back to a single line.

I know we can format with npx prettier --write ., but having your code change back to a previous state when saving or working on it is a HUGE PAIN.

I believe you've been using this. So how did you work around it?

udohjeremiah avatar Sep 04 '24 11:09 udohjeremiah

@udohjeremiah I mainly use VS Code. The format on save option is of course enabled and works fine.

Please try cloning the next-tailwind-template repository and check, and if the "pain" is reproduced, please report the issue.

ony3000 avatar Sep 04 '24 12:09 ony3000

Thanks for this plugin @ony3000. But the biggest pain still exists even with prettier-plugin-merge: the Format on save option in many editors takes the classNames back to a single line.

I know we can format with npx prettier --write ., but having your code change back to a previous state when saving or working on it is a HUGE PAIN.

Put the same settings to your VS Code settings.json

prettier.config.mjs

/** @type {import('prettier').Config} */
export default {
  plugins: [
    'prettier-plugin-astro',
    'prettier-plugin-tailwindcss',
    'prettier-plugin-classnames',
    'prettier-plugin-merge',
  ],
  singleQuote: true,
  tabWidth: 2,
  useTabs: false,
  trailingComma: 'es5',
  printWidth: 80,
  tailwindConfig: './tailwind.config.mjs',
};

VS Code settings.json

{
  "prettier.singleQuote": true,
  "prettier.tabWidth": 2,
  "prettier.useTabs": false,
  "prettier.trailingComma": "es5",
  "prettier.printWidth": 80,
  "prettier.plugins": [
    "prettier-plugin-astro",
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-merge"
  ]
}

Modify to your needs accordingly. Sometimes it's also a good idea to restart VS Code when changing these settings.

heby1 avatar Oct 07 '24 00:10 heby1

Thanks for this plugin @ony3000. But the biggest pain still exists even with prettier-plugin-merge: the Format on save option in many editors takes the classNames back to a single line. I know we can format with npx prettier --write ., but having your code change back to a previous state when saving or working on it is a HUGE PAIN.

Put the same settings to your VS Code settings.json

prettier.config.mjs

/** @type {import('prettier').Config} */
export default {
  plugins: [
    'prettier-plugin-astro',
    'prettier-plugin-tailwindcss',
    'prettier-plugin-classnames',
    'prettier-plugin-merge',
  ],
  singleQuote: true,
  tabWidth: 2,
  useTabs: false,
  trailingComma: 'es5',
  printWidth: 80,
  tailwindConfig: './tailwind.config.mjs',
};

VS Code settings.json

{
  "prettier.singleQuote": true,
  "prettier.tabWidth": 2,
  "prettier.useTabs": false,
  "prettier.trailingComma": "es5",
  "prettier.printWidth": 80,
  "prettier.plugins": [
    "prettier-plugin-astro",
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-merge"
  ]
}

Modify to your needs accordingly. Sometimes it's also a good idea to restart VS Code when changing these settings.

Does not work for me :( I get Unknown Configuration Setting for "prettier.plugins": in VSCode.

n3ssi3 avatar Nov 27 '24 08:11 n3ssi3

@n3ssi3 I didn't check carefully when the above comment was written. Now that I look back, it looks like there is no plugins property in the Prettier settings in VS Code.

And I don't think there's any need for a duplicate Prettier configuration.

ony3000 avatar Nov 27 '24 12:11 ony3000

Edit: this is now fixed 🙌

I understand too late that the merge plugin will impact everything before it by design which may or may not be desireable. Should the merge plugin be more specific in usage? The following breaks for me and I have a hard time pointing at the specific cause, even though those aren't all handling related code lines

/** @type {import("prettier").Config} */
module.exports = {
  endingPosition: 'absolute-with-indent',
  importOrder: [...],
  importOrderTypeScriptVersion: '5.0.0',
  plugins:
    // NOTE Order matters, the merge plugin ensures they are run sequentially
    [
      '@ianvs/prettier-plugin-sort-imports',
      'prettier-plugin-tailwindcss',
      'prettier-plugin-classnames',
      'prettier-plugin-merge',
    ],
  proseWrap: 'always',
  singleQuote: true,
  tailwindConfig: './tailwind.config.ts',
  tailwindFunctions: ['twJoin', 'twMerge'],
};

In addition to the following undesired changes in Markdown content

 Some Markdown content.

 ```tsx
-<Komponent />
+<Komponent />;
 ```

And even though --file-info seems to infer the appropriate parser, Prettier errors on some HTML:

[error] path/to/some.html: SyntaxError: ';' expected. (3:16)
[error]   1 | <!doctype html>
[error]   2 | <html>
[error] > 3 |   <head>
[error]     |                ^
[error]   4 |     <title>Some Title</title>
[error]   5 |     <script>
[error]   6 |       /** @license React v17.0.1
[error]   1 | <!doctype html>
[error]   2 | <html>
[error] > 3 |   <head>
[error]     |                ^
[error]   4 |     <title>Some Title</title>
[error]   5 |     <script>
[error]   6 |       /** @license React v17.0.1

Similar results happened with the original prettier-plugin-sort-imports plugin and I seem to reproduce by commenting plugins one by one and the classnames plugin seems to be the culprit. What am I missing?

angrybacon avatar Nov 29 '24 15:11 angrybacon

@angrybacon Well, this is the first time I've seen this type of problem, so I'll have to investigate it to figure out the cause.

Please report the issue by attaching the versions of Prettier and plugins, your Prettier configuration, and an example of the code that is causing the problem, and I will look into it.

ony3000 avatar Nov 29 '24 15:11 ony3000

Thank you for being so responsive 🙏 Unfortunately I could not reproduce my 2 issues with the exact same version numbers I use in my project so I'm not sure where to look now

I've added the sandbox and details anyway in case you can think of something relevant https://github.com/ony3000/prettier-plugin-classnames/issues/80

angrybacon avatar Nov 29 '24 17:11 angrybacon