@@ -29,8 +29,10 @@ use serde::{Deserialize, Serialize};
2929use cssparser:: { Parser , ParserInput , RuleListParser } ;
3030use crate :: traits:: ToCss ;
3131use printer:: Printer ;
32- use properties:: prefixes:: Browsers ;
32+ use properties:: VendorPrefix ;
33+ use properties:: prefixes:: { Browsers , Feature } ;
3334use declaration:: DeclarationHandler ;
35+ use std:: collections:: HashMap ;
3436
3537use parser:: TopLevelRuleParser ;
3638
@@ -65,6 +67,7 @@ fn compile(code: &str, minify: bool, targets: Option<Browsers>) -> String {
6567
6668 let mut handler = DeclarationHandler :: new ( false , targets) ;
6769 let mut important_handler = DeclarationHandler :: new ( true , targets) ;
70+ let mut keyframe_rules = HashMap :: new ( ) ;
6871
6972 for rule in rule_list {
7073 let rule = if let Ok ( ( _, rule) ) = rule {
@@ -84,6 +87,31 @@ fn compile(code: &str, minify: bool, targets: Option<Browsers>) -> String {
8487 for keyframe in keyframes. keyframes . iter_mut ( ) {
8588 keyframe. declarations . minify ( & mut handler, & mut important_handler) ;
8689 }
90+
91+ macro_rules! set_prefix {
92+ ( $keyframes: ident) => {
93+ if $keyframes. vendor_prefix. contains( VendorPrefix :: None ) {
94+ if let Some ( targets) = targets {
95+ $keyframes. vendor_prefix = Feature :: AtKeyframes . prefixes_for( targets)
96+ }
97+ }
98+ } ;
99+ }
100+
101+ // If there is an existing rule with the same name and identical keyframes,
102+ // merge the vendor prefixes from this rule into it.
103+ if let Some ( existing_idx) = keyframe_rules. get ( & keyframes. name ) {
104+ if let Some ( parser:: CssRule :: Keyframes ( existing) ) = & mut rules. get_mut ( * existing_idx) {
105+ if existing. keyframes == keyframes. keyframes {
106+ existing. vendor_prefix |= keyframes. vendor_prefix ;
107+ set_prefix ! ( existing) ;
108+ continue ;
109+ }
110+ }
111+ }
112+
113+ set_prefix ! ( keyframes) ;
114+ keyframe_rules. insert ( keyframes. name . clone ( ) , rules. len ( ) ) ;
87115 parser:: CssRule :: Keyframes ( keyframes)
88116 }
89117 parser:: CssRule :: Media ( mut media) => {
@@ -1940,6 +1968,265 @@ mod tests {
19401968 }
19411969 }
19421970 "# , "@keyframes test{0%{background:red}to{background:#00f}}" ) ;
1971+ minify_test ( r#"
1972+ @-webkit-keyframes test {
1973+ from {
1974+ background: green;
1975+ background-color: red;
1976+ }
1977+
1978+ 100% {
1979+ background: blue
1980+ }
1981+ }
1982+ "# , "@-webkit-keyframes test{0%{background:red}to{background:#00f}}" ) ;
1983+ minify_test ( r#"
1984+ @-moz-keyframes test {
1985+ from {
1986+ background: green;
1987+ background-color: red;
1988+ }
1989+
1990+ 100% {
1991+ background: blue
1992+ }
1993+ }
1994+ "# , "@-moz-keyframes test{0%{background:red}to{background:#00f}}" ) ;
1995+ minify_test ( r#"
1996+ @-webkit-keyframes test {
1997+ from {
1998+ background: green;
1999+ background-color: red;
2000+ }
2001+
2002+ 100% {
2003+ background: blue
2004+ }
2005+ }
2006+ @-moz-keyframes test {
2007+ from {
2008+ background: green;
2009+ background-color: red;
2010+ }
2011+
2012+ 100% {
2013+ background: blue
2014+ }
2015+ }
2016+ "# , "@-webkit-keyframes test{0%{background:red}to{background:#00f}}@-moz-keyframes test{0%{background:red}to{background:#00f}}" ) ;
2017+
2018+ prefix_test ( r#"
2019+ @keyframes test {
2020+ from {
2021+ background: green;
2022+ }
2023+ to {
2024+ background: blue
2025+ }
2026+ }
2027+ "# , indoc ! { r#"
2028+ @-webkit-keyframes test {
2029+ from {
2030+ background: green;
2031+ }
2032+
2033+ to {
2034+ background: #00f;
2035+ }
2036+ }
2037+
2038+ @-moz-keyframes test {
2039+ from {
2040+ background: green;
2041+ }
2042+
2043+ to {
2044+ background: #00f;
2045+ }
2046+ }
2047+
2048+ @keyframes test {
2049+ from {
2050+ background: green;
2051+ }
2052+
2053+ to {
2054+ background: #00f;
2055+ }
2056+ }
2057+ "# } , Browsers {
2058+ safari : Some ( 5 << 16 ) ,
2059+ firefox : Some ( 6 << 16 ) ,
2060+ ..Browsers :: default ( )
2061+ } ) ;
2062+ prefix_test ( r#"
2063+ @-webkit-keyframes test {
2064+ from {
2065+ background: green;
2066+ }
2067+
2068+ to {
2069+ background: blue;
2070+ }
2071+ }
2072+ @-moz-keyframes test {
2073+ from {
2074+ background: green;
2075+ }
2076+
2077+ to {
2078+ background: blue;
2079+ }
2080+ }
2081+ @keyframes test {
2082+ from {
2083+ background: green;
2084+ }
2085+ to {
2086+ background: blue
2087+ }
2088+ }
2089+ "# , indoc ! { r#"
2090+ @keyframes test {
2091+ from {
2092+ background: green;
2093+ }
2094+
2095+ to {
2096+ background: #00f;
2097+ }
2098+ }
2099+ "# } , Browsers {
2100+ safari : Some ( 10 << 16 ) ,
2101+ firefox : Some ( 17 << 16 ) ,
2102+ ..Browsers :: default ( )
2103+ } ) ;
2104+ prefix_test ( r#"
2105+ @-webkit-keyframes test1 {
2106+ from {
2107+ background: green;
2108+ }
2109+
2110+ to {
2111+ background: blue;
2112+ }
2113+ }
2114+
2115+ @-moz-keyframes test2 {
2116+ from {
2117+ background: green;
2118+ }
2119+
2120+ to {
2121+ background: blue;
2122+ }
2123+ }
2124+
2125+ @keyframes test3 {
2126+ from {
2127+ background: green;
2128+ }
2129+ to {
2130+ background: blue
2131+ }
2132+ }
2133+ "# , indoc ! { r#"
2134+ @-webkit-keyframes test1 {
2135+ from {
2136+ background: green;
2137+ }
2138+
2139+ to {
2140+ background: #00f;
2141+ }
2142+ }
2143+
2144+ @-moz-keyframes test2 {
2145+ from {
2146+ background: green;
2147+ }
2148+
2149+ to {
2150+ background: #00f;
2151+ }
2152+ }
2153+
2154+ @keyframes test3 {
2155+ from {
2156+ background: green;
2157+ }
2158+
2159+ to {
2160+ background: #00f;
2161+ }
2162+ }
2163+ "# } , Browsers {
2164+ safari : Some ( 10 << 16 ) ,
2165+ firefox : Some ( 17 << 16 ) ,
2166+ ..Browsers :: default ( )
2167+ } ) ;
2168+ prefix_test ( r#"
2169+ @-webkit-keyframes test {
2170+ from {
2171+ background: green;
2172+ }
2173+
2174+ to {
2175+ background: red;
2176+ }
2177+ }
2178+ @-moz-keyframes test {
2179+ from {
2180+ background: green;
2181+ }
2182+
2183+ to {
2184+ background: pink;
2185+ }
2186+ }
2187+ @keyframes test {
2188+ from {
2189+ background: green;
2190+ }
2191+ to {
2192+ background: blue
2193+ }
2194+ }
2195+ "# , indoc ! { r#"
2196+ @-webkit-keyframes test {
2197+ from {
2198+ background: green;
2199+ }
2200+
2201+ to {
2202+ background: red;
2203+ }
2204+ }
2205+
2206+ @-moz-keyframes test {
2207+ from {
2208+ background: green;
2209+ }
2210+
2211+ to {
2212+ background: pink;
2213+ }
2214+ }
2215+
2216+ @keyframes test {
2217+ from {
2218+ background: green;
2219+ }
2220+
2221+ to {
2222+ background: #00f;
2223+ }
2224+ }
2225+ "# } , Browsers {
2226+ safari : Some ( 10 << 16 ) ,
2227+ firefox : Some ( 17 << 16 ) ,
2228+ ..Browsers :: default ( )
2229+ } ) ;
19432230 }
19442231
19452232 #[ test]
0 commit comments