1- use crate :: StyleSelector :: { Dual , Media , Postfix , Prefix } ;
21use once_cell:: sync:: Lazy ;
32use regex:: Regex ;
43use serde:: { Deserialize , Serialize } ;
@@ -10,20 +9,18 @@ use std::sync::Mutex;
109
1110static SELECTOR_ORDER_MAP : Lazy < HashMap < String , u8 > > = Lazy :: new ( || {
1211 let mut map = HashMap :: new ( ) ;
13- map. insert ( "disabled" . to_string ( ) , 5 ) ;
14- map. insert ( "selected" . to_string ( ) , 4 ) ;
15- map. insert ( "active" . to_string ( ) , 3 ) ;
16- map. insert ( "focus" . to_string ( ) , 2 ) ;
17- map. insert ( "hover" . to_string ( ) , 1 ) ;
12+ map. insert ( "&: disabled" . to_string ( ) , 5 ) ;
13+ map. insert ( "&: selected" . to_string ( ) , 4 ) ;
14+ map. insert ( "&: active" . to_string ( ) , 3 ) ;
15+ map. insert ( "&: focus" . to_string ( ) , 2 ) ;
16+ map. insert ( "&: hover" . to_string ( ) , 1 ) ;
1817 map
1918} ) ;
2019
2120#[ derive( Debug , PartialEq , Clone , Hash , Eq , Serialize , Deserialize ) ]
2221pub enum StyleSelector {
23- Postfix ( String ) ,
24- Prefix ( String ) ,
2522 Media ( String ) ,
26- Dual ( String , String ) ,
23+ Selector ( String ) ,
2724}
2825
2926impl PartialOrd for StyleSelector {
@@ -35,77 +32,72 @@ impl PartialOrd for StyleSelector {
3532impl Ord for StyleSelector {
3633 fn cmp ( & self , other : & Self ) -> Ordering {
3734 match ( self , other) {
38- ( Media ( a) , Media ( b) ) => a. cmp ( b) ,
39- ( Media ( _) , _) => Ordering :: Less ,
40- ( _, Media ( _) ) => Ordering :: Greater ,
41- ( Postfix ( a) , Postfix ( b) ) => SELECTOR_ORDER_MAP
35+ ( StyleSelector :: Media ( a) , StyleSelector :: Media ( b) ) => a. cmp ( b) ,
36+ ( StyleSelector :: Selector ( a) , StyleSelector :: Selector ( b) ) => SELECTOR_ORDER_MAP
4237 . get ( a)
43- . unwrap_or ( & 0 )
44- . cmp ( SELECTOR_ORDER_MAP . get ( b) . unwrap_or ( & 0 ) ) ,
45- ( Prefix ( a) , Prefix ( b) ) => a. cmp ( b) ,
46- ( Dual ( p1, a) , Dual ( p2, b) ) => match p1. cmp ( p2) {
47- Ordering :: Equal => SELECTOR_ORDER_MAP
48- . get ( a)
49- . unwrap_or ( & 0 )
50- . cmp ( SELECTOR_ORDER_MAP . get ( b) . unwrap_or ( & 0 ) ) ,
51- x => x,
52- } ,
53- ( Postfix ( _) , _) => Ordering :: Less ,
54- ( Prefix ( _) , Postfix ( _) ) => Ordering :: Greater ,
55- ( Prefix ( _) , Dual ( _, _) ) => Ordering :: Less ,
56- ( Dual ( _, _) , _) => Ordering :: Greater ,
38+ . unwrap_or ( if a. starts_with ( "&" ) { & 0 } else { & 99 } )
39+ . cmp ( SELECTOR_ORDER_MAP . get ( b) . unwrap_or ( if b. starts_with ( "&" ) {
40+ & 0
41+ } else {
42+ & 99
43+ } ) ) ,
44+ ( StyleSelector :: Media ( _) , StyleSelector :: Selector ( _) ) => Ordering :: Greater ,
45+ ( StyleSelector :: Selector ( _) , StyleSelector :: Media ( _) ) => Ordering :: Less ,
5746 }
5847 }
5948}
6049
6150impl From < & str > for StyleSelector {
6251 fn from ( value : & str ) -> Self {
6352 if value. contains ( "&" ) {
64- let t: Vec < _ > = value. split ( "&" ) . collect ( ) ;
65- if let Prefix ( v) = t[ 0 ] . into ( ) {
66- if t[ 1 ] . is_empty ( ) {
67- Prefix ( v)
68- } else {
69- Dual ( v, t[ 1 ] . to_string ( ) )
70- }
71- } else {
72- Postfix ( t[ 1 ] . to_string ( ) )
73- }
53+ StyleSelector :: Selector ( value. to_string ( ) )
7454 } else if let Some ( s) = value. strip_prefix ( "group" ) {
7555 let post = to_kebab_case ( s) ;
76- Prefix ( format ! (
77- "{}{}{}" ,
56+ StyleSelector :: Selector ( format ! (
57+ "{}{}{} & " ,
7858 "*[role=group]" ,
7959 get_selector_separator( & post) ,
8060 post
8161 ) )
8262 } else if let Some ( s) = value. strip_prefix ( "theme" ) {
8363 // first character should lower case
84- Prefix ( format ! (
85- ":root[data-theme={}{}]" ,
64+ StyleSelector :: Selector ( format ! (
65+ ":root[data-theme={}{}] & " ,
8666 s. chars( ) . next( ) . unwrap( ) . to_ascii_lowercase( ) ,
8767 & s[ 1 ..]
8868 ) )
8969 } else if value == "print" {
90- Media ( "print" . to_string ( ) )
70+ StyleSelector :: Media ( "print" . to_string ( ) )
9171 } else if value. ends_with ( " " ) {
92- Prefix ( value. trim ( ) . to_string ( ) )
72+ StyleSelector :: Selector ( format ! ( "{} &" , value. trim( ) ) )
9373 } else {
94- Postfix ( to_kebab_case ( value) )
74+ let post = to_kebab_case ( value) ;
75+
76+ StyleSelector :: Selector ( format ! ( "&{}{}" , get_selector_separator( & post) , post) )
9577 }
9678 }
9779}
9880
81+ impl From < [ & str ; 2 ] > for StyleSelector {
82+ fn from ( value : [ & str ; 2 ] ) -> Self {
83+ let post = to_kebab_case ( value[ 1 ] ) ;
84+ StyleSelector :: Selector ( format ! (
85+ "{}{}{}" ,
86+ StyleSelector :: from( value[ 0 ] ) ,
87+ get_selector_separator( & post) ,
88+ post
89+ ) )
90+ }
91+ }
92+
9993impl Display for StyleSelector {
10094 fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
10195 write ! (
10296 f,
10397 "{}" ,
10498 match self {
105- Postfix ( value) => format!( "-{}" , value) ,
106- Prefix ( value) => format!( "-{}-" , value) ,
107- Dual ( prefix, postfix) => format!( "-{}-{}" , prefix, postfix) ,
108- Media ( value) => format!( "@{}" , value) ,
99+ StyleSelector :: Selector ( value) => value. to_string( ) ,
100+ StyleSelector :: Media ( value) => format!( "@{}" , value) ,
109101 }
110102 )
111103 }
@@ -114,21 +106,8 @@ impl Display for StyleSelector {
114106pub fn merge_selector ( class_name : & str , selector : Option < & StyleSelector > ) -> String {
115107 if let Some ( selector) = selector {
116108 match selector {
117- Postfix ( postfix) => format ! (
118- ".{}{}{}" ,
119- class_name,
120- get_selector_separator( postfix) ,
121- postfix
122- ) ,
123- Prefix ( prefix) => format ! ( "{} .{}" , prefix, class_name) ,
124- Dual ( prefix, postfix) => format ! (
125- "{} .{}{}{}" ,
126- prefix,
127- class_name,
128- get_selector_separator( postfix) ,
129- postfix
130- ) ,
131- Media ( _) => format ! ( ".{}" , class_name) ,
109+ StyleSelector :: Selector ( value) => value. replace ( "&" , & format ! ( ".{}" , class_name) ) ,
110+ StyleSelector :: Media ( _) => format ! ( ".{}" , class_name) ,
132111 }
133112 } else {
134113 format ! ( ".{}" , class_name)
@@ -660,43 +639,40 @@ mod tests {
660639
661640 #[ test]
662641 fn test_style_selector ( ) {
663- assert_eq ! ( StyleSelector :: from( "hover" ) , Postfix ( "hover" . to_string( ) ) ) ;
642+ assert_eq ! (
643+ StyleSelector :: from( "hover" ) ,
644+ StyleSelector :: Selector ( "&:hover" . to_string( ) )
645+ ) ;
664646 assert_eq ! (
665647 StyleSelector :: from( "focusVisible" ) ,
666- Postfix ( " focus-visible". to_string( ) )
648+ StyleSelector :: Selector ( "&: focus-visible". to_string( ) )
667649 ) ;
668650 assert_eq ! (
669651 StyleSelector :: from( "groupHover" ) ,
670- Prefix ( "*[role=group]:hover" . to_string( ) )
652+ StyleSelector :: Selector ( "*[role=group]:hover & " . to_string( ) )
671653 ) ;
672654 assert_eq ! (
673655 StyleSelector :: from( "groupFocusVisible" ) ,
674- Prefix ( "*[role=group]:focus-visible" . to_string( ) )
656+ StyleSelector :: Selector ( "*[role=group]:focus-visible & " . to_string( ) )
675657 ) ;
676658 assert_eq ! (
677659 StyleSelector :: from( "group1" ) ,
678- Prefix ( "*[role=group]:1" . to_string( ) )
660+ StyleSelector :: Selector ( "*[role=group]:1 & " . to_string( ) )
679661 ) ;
680662
681663 assert_eq ! (
682- StyleSelector :: from( "themeDark&placeholder" ) ,
683- Dual (
684- ":root[data-theme=dark]" . to_string( ) ,
685- "placeholder" . to_string( )
686- )
664+ StyleSelector :: from( [ "themeDark" , "placeholder" ] ) ,
665+ StyleSelector :: Selector ( ":root[data-theme=dark] &::placeholder" . to_string( ) )
687666 ) ;
688667
689- assert_eq ! ( Prefix ( ".cls" . to_string( ) ) . to_string( ) , "-.cls-" ) ;
690- assert_eq ! ( Postfix ( ".cls" . to_string( ) ) . to_string( ) , "-.cls" ) ;
691-
692668 assert_eq ! (
693669 StyleSelector :: from( "themeLight" ) ,
694- Prefix ( ":root[data-theme=light]" . to_string( ) )
670+ StyleSelector :: Selector ( ":root[data-theme=light] & " . to_string( ) )
695671 ) ;
696672
697673 assert_eq ! (
698674 StyleSelector :: from( "*[aria=disabled='true'] &:hover" ) ,
699- Dual ( "*[aria=disabled='true']" . to_string ( ) , " :hover". to_string( ) )
675+ StyleSelector :: Selector ( "*[aria=disabled='true'] & :hover" . to_string( ) )
700676 ) ;
701677 }
702678
@@ -714,20 +690,24 @@ mod tests {
714690 assert_eq ! (
715691 merge_selector(
716692 "cls" ,
717- Some ( & Prefix ( ":root[data-theme=dark]:hover" . to_string( ) , ) ) ,
693+ Some ( & StyleSelector :: Selector (
694+ ":root[data-theme=dark]:hover &" . to_string( ) ,
695+ ) ) ,
718696 ) ,
719697 ":root[data-theme=dark]:hover .cls"
720698 ) ;
721699 assert_eq ! (
722700 merge_selector(
723701 "cls" ,
724- Some ( & Prefix ( ":root[data-theme=dark]::placeholder" . to_string( ) ) ) ,
702+ Some ( & StyleSelector :: Selector (
703+ ":root[data-theme=dark]::placeholder &" . to_string( )
704+ ) ) ,
725705 ) ,
726706 ":root[data-theme=dark]::placeholder .cls"
727707 ) ;
728708
729709 assert_eq ! (
730- merge_selector( "cls" , Some ( & "themeDark& hover" . into( ) ) , ) ,
710+ merge_selector( "cls" , Some ( & [ "themeDark" , " hover"] . into( ) ) , ) ,
731711 ":root[data-theme=dark] .cls:hover"
732712 ) ;
733713 }
0 commit comments