v3: Allow hyphen character in regex pattern to use support queries as is (#13605)

This is the v3 equivalent of PR #13596

Matching for the hyphen character in the existing regex to use support
queries as-is

Resolves #13594

Tests (w/ updated):
- ✅ `supports-[display:grid]:grid`
- ✅ `supports-[transform-origin:5%_5%]:underline`
- ✅ `supports-[not(foo:bar)]:underline`
- ✅ `supports-[(foo:bar)or(bar:baz)]:underline`
- ✅ `supports-[(foo:bar)and(bar:baz)]:underline`
- ✅ `supports-[(foo:bar)_and_(bar:baz)]:grid`
- ✅ `supports-[(foo:bar)_and_(bar:baz)_or(baz:qux)]:grid`
- ✅ `supports-[container-type]:underline`
- ✅ `supports-grid:underline`
- ✅ `supports-[--test]:flex`
- ✅ `supports-[selector(A_>_B)]:underline`
- ✅ `supports-[font-format(opentype)]:grid`
- ✅ `supports-[font-tech(color-COLRv1)]:flex`

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This commit is contained in:
Brandon McConnell 2025-01-28 11:42:09 -05:00 • committed by GitHub
parent 4f9f603e12
commit 40f506f317
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 75 additions and 35 deletions

View file

@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Nothing yet!
### Fixed
- Improve support for raw `supports-[…]` queries in arbitrary values ([#13605](https://github.com/tailwindlabs/tailwindcss/pull/13605))
## [3.4.17] - 2024-12-17

View file

@ -409,8 +409,8 @@ export let variantPlugins = {
matchVariant(
'supports',
(value = '') => {
let check = normalize(value)
let isRaw = /^\w*\s*\(/.test(check)
let check = value.startsWith('--') ? value : normalize(value)
let isRaw = /^[\w-]*\s*\(/.test(check)
// Chrome has a bug where `(condition1)or(condition2)` is not valid
// But `(condition1) or (condition2)` is supported.

View file

@ -767,18 +767,28 @@ it('should support supports', () => {
<div class="supports-[display:grid]:grid"></div>
<!-- Value with spaces, needs to be normalized -->
<div class="supports-[transform-origin:5%_5%]:underline"></div>
<!-- Selectors (raw) -->
<div class="supports-[selector(A_>_B)]:underline"></div>
<!-- 'not' check (raw) -->
<div class="supports-[not(foo:bar)]:underline"></div>
<!-- 'or' check (raw) -->
<div class="supports-[(foo:bar)or(bar:baz)]:underline"></div>
<!-- 'and' check (raw) -->
<div class="supports-[(foo:bar)and(bar:baz)]:underline"></div>
<!-- 'and' check with spaces (raw) -->
<div class="supports-[(foo:bar)_and_(bar:baz)]:grid"></div>
<!-- 'and' + 'or' check (raw) -->
<div class="supports-[(foo:bar)_and_(bar:baz)_or(baz:qux)]:grid"></div>
<!-- No value give for the property, defaulting to prop: var(--tw) -->
<div class="supports-[container-type]:underline"></div>
<!-- Named supports usage -->
<div class="supports-grid:underline"></div>
<!-- Custom properties -->
<div class="supports-[--test]:flex"></div>
<!-- Function syntax: selector (raw) -->
<div class="supports-[selector(A_>_B)]:underline"></div>
<!-- Function syntax: font-format (raw) -->
<div class="supports-[font-format(opentype)]:grid"></div>
<!-- Function syntax: font-tech (raw) -->
<div class="supports-[font-tech(color-COLRv1)]:flex"></div>
</div>
`,
},
@ -791,45 +801,73 @@ it('should support supports', () => {
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@supports (display: grid) {
.supports-grid\:underline {
text-decoration-line: underline;
}
.supports-\[display\:grid\]\:grid {
display: grid;
}
expect(result.css).toMatchInlineSnapshot(`
"@supports (display: grid) {
.supports-grid\\:underline {
text-decoration-line: underline
}
}
@supports (foo: bar) and (bar: baz) {
.supports-\[\(foo\:bar\)and\(bar\:baz\)\]\:underline {
text-decoration-line: underline;
}
@supports (--test: var(--tw)) {
.supports-\\[--test\\]\\:flex {
display: flex
}
}
@supports (foo: bar) or (bar: baz) {
.supports-\[\(foo\:bar\)or\(bar\:baz\)\]\:underline {
text-decoration-line: underline;
}
@supports font-tech(color-COLRv1) {
.supports-\\[font-tech\\(color-COLRv1\\)\\]\\:flex {
display: flex
}
}
@supports (foo:bar) and (bar:baz) {
.supports-\\[\\(foo\\:bar\\)_and_\\(bar\\:baz\\)\\]\\:grid {
display: grid
}
}
@supports (foo:bar) and (bar:baz) or (baz:qux) {
.supports-\\[\\(foo\\:bar\\)_and_\\(bar\\:baz\\)_or\\(baz\\:qux\\)\\]\\:grid {
display: grid
}
}
@supports (display:grid) {
.supports-\\[display\\:grid\\]\\:grid {
display: grid
}
}
@supports font-format(opentype) {
.supports-\\[font-format\\(opentype\\)\\]\\:grid {
display: grid
}
}
@supports (foo:bar) and (bar:baz) {
.supports-\\[\\(foo\\:bar\\)and\\(bar\\:baz\\)\\]\\:underline {
text-decoration-line: underline
}
}
@supports (foo:bar) or (bar:baz) {
.supports-\\[\\(foo\\:bar\\)or\\(bar\\:baz\\)\\]\\:underline {
text-decoration-line: underline
}
}
@supports (container-type: var(--tw)) {
.supports-\[container-type\]\:underline {
text-decoration-line: underline;
}
.supports-\\[container-type\\]\\:underline {
text-decoration-line: underline
}
}
@supports not (foo: bar) {
.supports-\[not\(foo\:bar\)\]\:underline {
text-decoration-line: underline;
}
@supports not (foo:bar) {
.supports-\\[not\\(foo\\:bar\\)\\]\\:underline {
text-decoration-line: underline
}
}
@supports selector(A > B) {
.supports-\[selector\(A_\>_B\)\]\:underline {
text-decoration-line: underline;
}
.supports-\\[selector\\(A_\\>_B\\)\\]\\:underline {
text-decoration-line: underline
}
}
@supports (transform-origin: 5% 5%) {
.supports-\[transform-origin\:5\%_5\%\]\:underline {
text-decoration-line: underline;
}
@supports (transform-origin:5% 5%) {
.supports-\\[transform-origin\\:5\\%_5\\%\\]\\:underline {
text-decoration-line: underline
}
}
"
`)
})
})