@@ -25,6 +25,7 @@ const input =
25
25
< div class ="uppercase: "> </ div >
26
26
< div class ="hover:font-bold "> </ div >
27
27
< div class ="content-['>'] "> </ div >
28
+ < div class ="[--y:theme(colors.blue.500)] ">
28
29
29
30
< script >
30
31
let classes01 = [ "text-[10px]" ]
@@ -43,7 +44,7 @@ const input =
43
44
let classes14 = [ "<div class='hover:test'>" ]
44
45
45
46
let obj = {
46
- uppercase : true
47
+ lowercase : true
47
48
}
48
49
</ script >
49
50
` + jsxExample
@@ -65,6 +66,7 @@ const includes = [
65
66
`fill-[#bada55]/50` ,
66
67
`px-1.5` ,
67
68
`uppercase` ,
69
+ `lowercase` ,
68
70
`hover:font-bold` ,
69
71
`text-sm` ,
70
72
`text-[10px]` ,
@@ -87,6 +89,7 @@ const includes = [
87
89
`content-['>']` ,
88
90
`hover:test` ,
89
91
`overflow-scroll` ,
92
+ `[--y:theme(colors.blue.500)]` ,
90
93
]
91
94
92
95
const excludes = [
@@ -109,3 +112,214 @@ test('The default extractor works as expected', async () => {
109
112
expect ( extractions ) . not . toContain ( str )
110
113
}
111
114
} )
115
+
116
+ // Scenarios:
117
+ // - In double quoted class attribute
118
+ // - In single quoted class attribute
119
+ // - Single-quoted as a variable
120
+ // - Double-quoted as a variable
121
+ // - Single-quoted as first array item
122
+ // - Double-quoted as first array item
123
+ // - Single-quoted as middle array item
124
+ // - Double-quoted as middle array item
125
+ // - Single-quoted as last array item
126
+ // - Double-quoted as last array item
127
+ // - Bare as an object key (with trailing `:`)
128
+ // - Quoted as an object key (with trailing `:`)
129
+ // - Within a template literal
130
+ // - Within a template literal directly before interpolation
131
+ // - Within a template literal directly after interpolation
132
+ // - JS: ${...}
133
+ // - PHP: {$...}
134
+ // - Ruby: #{...}
135
+ // - Within a string of HTML wrapped in escaped quotes
136
+
137
+ test ( 'basic utility classes' , async ( ) => {
138
+ const extractions = defaultExtractor ( `
139
+ <div class="text-center font-bold px-4 pointer-events-none"></div>
140
+ ` )
141
+
142
+ expect ( extractions ) . toContain ( 'text-center' )
143
+ expect ( extractions ) . toContain ( 'font-bold' )
144
+ expect ( extractions ) . toContain ( 'px-4' )
145
+ expect ( extractions ) . toContain ( 'pointer-events-none' )
146
+ } )
147
+
148
+ test ( 'modifiers with basic utilites' , async ( ) => {
149
+ const extractions = defaultExtractor ( `
150
+ <div class="hover:text-center hover:focus:font-bold"></div>
151
+ ` )
152
+
153
+ expect ( extractions ) . toContain ( 'hover:text-center' )
154
+ expect ( extractions ) . toContain ( 'hover:focus:font-bold' )
155
+ } )
156
+
157
+ test ( 'utilities with dot characters' , async ( ) => {
158
+ const extractions = defaultExtractor ( `
159
+ <div class="px-1.5 active:px-2.5 hover:focus:px-3.5"></div>
160
+ ` )
161
+
162
+ expect ( extractions ) . toContain ( 'px-1.5' )
163
+ expect ( extractions ) . toContain ( 'active:px-2.5' )
164
+ expect ( extractions ) . toContain ( 'hover:focus:px-3.5' )
165
+ } )
166
+
167
+ test ( 'basic utilities with color opacity modifier' , async ( ) => {
168
+ const extractions = defaultExtractor ( `
169
+ <div class="text-red-500/25 hover:text-red-500/50 hover:active:text-red-500/75"></div>
170
+ ` )
171
+
172
+ expect ( extractions ) . toContain ( 'text-red-500/25' )
173
+ expect ( extractions ) . toContain ( 'hover:text-red-500/50' )
174
+ expect ( extractions ) . toContain ( 'hover:active:text-red-500/75' )
175
+ } )
176
+
177
+ test ( 'basic arbitrary values' , async ( ) => {
178
+ const extractions = defaultExtractor ( `
179
+ <div class="px-[25px] hover:px-[40rem] hover:focus:px-[23vh]"></div>
180
+ ` )
181
+
182
+ expect ( extractions ) . toContain ( 'px-[25px]' )
183
+ expect ( extractions ) . toContain ( 'hover:px-[40rem]' )
184
+ expect ( extractions ) . toContain ( 'hover:focus:px-[23vh]' )
185
+ } )
186
+
187
+ test ( 'arbitrary values with color opacity modifier' , async ( ) => {
188
+ const extractions = defaultExtractor ( `
189
+ <div class="text-[#bada55]/25 hover:text-[#bada55]/50 hover:active:text-[#bada55]/75"></div>
190
+ ` )
191
+
192
+ expect ( extractions ) . toContain ( 'text-[#bada55]/25' )
193
+ expect ( extractions ) . toContain ( 'hover:text-[#bada55]/50' )
194
+ expect ( extractions ) . toContain ( 'hover:active:text-[#bada55]/75' )
195
+ } )
196
+
197
+ test ( 'arbitrary values with spaces' , async ( ) => {
198
+ const extractions = defaultExtractor ( `
199
+ <div class="grid-cols-[1fr_200px_3fr] md:grid-cols-[2fr_100px_1fr] open:lg:grid-cols-[3fr_300px_1fr]"></div>
200
+ ` )
201
+
202
+ expect ( extractions ) . toContain ( 'grid-cols-[1fr_200px_3fr]' )
203
+ expect ( extractions ) . toContain ( 'md:grid-cols-[2fr_100px_1fr]' )
204
+ expect ( extractions ) . toContain ( 'open:lg:grid-cols-[3fr_300px_1fr]' )
205
+ } )
206
+
207
+ test ( 'arbitrary values with css variables' , async ( ) => {
208
+ const extractions = defaultExtractor ( `
209
+ <div class="fill-[var(--my-color)] hover:fill-[var(--my-color-2)] hover:focus:fill-[var(--my-color-3)]"></div>
210
+ ` )
211
+
212
+ expect ( extractions ) . toContain ( 'fill-[var(--my-color)]' )
213
+ expect ( extractions ) . toContain ( 'hover:fill-[var(--my-color-2)]' )
214
+ expect ( extractions ) . toContain ( 'hover:focus:fill-[var(--my-color-3)]' )
215
+ } )
216
+
217
+ test ( 'arbitrary values with type hints' , async ( ) => {
218
+ const extractions = defaultExtractor ( `
219
+ <div class="text-[color:var(--my-color)] hover:text-[color:var(--my-color-2)] hover:focus:text-[color:var(--my-color-3)]"></div>
220
+ ` )
221
+
222
+ expect ( extractions ) . toContain ( 'text-[color:var(--my-color)]' )
223
+ expect ( extractions ) . toContain ( 'hover:text-[color:var(--my-color-2)]' )
224
+ expect ( extractions ) . toContain ( 'hover:focus:text-[color:var(--my-color-3)]' )
225
+ } )
226
+
227
+ test ( 'arbitrary values with single quotes' , async ( ) => {
228
+ const extractions = defaultExtractor ( `
229
+ <div class="content-['hello_world'] hover:content-['hello_world_2'] hover:focus:content-['hello_world_3']"></div>
230
+ ` )
231
+
232
+ expect ( extractions ) . toContain ( `content-['hello_world']` )
233
+ expect ( extractions ) . toContain ( `hover:content-['hello_world_2']` )
234
+ expect ( extractions ) . toContain ( `hover:focus:content-['hello_world_3']` )
235
+ } )
236
+
237
+ test ( 'arbitrary values with double quotes' , async ( ) => {
238
+ const extractions = defaultExtractor ( `
239
+ <div class='content-["hello_world"] hover:content-["hello_world_2"] hover:focus:content-["hello_world_3"]'></div>
240
+ ` )
241
+
242
+ expect ( extractions ) . toContain ( `content-["hello_world"]` )
243
+ expect ( extractions ) . toContain ( `hover:content-["hello_world_2"]` )
244
+ expect ( extractions ) . toContain ( `hover:focus:content-["hello_world_3"]` )
245
+ } )
246
+
247
+ test ( 'arbitrary values with some single quoted values' , async ( ) => {
248
+ const extractions = defaultExtractor ( `
249
+ <div class="font-['Open_Sans',_system-ui,_sans-serif] hover:font-['Proxima_Nova',_system-ui,_sans-serif] hover:focus:font-['Inter_var',_system-ui,_sans-serif]"></div>
250
+ ` )
251
+
252
+ expect ( extractions ) . toContain ( `font-['Open_Sans',_system-ui,_sans-serif]` )
253
+ expect ( extractions ) . toContain ( `hover:font-['Proxima_Nova',_system-ui,_sans-serif]` )
254
+ expect ( extractions ) . toContain ( `hover:focus:font-['Inter_var',_system-ui,_sans-serif]` )
255
+ } )
256
+
257
+ test ( 'arbitrary values with some double quoted values' , async ( ) => {
258
+ const extractions = defaultExtractor ( `
259
+ <div class='font-["Open_Sans",_system-ui,_sans-serif] hover:font-["Proxima_Nova",_system-ui,_sans-serif] hover:focus:font-["Inter_var",_system-ui,_sans-serif]'></div>
260
+ ` )
261
+
262
+ expect ( extractions ) . toContain ( `font-["Open_Sans",_system-ui,_sans-serif]` )
263
+ expect ( extractions ) . toContain ( `hover:font-["Proxima_Nova",_system-ui,_sans-serif]` )
264
+ expect ( extractions ) . toContain ( `hover:focus:font-["Inter_var",_system-ui,_sans-serif]` )
265
+ } )
266
+
267
+ test ( 'arbitrary values with escaped underscores' , async ( ) => {
268
+ const extractions = defaultExtractor ( `
269
+ <div class="content-['hello\\_world'] hover:content-['hello\\_world\\_2'] hover:focus:content-['hello\\_world\\_3']"></div>
270
+ ` )
271
+
272
+ expect ( extractions ) . toContain ( `content-['hello\\_world']` )
273
+ expect ( extractions ) . toContain ( `hover:content-['hello\\_world\\_2']` )
274
+ expect ( extractions ) . toContain ( `hover:focus:content-['hello\\_world\\_3']` )
275
+ } )
276
+
277
+ test ( 'basic utilities with arbitrary color opacity modifier' , async ( ) => {
278
+ const extractions = defaultExtractor ( `
279
+ <div class="text-red-500/[.25] hover:text-red-500/[.5] hover:active:text-red-500/[.75]"></div>
280
+ ` )
281
+
282
+ expect ( extractions ) . toContain ( 'text-red-500/[.25]' )
283
+ expect ( extractions ) . toContain ( 'hover:text-red-500/[.5]' )
284
+ expect ( extractions ) . toContain ( 'hover:active:text-red-500/[.75]' )
285
+ } )
286
+
287
+ test ( 'arbitrary values with arbitrary color opacity modifier' , async ( ) => {
288
+ const extractions = defaultExtractor ( `
289
+ <div class="text-[#bada55]/[.25] hover:text-[#bada55]/[.5] hover:active:text-[#bada55]/[.75]"></div>
290
+ ` )
291
+
292
+ expect ( extractions ) . toContain ( 'text-[#bada55]/[.25]' )
293
+ expect ( extractions ) . toContain ( 'hover:text-[#bada55]/[.5]' )
294
+ expect ( extractions ) . toContain ( 'hover:active:text-[#bada55]/[.75]' )
295
+ } )
296
+
297
+ test ( 'arbitrary values with angle brackets' , async ( ) => {
298
+ const extractions = defaultExtractor ( `
299
+ <div class="content-[>] hover:content-[<] hover:focus:content-[>]"></div>
300
+ ` )
301
+
302
+ expect ( extractions ) . toContain ( `content-[>]` )
303
+ expect ( extractions ) . toContain ( `hover:content-[<]` )
304
+ expect ( extractions ) . toContain ( `hover:focus:content-[>]` )
305
+ } )
306
+
307
+ test ( 'arbitrary values with angle brackets in single quotes' , async ( ) => {
308
+ const extractions = defaultExtractor ( `
309
+ <div class="content-['>'] hover:content-['<'] hover:focus:content-['>']"></div>
310
+ ` )
311
+
312
+ expect ( extractions ) . toContain ( `content-['>']` )
313
+ expect ( extractions ) . toContain ( `hover:content-['<']` )
314
+ expect ( extractions ) . toContain ( `hover:focus:content-['>']` )
315
+ } )
316
+
317
+ test ( 'arbitrary values with angle brackets in double quotes' , async ( ) => {
318
+ const extractions = defaultExtractor ( `
319
+ <div class="content-[">"] hover:content-["<"] hover:focus:content-[">"]"></div>
320
+ ` )
321
+
322
+ expect ( extractions ) . toContain ( `content-[">"]` )
323
+ expect ( extractions ) . toContain ( `hover:content-["<"]` )
324
+ expect ( extractions ) . toContain ( `hover:focus:content-[">"]` )
325
+ } )
0 commit comments