Skip to content

Breaking changes in plugins potentially caused by parser changes #13473

@brandonmcconnell

Description

@brandonmcconnell

What version of Tailwind CSS are you using?

v3.4.3

What browser are you using?

Chrome v123.0.6312.107 (Official Build) (arm64)

What operating system are you using?

macOS Sonoma v14.4.1 (23E224)

Reproduction URL

Describe your issue

I was auditing some of the plugins in my growing collection of plugins I've developed for the Tailwind CSS community this past week, and a couple of them appear to now break due to what I perceive to be changes in the way the parser handles arbitrary values in plugins.

Affected plugins:

1. MultiTool for Tailwind CSS (github | npm)

My MultiTool for Tailwind CSS plugin breaks when it contains a string including the : symbol, likely due to the parser terminating/splitting variants when it encounters the : symbol.

I've done some testing, and this doesn't appear to be something my plugin can account for internally. If you look at the reproduction URL linked above (also here), the first two lines receive the expected styles, but the last breaks entirely if it contains that character.

The problematic instances (those that contain :) don't appear to trigger the plugin and are likely seen as erroneous since, assuming my guesses here are correct, a usage like multi-[underline;hover:font-bold] would be split into :multi-[underline;hover and font-bold].

With some slight tweaking to the parser, values could whitelist any instances of : within brackets.

  • current: 'a:b:[c:d]:e'['a', 'b', '[c', 'd]', 'e']
  • desired: 'a:b:[c:d]:e'['a', 'b', '[c:d]', 'e']

It's also important to note here that this was not always the case, or at least I am convinced it is not, as I include this example in the plugin's README, which worked when I tested it before including it in the README:

<div class="sm:[&>div]:hover:active:multi-[font-bold;text-[red];[font-family:'Open_Sans',sans-serif]]">
  When hovered, this text will appear bold, red, and in Open Sans font.
</div>

Even a more :-riddled nested variant should be perfectly fine:

<div class="hover:multi-[[&:is(*)]:focus:underline;[--some-var:{whatever}]]"></div>

2. JS Tool for Tailwind CSS (github | npm)

Without rehashing many of the same points I did above, if you take a look at this Tailwind Play example linked above (also here), you'll see many examples I use to showcase how JS can expose specific values to Tailwind CSS using plugins. Admittedly, I seldom use this one, but it is nice sometimes when I need to break glass and expose JSON values to CSS while testing. I could expose them as CSS variables alternatively, but it's helpful to have some means to directly interface with raw data like this, even if only used on occasion.

Here are those same examples from the linked Tailwind Play example, all of which previously worked:

<div class="before:js-[content-['fontSize.2xl_===_#{theme('fontSize.2xl')}']]"></div>
<div class="before:js-[content-['the_registered_config_keys_are_#{Object.keys(config()).join(',_')}']]"></div>
<div class="before:js-[content-['A_random_digit_is_#{randomDigit()}']]"></div>
<div class="js-[[--random-color:#{randomColor()}]] js-[[--random-color-2:#{randomColor()}]] text-[--random-color] font-semibold [text-shadow:1px_2px_0_var(--random-color-2)]">Random_colors_ftw!</div>
<div class="js-[[--random-length:#{randomRange(16,22)}px]] text-[length:--random-length]">Random sizes too 🤯</div>

In both of these examples, I'm primarily addressing how these regressions limit plugin authors from achieving some of the powerful tasks plugins were formerly able to perform.

Both of these plugins may seem to operate unconventionally, but that's why they're plugins. This is part of what excites a community like this one—testing the limits of a technology like Tailwind CSS, finding various ways it can be extended to achieve different tasks, and ultimately building within those limits to make someone else's work easier.

I've heard from real users of my plugins how my tools have improved their experience building with Tailwind CSS, and I would hate to discontinue some of them due to breaking changes.

Even this past week, I've been prepping content for a blog post or video—perhaps both—on the powerful ways Tailwind CSS plugins supercharge the developer experience, demonstrating examples and providing a crash course on how to build effective plugins.

"The power of JavaScript in the simple and familiar form factor of Tailwind CSS utilities." (still bikeshedding the name)

Because many people primarily associate Tailwind CSS with CSS (for obvious reasons), they miss that with plugins, we can interject all sorts of sophisticated and useful functionality into our utilities. Plugins are essentially middleware that allow us to bridge the parser/compiler to our frontend in dynamic and performant ways, leveraging build-time processing.

Many things that are not yet possible in pure CSS are possible with Tailwind CSS because of this JS processing, so it acts more like mixins and functions than just variable interpolation.

That said, it would be helpful to use examples like these to demonstrate the flexibility of Tailwind CSS plugins. Thanks!

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions