11use crate :: {
22 COLOR_HASH , F_SPACE_RE , ZERO_RE ,
3- constant:: { DOT_ZERO_RE , F_DOT_RE } ,
3+ constant:: { DOT_ZERO_RE , F_DOT_RE , INNER_TRIM_RE , ZERO_PERCENT_FUNCTION } ,
44} ;
55
66pub fn optimize_value ( value : & str ) -> String {
77 let mut ret = value. trim ( ) . to_string ( ) ;
8+ ret = INNER_TRIM_RE . replace_all ( & ret, "(${1})" ) . to_string ( ) ;
89 if ret. contains ( "," ) {
910 ret = F_SPACE_RE . replace_all ( & ret, "," ) . trim ( ) . to_string ( ) ;
1011 }
@@ -17,6 +18,31 @@ pub fn optimize_value(value: &str) -> String {
1718 ret = DOT_ZERO_RE . replace_all ( & ret, "${1}0${2}" ) . to_string ( ) ;
1819 ret = F_DOT_RE . replace_all ( & ret, "${1}.${2}" ) . to_string ( ) ;
1920 ret = ZERO_RE . replace_all ( & ret, "${1}0" ) . to_string ( ) ;
21+
22+ for f in ZERO_PERCENT_FUNCTION . iter ( ) {
23+ if ret. contains ( f) {
24+ let index = ret. find ( f) . unwrap ( ) + f. len ( ) ;
25+ let mut zero_idx = vec ! [ ] ;
26+ let mut depth = 0 ;
27+ for i in index..ret. len ( ) {
28+ if ret[ i..i + 1 ] . eq ( "(" ) {
29+ depth += 1 ;
30+ } else if ret[ i..i + 1 ] . eq ( ")" ) {
31+ depth -= 1 ;
32+ } else if ret[ i..i + 1 ] . eq ( "0" )
33+ && !ret[ i - 1 ..i] . chars ( ) . next ( ) . unwrap ( ) . is_ascii_digit ( )
34+ && ( ret. len ( ) == i + 1
35+ || !ret[ i + 1 ..i + 2 ] . chars ( ) . next ( ) . unwrap ( ) . is_ascii_digit ( ) )
36+ && depth == 0
37+ {
38+ zero_idx. push ( i) ;
39+ }
40+ }
41+ for i in zero_idx. iter ( ) . rev ( ) {
42+ ret = ret[ ..* i] . to_string ( ) + "0%" + & ret[ * i + 1 ..] ;
43+ }
44+ }
45+ }
2046 }
2147 // remove ; from dynamic value
2248 for str_symbol in [ "" , "`" , "\" " , "'" ] {
@@ -34,6 +60,27 @@ pub fn optimize_value(value: &str) -> String {
3460 ) ;
3561 }
3662 }
63+
64+ if ret. contains ( "(" ) || ret. contains ( ")" ) {
65+ let mut depth = 0 ;
66+ for i in 0 ..ret. len ( ) {
67+ if ret[ i..i + 1 ] . eq ( "(" ) {
68+ depth += 1 ;
69+ } else if ret[ i..i + 1 ] . eq ( ")" ) {
70+ depth -= 1 ;
71+ }
72+ }
73+ if depth < 0 {
74+ for _ in 0 ..( -depth) {
75+ ret. insert ( 0 , '(' ) ;
76+ }
77+ }
78+ if depth > 0 {
79+ for _ in 0 ..depth {
80+ ret. push ( ')' ) ;
81+ }
82+ }
83+ }
3784 ret
3885}
3986
@@ -99,6 +146,19 @@ mod tests {
99146 #[ case( "translate(-0px, 0px)" , "translate(0,0)" ) ]
100147 #[ case( "translate(0px, 0px)" , "translate(0,0)" ) ]
101148 #[ case( "translate(10px, 0px)" , "translate(10px,0)" ) ]
149+ #[ case( "translate( 10px , 0px )" , "translate(10px,0)" ) ]
150+ #[ case( "translate( 0px , 0px )" , "translate(0,0)" ) ]
151+ #[ case( " translate( 0px , 0px ) " , "translate(0,0)" ) ]
152+ #[ case( "clamp(0, 10px, 10px)" , "clamp(0%,10px,10px)" ) ]
153+ #[ case( "clamp(10px, 0, 10px)" , "clamp(10px,0%,10px)" ) ]
154+ #[ case( "clamp(10px, 10px, 0)" , "clamp(10px,10px,0%)" ) ]
155+ #[ case( "clamp(0px, 10px, 0px)" , "clamp(0%,10px,0%)" ) ]
156+ #[ case( "min(0, 10px)" , "min(0%,10px)" ) ]
157+ #[ case( "max(0, 10px)" , "max(0%,10px)" ) ]
158+ #[ case( "min(10px, 0)" , "min(10px,0%)" ) ]
159+ #[ case( "max(10px, 0)" , "max(10px,0%)" ) ]
160+ #[ case( "max(some(0), 0)" , "max(some(0),0%)" ) ]
161+ #[ case( "translate(0, min(0, 10px))" , "translate(0,min(0%,10px))" ) ]
102162 #[ case( "\" red\" " , "\" red\" " ) ]
103163 #[ case( "'red'" , "'red'" ) ]
104164 #[ case( "`red`" , "`red`" ) ]
@@ -110,6 +170,11 @@ mod tests {
110170 #[ case( "('red;')" , "('red')" ) ]
111171 #[ case( "('red') + 'blue;'" , "('red') + 'blue'" ) ]
112172 #[ case( "translateX(0px) translateY(0px)" , "translateX(0) translateY(0)" ) ]
173+ // recovery case
174+ #[ case( "max(10px, 0" , "max(10px,0%)" ) ]
175+ #[ case( "max(10px, calc(0" , "max(10px,calc(0%))" ) ]
176+ #[ case( "max(10px, any(0" , "max(10px,any(0))" ) ]
177+ #[ case( "10px, any(0))" , "(10px,any(0))" ) ]
113178 fn test_optimize_value ( #[ case] input : & str , #[ case] expected : & str ) {
114179 assert_eq ! ( optimize_value( input) , expected) ;
115180 }
0 commit comments