Skip to content

Canonicalization: make hex colors case insensitive - #20298

Merged
RobinMalfait merged 4 commits into
mainfrom
fix/issue-20295
Jul 1, 2026
Merged

Canonicalization: make hex colors case insensitive#20298
RobinMalfait merged 4 commits into
mainfrom
fix/issue-20295

Conversation

@RobinMalfait

Copy link
Copy Markdown
Member

This PR fixes an issue where hex-based colors in arbitrary properties and values were considered case-sensitive even though they are case-insensitive in CSS.

If you look at the linked issue, there is this input CSS:

@theme {
  --color-brand-purple: #3f3cbb;
}

We expect that both bg-[#3f3cbb] and bg-[#3F3CBB] get canonicalized to color-brand-purple but before this pr, only the first one would get canonicalized that way (since it's a perfect match).

Technically a bunch more values are case-insensitive but a lot of them are sensitive so to get this 100% correct, a lot more parsing needs to happen. I think we can start with this and expand the logic when needed.

Fixes: #20295

Test plan

  1. Added a regression test based on the linked issue
  2. Added tests for arbitrary properties ([color:#fff] vs [color:#FFF]), and tests for arbitrary properties (bg-[#fff] vs bg-[#FFF])

@RobinMalfait
RobinMalfait requested a review from a team as a code owner July 1, 2026 21:58
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d9b35f32-e3c6-48a4-99ac-61659f5a2df1

📥 Commits

Reviewing files that changed from the base of the PR and between 4dfd747 and e7ad790.

📒 Files selected for processing (1)
  • CHANGELOG.md

Walkthrough

This change adds case-insensitive canonicalization for hex color values. canonicalizeAst now lowercases matched hex literals in declaration values while leaving CSS custom properties unchanged. Tests were added and updated to cover arbitrary properties, arbitrary values, and a regression case where differently cased hex inputs canonicalize to the same themed utility. A changelog entry was also added.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: making hex color canonicalization case insensitive.
Description check ✅ Passed The description is directly related to the code changes and explains the hex-color canonicalization fix.
Linked Issues check ✅ Passed The implementation and tests address issue #20295 by normalizing hex casing for candidate canonicalization.
Out of Scope Changes check ✅ Passed The changed files stay focused on canonicalization logic and its tests, with no obvious unrelated additions.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/tailwindcss/src/canonicalize-candidates.ts (2)

2547-2556: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Hex regex can match inside non-color string literals.

HEX_REGEX blindly scans the entire declaration value and lowercases any hash-prefixed hex-length sequence, including inside quoted string literals (e.g. content: "#FFF002"). Since this only affects the internal canonicalization/signature string (not real output), the practical risk is narrow, but it's a latent correctness gap if declarations with quoted hex-like content are ever canonicalized/compared.


2551-2555: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the redundant lastIndex reset. String.prototype.replace() already starts a global regex at lastIndex = 0, so this line can be dropped without changing behavior.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a7a2f9a8-9a1a-4a5a-bd31-2d22cc8cc17b

📥 Commits

Reviewing files that changed from the base of the PR and between 39656f7 and 4dfd747.

📒 Files selected for processing (2)
  • packages/tailwindcss/src/canonicalize-candidates.test.ts
  • packages/tailwindcss/src/canonicalize-candidates.ts

@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to the canonicalization comparison path and does not affect emitted CSS.

The fix applies hex-color lowercasing only during signature comparison (canonicalizeAst), never to emitted CSS. The regex is correct for all valid CSS hex lengths (3, 4, 6, 8 digits), the global flag's lastIndex is reset defensively before each use, and CSS variable declarations are explicitly excluded. Tests cover both affected code paths and the original bug report.

No files require special attention.

Reviews (2): Last reviewed commit: "update changelog" | Re-trigger Greptile

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.

Uppercase hex arbitrary values aren't suggested as theme colors (e.g. bg-[#3F3CBB])

1 participant