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

Upgrade: Ensure underscores in url() and var() are not escaped #14778

Conversation

philipp-spiess
Copy link
Member

@philipp-spiess philipp-spiess commented Oct 24, 2024

This PR fixes an issue where currently a theme() function call inside an arbitrary value that used a dot in the key path:

let className = "ml-[theme(spacing[1.5])]"

Was causing issues when going though the codemod. The issue is that for candidates, we require _ to be escaped, since otherwise they will be replaced with underscore. When going through the codemods, the above candidate would be translated to the following CSS variable access:

let className = "ml-[var(--spacing-1\_5))"

Because the underscore was escaped, we now have an invalid string inside a JavaScript file (as the \ would escape inside the quoted string.

To resolve this, we decided that this common case (as its used by the Tailwind CSS default theme) should work without escaping. In #14776, we made the changes that CSS variables used via var() no longer unescape underscores. This PR extends that so that the Variant printer (that creates the serialized candidate representation after the codemods make changes) take this new encoding into account.

This will result in the above example being translated into:

let className = "ml-[var(--spacing-1_5))"

With no more escaping. Nice!

Test Plan

I have added test for this to the kitchen-sink upgrade tests. Furthermore, to ensure this really works full-stack, I have updated the kitchen-sink test to actually build the migrated project with Tailwind CSS v4. After doing so, we can assert that we indeed have the right class name in the generated CSS.

Copy link
Member Author

philipp-spiess commented Oct 24, 2024

@philipp-spiess philipp-spiess force-pushed the 10-24-upgrade_ensure_underscores_in_url_and_var_are_not_escaped branch from 48526c7 to 55720f2 Compare October 24, 2024 15:04
@philipp-spiess philipp-spiess marked this pull request as ready for review October 24, 2024 15:32
@philipp-spiess philipp-spiess requested a review from a team as a code owner October 24, 2024 15:32
@philipp-spiess philipp-spiess force-pushed the 10-24-don_t_escape_underscores_for_the_first_parameter_of_var_ branch from 6460bcb to 21eb011 Compare October 24, 2024 15:33
@philipp-spiess philipp-spiess force-pushed the 10-24-upgrade_ensure_underscores_in_url_and_var_are_not_escaped branch from 55720f2 to 1b75b2b Compare October 24, 2024 15:33
@philipp-spiess philipp-spiess force-pushed the 10-24-don_t_escape_underscores_for_the_first_parameter_of_var_ branch from 21eb011 to 75aa966 Compare October 24, 2024 15:38
@philipp-spiess philipp-spiess force-pushed the 10-24-upgrade_ensure_underscores_in_url_and_var_are_not_escaped branch from 1b75b2b to 12b61ca Compare October 24, 2024 15:38
Base automatically changed from 10-24-don_t_escape_underscores_for_the_first_parameter_of_var_ to next October 24, 2024 15:42
@philipp-spiess philipp-spiess force-pushed the 10-24-upgrade_ensure_underscores_in_url_and_var_are_not_escaped branch from 12b61ca to 9adc483 Compare October 24, 2024 15:43
CHANGELOG.md Outdated Show resolved Hide resolved
Comment on lines 255 to 262
function never(): never {
throw new Error('This should never happen')
}
Copy link
Member

Choose a reason for hiding this comment

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

Any reason not to inline this if it's only ever called once? Also wonder if it would be helpful to use a more descriptive message like "Unexpected node kind `${node.kind}` is not handled for when escaping underscores" ?

Copy link
Member Author

Choose a reason for hiding this comment

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

The idea here is to use the never type so that TypeScript can actually notify us when we add a test (creating an exhaustive switch)

Screenshot 2024-10-24 at 17 55 37

But... I did screw this up, we actually need to assert that node.value has the type never not just the return function here. 😶‍🌫️

This way that symbol is never read, it won't even compile if a new type to the ValueParser is added!

Copy link
Member

Choose a reason for hiding this comment

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

Another fun solution to this problem is to use

default:
  node satisfies never

Then you don't get a runtime error, but only a compile time one. But I think in either solution (current one and the one I'm showing) we always build regardless of build errors (or at least, it seems to be building locally) 🤔.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah I tried with as and it wasn't working, didn't test satisfies! Yeah might be cleaner.

On the other thing: I think it's fine if it actually builds but at least CI should yell at us if we have a type issue somewhere.

@philipp-spiess philipp-spiess force-pushed the 10-24-upgrade_ensure_underscores_in_url_and_var_are_not_escaped branch from 9adc483 to 0999612 Compare October 24, 2024 15:57
Co-authored-by: Adam Wathan <[email protected]>
@adamwathan adamwathan merged commit b722ebc into next Oct 24, 2024
2 checks passed
@adamwathan adamwathan deleted the 10-24-upgrade_ensure_underscores_in_url_and_var_are_not_escaped branch October 24, 2024 16:49
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.

3 participants