@@ -3,6 +3,7 @@ import { parseCandidate, type Candidate, type Variant } from '../../../../tailwi
3
3
import type { Config } from '../../../../tailwindcss/src/compat/plugin-api'
4
4
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
5
5
import { isPositiveInteger } from '../../../../tailwindcss/src/utils/infer-data-type'
6
+ import * as ValueParser from '../../../../tailwindcss/src/value-parser'
6
7
import { printCandidate } from './candidates'
7
8
8
9
function memcpy < T extends object , U extends object | null > ( target : T , source : U ) : U {
@@ -146,6 +147,83 @@ export function migrateModernizeArbitraryValues(
146
147
continue
147
148
}
148
149
150
+ // Migrate `@media` variants
151
+ //
152
+ // E.g.: `[@media(scripting:none)]:` -> `noscript:`
153
+ if (
154
+ // Only top-level, so `in-[@media(scripting:none)]` is not supported
155
+ parent === null &&
156
+ // [@media (scripting:none)]:flex
157
+ // ^^^^^^^^^^^^^^^^^^^^^^
158
+ ast . nodes [ 0 ] . nodes [ 0 ] . type === 'tag' &&
159
+ ast . nodes [ 0 ] . nodes [ 0 ] . value . startsWith ( '@media' )
160
+ ) {
161
+ // Replace all whitespace such that `@media (scripting: none)` and
162
+ // `@media(scripting:none)` are equivalent.
163
+ //
164
+ // As arbitrary variants that means that these are equivalent:
165
+ // - `[@media_(scripting:_none)]:`
166
+ // - `[@media(scripting:none)]:`
167
+ let parsed = ValueParser . parse ( ast . nodes [ 0 ] . toString ( ) . trim ( ) . replace ( '@media' , '' ) )
168
+
169
+ // Drop whitespace
170
+ ValueParser . walk ( parsed , ( node , { replaceWith } ) => {
171
+ // Drop whitespace nodes
172
+ if ( node . kind === 'separator' && ! node . value . trim ( ) ) {
173
+ replaceWith ( [ ] )
174
+ }
175
+
176
+ // Trim whitespace
177
+ else {
178
+ node . value = node . value . trim ( )
179
+ }
180
+ } )
181
+
182
+ if (
183
+ parsed . length === 1 &&
184
+ parsed [ 0 ] . kind === 'function' && // `(` and `)` are considered a function
185
+ parsed [ 0 ] . nodes . length === 3 &&
186
+ parsed [ 0 ] . nodes [ 0 ] . kind === 'word' &&
187
+ parsed [ 0 ] . nodes [ 1 ] . kind === 'separator' &&
188
+ parsed [ 0 ] . nodes [ 1 ] . value === ':' &&
189
+ parsed [ 0 ] . nodes [ 2 ] . kind === 'word'
190
+ ) {
191
+ let key = parsed [ 0 ] . nodes [ 0 ] . value
192
+ let value = parsed [ 0 ] . nodes [ 2 ] . value
193
+ let replacement : string | null = null
194
+
195
+ if ( key === 'prefers-reduced-motion' && value === 'no-preference' )
196
+ replacement = 'motion-safe'
197
+ if ( key === 'prefers-reduced-motion' && value === 'reduce' )
198
+ replacement = 'motion-reduce'
199
+
200
+ if ( key === 'prefers-contrast' && value === 'more' ) replacement = 'contrast-more'
201
+ if ( key === 'prefers-contrast' && value === 'less' ) replacement = 'contrast-less'
202
+
203
+ if ( key === 'orientation' && value === 'portrait' ) replacement = 'portrait'
204
+ if ( key === 'orientation' && value === 'landscape' ) replacement = 'landscape'
205
+
206
+ if ( key === 'forced-colors' && value === 'active' ) replacement = 'forced-colors'
207
+
208
+ if ( key === 'inverted-colors' && value === 'inverted' ) replacement = 'inverted-colors'
209
+
210
+ if ( key === 'pointer' && value === 'none' ) replacement = 'pointer-none'
211
+ if ( key === 'pointer' && value === 'coarse' ) replacement = 'pointer-coarse'
212
+ if ( key === 'pointer' && value === 'fine' ) replacement = 'pointer-fine'
213
+ if ( key === 'any-pointer' && value === 'none' ) replacement = 'any-pointer-none'
214
+ if ( key === 'any-pointer' && value === 'coarse' ) replacement = 'any-pointer-coarse'
215
+ if ( key === 'any-pointer' && value === 'fine' ) replacement = 'any-pointer-fine'
216
+
217
+ if ( key === 'scripting' && value === 'none' ) replacement = 'noscript'
218
+
219
+ if ( replacement ) {
220
+ changed = true
221
+ memcpy ( variant , designSystem . parseVariant ( replacement ) )
222
+ }
223
+ }
224
+ continue
225
+ }
226
+
149
227
let prefixedVariant : Variant | null = null
150
228
151
229
// Handling a child combinator. E.g.: `[&>[data-visible]]` => `*:data-visible`
0 commit comments