@@ -108,6 +108,75 @@ impl PreProcessor for Clojure {
108
108
}
109
109
}
110
110
111
+ // Handle quote with a list, e.g.: `'(…)`
112
+ // and with a vector, e.g.: `'[…]`
113
+ b'\'' if matches ! ( cursor. next, b'[' | b'(' ) => {
114
+ result[ cursor. pos ] = b' ' ;
115
+ cursor. advance ( ) ;
116
+ result[ cursor. pos ] = b' ' ;
117
+ let end = match cursor. curr {
118
+ b'[' => b']' ,
119
+ b'(' => b')' ,
120
+ _ => unreachable ! ( ) ,
121
+ } ;
122
+
123
+ // Consume until the closing `]`
124
+ while cursor. pos < len {
125
+ match cursor. curr {
126
+ x if x == end => {
127
+ result[ cursor. pos ] = b' ' ;
128
+ break ;
129
+ }
130
+
131
+ // Consume strings as-is
132
+ b'"' => {
133
+ result[ cursor. pos ] = b' ' ;
134
+ cursor. advance ( ) ;
135
+
136
+ while cursor. pos < len {
137
+ match cursor. curr {
138
+ // Escaped character, skip ahead to the next character
139
+ b'\\' => cursor. advance_twice ( ) ,
140
+
141
+ // End of the string
142
+ b'"' => {
143
+ result[ cursor. pos ] = b' ' ;
144
+ break ;
145
+ }
146
+
147
+ // Everything else is valid
148
+ _ => cursor. advance ( ) ,
149
+ } ;
150
+ }
151
+ }
152
+ _ => { }
153
+ } ;
154
+
155
+ cursor. advance ( ) ;
156
+ }
157
+ }
158
+
159
+ // Handle quote with a keyword, e.g.: `'bg-white`
160
+ b'\'' if !cursor. next . is_ascii_whitespace ( ) => {
161
+ result[ cursor. pos ] = b' ' ;
162
+ cursor. advance ( ) ;
163
+
164
+ while cursor. pos < len {
165
+ match cursor. curr {
166
+ // End of keyword.
167
+ _ if !is_keyword_character ( cursor. curr ) => {
168
+ result[ cursor. pos ] = b' ' ;
169
+ break ;
170
+ }
171
+
172
+ // Consume everything else.
173
+ _ => { }
174
+ } ;
175
+
176
+ cursor. advance ( ) ;
177
+ }
178
+ }
179
+
111
180
// Aggressively discard everything else, reducing false positives and preventing
112
181
// characters surrounding keywords from producing false negatives.
113
182
// E.g.:
@@ -281,4 +350,87 @@ mod tests {
281
350
vec ! [ "py-5" , "flex" , "pr-1.5" , "bg-white" , "bg-black" ] ,
282
351
) ;
283
352
}
353
+
354
+ // https://github.com/tailwindlabs/tailwindcss/issues/18882
355
+ #[ test]
356
+ fn test_extract_from_symbol_list ( ) {
357
+ let input = r#"
358
+ [:div {:class '[z-1 z-2
359
+ z-3 z-4]}]
360
+ "# ;
361
+ Clojure :: test_extract_contains ( input, vec ! [ "z-1" , "z-2" , "z-3" , "z-4" ] ) ;
362
+
363
+ // https://github.com/tailwindlabs/tailwindcss/pull/18345#issuecomment-3253403847
364
+ let input = r#"
365
+ (def hl-class-names '[ring ring-blue-500])
366
+
367
+ [:div
368
+ {:class (cond-> '[input w-full]
369
+ textarea? (conj 'textarea)
370
+ (seq errors) (concat '[border-red-500 bg-red-100])
371
+ highlight? (concat hl-class-names))}]
372
+ "# ;
373
+ Clojure :: test_extract_contains (
374
+ input,
375
+ vec ! [
376
+ "ring" ,
377
+ "ring-blue-500" ,
378
+ "input" ,
379
+ "w-full" ,
380
+ "textarea" ,
381
+ "border-red-500" ,
382
+ "bg-red-100" ,
383
+ ] ,
384
+ ) ;
385
+
386
+ let input = r#"
387
+ [:div
388
+ {:class '[h-100 lg:h-200 max-w-32 mx-auto py-60
389
+ flex flex-col justify-end items-center
390
+ lg:flex-row lg:justify-between
391
+ bg-cover bg-center bg-no-repeat rounded-3xl overflow-hidden
392
+ font-semibold text-gray-900]}]
393
+ "# ;
394
+ Clojure :: test_extract_contains (
395
+ input,
396
+ vec ! [
397
+ "h-100" ,
398
+ "lg:h-200" ,
399
+ "max-w-32" ,
400
+ "mx-auto" ,
401
+ "py-60" ,
402
+ "flex" ,
403
+ "flex-col" ,
404
+ "justify-end" ,
405
+ "items-center" ,
406
+ "lg:flex-row" ,
407
+ "lg:justify-between" ,
408
+ "bg-cover" ,
409
+ "bg-center" ,
410
+ "bg-no-repeat" ,
411
+ "rounded-3xl" ,
412
+ "overflow-hidden" ,
413
+ "font-semibold" ,
414
+ "text-gray-900" ,
415
+ ] ,
416
+ ) ;
417
+
418
+ // `/` is invalid and requires explicit quoting
419
+ let input = r#"
420
+ '[p-32 "text-black/50"]
421
+ "# ;
422
+ Clojure :: test_extract_contains ( input, vec ! [ "p-32" , "text-black/50" ] ) ;
423
+
424
+ // `[…]` is invalid and requires explicit quoting
425
+ let input = r#"
426
+ (print '[ring ring-blue-500 "bg-[#0088cc]"])
427
+ "# ;
428
+ Clojure :: test_extract_contains ( input, vec ! [ "ring" , "ring-blue-500" , "bg-[#0088cc]" ] ) ;
429
+
430
+ // `'(…)` looks similar to `[…]` but uses parentheses instead of brackets
431
+ let input = r#"
432
+ (print '(ring ring-blue-500 "bg-[#0088cc]"))
433
+ "# ;
434
+ Clojure :: test_extract_contains ( input, vec ! [ "ring" , "ring-blue-500" , "bg-[#0088cc]" ] ) ;
435
+ }
284
436
}
0 commit comments