feat: handle backslash in @utility name#19626
feat: handle backslash in @utility name#19626RobinMalfait merged 7 commits intotailwindlabs:mainfrom
@utility name#19626Conversation
WalkthroughThis change adds support for escape sequences in 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/tailwindcss/src/index.ts`:
- Around line 234-235: The current blanket removal of backslashes (node.params =
node.params.replace(/\\/g, '')) breaks CSS hex/char escapes; replace that line
to call the existing unescape helper (e.g., node.params = unescape(node.params))
so CSS escapes like \61 are decoded correctly while still producing literal
characters for sequences such as \/ and \%; add the unescape import if missing
and ensure you reference the unescape helper when normalizing node.params.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/tailwindcss/src/utilities.ts (1)
5943-5947: Core change is correct —unescapeis applied in the right place, before both validation and registration.One thing worth noting:
unescapehandles CSS hex unicode escapes (e.g.,\2F→/,\000041→A) in addition to simple character escapes (\/→/). The existing comment and the PR description only mention the simple case. Both branches still have to pass the downstreamisValidStaticUtilityName/isValidFunctionalUtilityNamegates, so no new characters are silently let through — but it may be worth extending the comment (or adding a test) to document that CSS hex escapes are also normalized, to avoid future confusion about the scope of this feature.📝 Suggested comment clarification
- // Allow escaped characters in the name for compatibility with formatters and - // other parsers, to ensure valid CSS syntax. E.g.: `@utility foo-1\/2`. - // - // Note: the actual utility will be `foo-1/2` + // Allow CSS escape sequences in the name for compatibility with formatters and + // other parsers that require valid CSS syntax. Both simple character escapes + // (e.g., `@utility foo-1\/2`) and CSS hex unicode escapes + // (e.g., `@utility foo-\2Fbar`) are normalized to their unescaped forms before + // validation and registration. + // + // Note: `@utility foo-1\/2` and `@utility foo-1/2` produce the same utility `foo-1/2` let name = unescape(node.params)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/tailwindcss/src/utilities.ts` around lines 5943 - 5947, Update the comment above the unescape(node.params) call to note that unescape also normalizes CSS hex unicode escapes (e.g. "\2F" → "/" and "\000041" → "A") in addition to simple escapes like "\/"; mention that the normalized name is still validated by isValidStaticUtilityName and isValidFunctionalUtilityName so no new invalid characters bypass checks, and consider adding a unit test demonstrating a hex-escaped input (via node.params) is correctly unescaped and validated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/tailwindcss/src/utilities.ts`:
- Around line 5943-5947: Update the comment above the unescape(node.params) call
to note that unescape also normalizes CSS hex unicode escapes (e.g. "\2F" → "/"
and "\000041" → "A") in addition to simple escapes like "\/"; mention that the
normalized name is still validated by isValidStaticUtilityName and
isValidFunctionalUtilityName so no new invalid characters bypass checks, and
consider adding a unit test demonstrating a hex-escaped input (via node.params)
is correctly unescaped and validated.
Resolves #19607
Summary
I believe there is no obstacle to simply ignoring backslashes in the name. This way, various validators - which are not aware of Tailwind CSS's specific syntax (which allows the
/character to be used directly in utility names) - can still be bypassed using backslashes. For example, instead of@utility push-1/2, one could use@utility push-1\/2, while the end result would be identical.Test plan
I took a previous utility test as a baseline and extended it with backslashes, and I expect the same result in the output as in the original test case: