@@ -297,6 +297,11 @@ pub struct SortKey {
297297 /// This is used to properly sort compound variants like peer-hover vs peer-focus
298298 pub variant_chain : Vec < VariantInfo > ,
299299
300+ /// Arbitrary variant selectors for tiebreaking when variant_order is equal
301+ /// e.g., for `[&.x]:block` this would be `["[&.x]"]`
302+ /// Used to sort different arbitrary variants lexicographically (with `_` decoded as space)
303+ pub arbitrary_variants : Vec < compact_str:: CompactString > ,
304+
300305 /// Property indices from PROPERTY_ORDER (lower = earlier)
301306 /// When utilities have multiple properties (e.g., rounded-t), ALL property indices
302307 /// are stored and compared in order for proper tiebreaking.
@@ -619,19 +624,53 @@ impl Ord for SortKey {
619624 ( false , true ) => return Ordering :: Greater , // Variant after base class
620625 ( true , true ) => { } // Both base classes, continue to property comparison
621626 ( false , false ) => {
622- // Both have variants - compare by variant_order
627+ // Both have variants - continue with comparison below
628+ }
629+ }
630+
631+ // Bit 63 indicates presence of arbitrary variants
632+ const ARBITRARY_BIT : u128 = 1u128 << 63 ;
633+ let self_has_arbitrary = self . variant_order & ARBITRARY_BIT != 0 ;
634+ let other_has_arbitrary = other. variant_order & ARBITRARY_BIT != 0 ;
635+
636+ // 2. Compare by arbitrary variant presence and selectors
637+ // Classes without arbitrary variants sort BEFORE classes with arbitrary variants
638+ // When both have arbitrary, compare selectors FIRST, then known variant bits
639+ match ( self_has_arbitrary, other_has_arbitrary) {
640+ ( false , true ) => return Ordering :: Less , // No arbitrary before arbitrary
641+ ( true , false ) => return Ordering :: Greater ,
642+ ( true , true ) => {
643+ // Both have arbitrary variants - compare selectors FIRST
644+ let decode = |s : & str | s. replace ( '_' , " " ) ;
645+ let a: Vec < _ > = self . arbitrary_variants . iter ( ) . map ( |s| decode ( s) ) . collect ( ) ;
646+ let b: Vec < _ > = other. arbitrary_variants . iter ( ) . map ( |s| decode ( s) ) . collect ( ) ;
647+ match a. cmp ( & b) {
648+ Ordering :: Equal => {
649+ // Same arbitrary selectors - compare known variant bits
650+ // (mask out the arbitrary bit for comparison)
651+ let self_known = self . variant_order & !ARBITRARY_BIT ;
652+ let other_known = other. variant_order & !ARBITRARY_BIT ;
653+ if self_known != other_known {
654+ return self_known. cmp ( & other_known) ;
655+ }
656+ // Fall through to fine-grained comparison
657+ }
658+ other => return other,
659+ }
660+ }
661+ ( false , false ) => {
662+ // Neither has arbitrary - compare by known variant bits
663+ if self . variant_order != other. variant_order {
664+ return self . variant_order . cmp ( & other. variant_order ) ;
665+ }
666+ // Fall through to fine-grained comparison
623667 }
624668 }
625669
626- // 2. Compare by variant order (bitwise OR of all variant indices)
627- // This matches Tailwind's algorithm exactly - variant_order comes FIRST
628- // When variant_order is equal, fall through to fine-grained variant chain comparison
629- self . variant_order
630- . cmp ( & other. variant_order )
631- // 3. Fine-grained recursive variant chain comparison
632- // When coarse variant_order ties, compare the actual variant chains
633- // This handles multi-level variants like focus:dark: vs dark:focus:
634- . then_with ( || compare_variant_lists ( & self . variant_chain , & other. variant_chain ) )
670+ // 3. Fine-grained recursive variant chain comparison
671+ // When coarse variant_order ties, compare the actual variant chains
672+ // This handles multi-level variants like focus:dark: vs dark:focus:
673+ compare_variant_lists ( & self . variant_chain , & other. variant_chain )
635674 // Then compare by property indices - compare ALL properties in order
636675 // This is crucial for utilities like rounded-t vs rounded-l that tie on first property
637676 . then_with ( || {
@@ -903,6 +942,15 @@ impl PatternSorter {
903942 // Parse variants into structured form for recursive comparison
904943 let variant_chain = parse_variants ( & parsed. variants ) ;
905944
945+ // Extract arbitrary variants for lexicographic tiebreaking
946+ // These are variants that start with '[' (e.g., [&.htmx-request], [&>*])
947+ let arbitrary_variants: Vec < compact_str:: CompactString > = parsed
948+ . variants
949+ . iter ( )
950+ . filter ( |v| v. starts_with ( '[' ) )
951+ . map ( |v| compact_str:: CompactString :: new ( * v) )
952+ . collect ( ) ;
953+
906954 // Get the CSS properties this utility generates
907955 let properties = parsed. get_properties ( ) ?;
908956
@@ -940,6 +988,7 @@ impl PatternSorter {
940988 Some ( SortKey {
941989 variant_order,
942990 variant_chain,
991+ arbitrary_variants,
943992 property_indices,
944993 numeric_value,
945994 is_negative,
@@ -1131,6 +1180,7 @@ mod tests {
11311180 let key1 = SortKey {
11321181 variant_order : 0 ,
11331182 variant_chain : vec ! [ ] ,
1183+ arbitrary_variants : vec ! [ ] ,
11341184 property_indices : vec ! [ 100 ] ,
11351185 numeric_value : None ,
11361186 is_negative : false ,
@@ -1142,6 +1192,7 @@ mod tests {
11421192 let key2 = SortKey {
11431193 variant_order : 1 ,
11441194 variant_chain : parse_variants ( & [ "md" ] ) ,
1195+ arbitrary_variants : vec ! [ ] ,
11451196 property_indices : vec ! [ 100 ] ,
11461197 numeric_value : None ,
11471198 is_negative : false ,
@@ -1159,6 +1210,7 @@ mod tests {
11591210 let key1 = SortKey {
11601211 variant_order : 0 ,
11611212 variant_chain : vec ! [ ] ,
1213+ arbitrary_variants : vec ! [ ] ,
11621214 property_indices : vec ! [ 50 ] ,
11631215 numeric_value : None ,
11641216 is_negative : false ,
@@ -1170,6 +1222,7 @@ mod tests {
11701222 let key2 = SortKey {
11711223 variant_order : 0 ,
11721224 variant_chain : vec ! [ ] ,
1225+ arbitrary_variants : vec ! [ ] ,
11731226 property_indices : vec ! [ 100 ] ,
11741227 numeric_value : None ,
11751228 is_negative : false ,
@@ -1187,6 +1240,7 @@ mod tests {
11871240 let key1 = SortKey {
11881241 variant_order : 0 ,
11891242 variant_chain : vec ! [ ] ,
1243+ arbitrary_variants : vec ! [ ] ,
11901244 property_indices : vec ! [ 100 ] ,
11911245 numeric_value : None ,
11921246 is_negative : false ,
@@ -1198,6 +1252,7 @@ mod tests {
11981252 let key2 = SortKey {
11991253 variant_order : 0 ,
12001254 variant_chain : vec ! [ ] ,
1255+ arbitrary_variants : vec ! [ ] ,
12011256 property_indices : vec ! [ 100 ] ,
12021257 numeric_value : None ,
12031258 is_negative : false ,
@@ -1215,6 +1270,7 @@ mod tests {
12151270 let key1 = SortKey {
12161271 variant_order : 0 ,
12171272 variant_chain : vec ! [ ] ,
1273+ arbitrary_variants : vec ! [ ] ,
12181274 property_indices : vec ! [ 100 ] ,
12191275 numeric_value : None ,
12201276 is_negative : false ,
@@ -1226,6 +1282,7 @@ mod tests {
12261282 let key2 = SortKey {
12271283 variant_order : 0 ,
12281284 variant_chain : vec ! [ ] ,
1285+ arbitrary_variants : vec ! [ ] ,
12291286 property_indices : vec ! [ 100 ] ,
12301287 numeric_value : None ,
12311288 is_negative : false ,
@@ -1358,6 +1415,7 @@ mod tests {
13581415 let key1 = SortKey {
13591416 variant_order : 0 ,
13601417 variant_chain : vec ! [ ] ,
1418+ arbitrary_variants : vec ! [ ] ,
13611419 property_indices : vec ! [ 100 ] ,
13621420 numeric_value : Some ( 4.0 ) ,
13631421 is_negative : false ,
@@ -1368,6 +1426,7 @@ mod tests {
13681426 let key2 = SortKey {
13691427 variant_order : 0 ,
13701428 variant_chain : vec ! [ ] ,
1429+ arbitrary_variants : vec ! [ ] ,
13711430 property_indices : vec ! [ 100 ] ,
13721431 numeric_value : Some ( 8.0 ) ,
13731432 is_negative : false ,
@@ -1381,6 +1440,7 @@ mod tests {
13811440 let key3 = SortKey {
13821441 variant_order : 0 ,
13831442 variant_chain : vec ! [ ] ,
1443+ arbitrary_variants : vec ! [ ] ,
13841444 property_indices : vec ! [ 100 ] ,
13851445 numeric_value : Some ( 50.0 ) ,
13861446 is_negative : false ,
@@ -1391,6 +1451,7 @@ mod tests {
13911451 let key4 = SortKey {
13921452 variant_order : 0 ,
13931453 variant_chain : vec ! [ ] ,
1454+ arbitrary_variants : vec ! [ ] ,
13941455 property_indices : vec ! [ 100 ] ,
13951456 numeric_value : Some ( 110.0 ) ,
13961457 is_negative : false ,
@@ -1404,6 +1465,7 @@ mod tests {
14041465 let key5 = SortKey {
14051466 variant_order : 0 ,
14061467 variant_chain : vec ! [ ] ,
1468+ arbitrary_variants : vec ! [ ] ,
14071469 property_indices : vec ! [ 100 ] ,
14081470 numeric_value : Some ( 4.0 ) ,
14091471 is_negative : false ,
@@ -1414,6 +1476,7 @@ mod tests {
14141476 let key6 = SortKey {
14151477 variant_order : 0 ,
14161478 variant_chain : vec ! [ ] ,
1479+ arbitrary_variants : vec ! [ ] ,
14171480 property_indices : vec ! [ 100 ] ,
14181481 numeric_value : None ,
14191482 is_negative : false ,
0 commit comments