Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove duplicate classes and excess whitespace #272

Merged
merged 9 commits into from
May 30, 2024
Merged

Conversation

thecrypticace
Copy link
Contributor

@thecrypticace thecrypticace commented May 29, 2024

This PR introduces two new features to the plugin: removal of duplicate class names and removal of excess / unncecessary whitespace.

Removal of duplicate classes

This feature is always enabled. An example of this feature in action is shown below — notice that the extra p-4 class is removed:

- <div className="sm:p-0 p-4 p-4" />
+ <div className="p-4 sm:p-0" />

Removal of excess / unnecessary whitespace

This was originally implemented in #70 but reverted due to issues breaking code that relies on the presence of whitespace in a class list. This PR enables this feature by default but allows you to disable it (via tailwindPreserveWhitespace) should you run into issues. For example, the following code will be formatted as shown below:

- <div className=" sm:p-0 \n      p-4  " />
+ <div className="p-4 sm:p-0" />

What can break?

As mentioned above, removal of whitespace in a class list can break code that relies on the presence of leading or trailing whitespace. e.g. when concatenating strings of classes. In the following code, you can see the after version results in a non-existent class. This is a known limitation and is why this feature can be disabled.

- <div className={`flex ` + `text-red-500`} />
+ <div className={`flex` + `text-red-500`} />

To disable this feature and preserve whitespace in class lists, set the option tailwindPreserveWhitespace to true in your Prettier configuration:

{
  // … your config
  "tailwindPreserveWhitespace": true
}

If you don't want to disable the feature for your entire project you can use one of the following methods:

  1. Use // prettier-ignore to prevent Prettier from formatting the line:
// prettier-ignore
<div className={`flex ` + `text-red-500`} />
  1. Use a separate, whitespace-only string.

When sorting we will ensure that a class list that is composed of only whitespace is not removed. It will, however, be shortened to a single space:

- <div className={`flex  ` + `   ` + ` text-red-500`} />
+ <div className={`flex` + ` ` + `text-red-500`} />
  1. Disable the feature for just one file. You can do this by utilizing the "overrides" feature in Prettier. For example, you can add the following to your .prettierrc file and it will only preserve whitespace in src/components/MyComponent.jsx:
{
  // … your config
  "overrides": [
    {
      "files": "src/components/MyComponent.jsx",
      "options": {
        "tailwindPreserveWhitespace": true
      }
    }
  ]
}

@adamwathan
Copy link
Member

Nice! Personally I would vote for enabling this by default and making it opt-out. Would be a breaking change but I think worth it because of how much this feature has been requested.

We leave one space in when a class list consists of just whitespace
@thecrypticace
Copy link
Contributor Author

Yeah, I'm fine with enabling it by default. We'll want to release this as v0.6.0 if we do.

Copy link
Contributor

@RobinMalfait RobinMalfait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Only place where I can't make it work (which might be expected honestly) is in HTML files with handlebars-like interpolation.

For React, this seems to work as expected, input:

<div className={clsx('p-2       p-2', condition ? 'p-4 p-4' : '')} />

Output:

<div className={clsx('p-2', condition ? 'p-4' : '')} />

Same for Vue, works as expected, input:

<div :class="['p-2         p-2', condition ? 'p-4 p-4' : '']"></div>

Output:

<div :class="['p-2', condition ? 'p-4' : '']"></div>

However, if we do something similar in (post) HTML, then this doesn't seem to be the case.

Input:

<div class="p-2         p-2 {{ condition ? 'p-4 p-4' : '' }}"></div>

Actual:

<div class="p-2         p-2 {{ condition ? 'p-4 p-4' : '' }}"></div>

Expected:

<div class="p-2 {{ condition ? 'p-4' : '' }}"></div>

Not the end of the world, but if this is expected, then we might want to mention this in the description. It's also totally possible I'm missing something.

@thecrypticace
Copy link
Contributor Author

Yeah that's expected and not a side-effect of this PR. Prettier itself completely ignores class attributes with handlebars interpolation and we do the same. We could revisit that decision (in a separate PR) but we'd need to parse each attribute containing {{ as a handlebars AST first.

@thecrypticace thecrypticace merged commit 1f83aae into main May 30, 2024
1 check passed
@thecrypticace thecrypticace deleted the feat/collapsing branch May 30, 2024 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants