Skip to content

Commit 29a487f

Browse files
committed
Prefix keyframes
1 parent 29b4fd7 commit 29a487f

File tree

5 files changed

+384
-60
lines changed

5 files changed

+384
-60
lines changed

src/lib.rs

Lines changed: 288 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ use serde::{Deserialize, Serialize};
2929
use cssparser::{Parser, ParserInput, RuleListParser};
3030
use crate::traits::ToCss;
3131
use printer::Printer;
32-
use properties::prefixes::Browsers;
32+
use properties::VendorPrefix;
33+
use properties::prefixes::{Browsers, Feature};
3334
use declaration::DeclarationHandler;
35+
use std::collections::HashMap;
3436

3537
use 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

Comments
 (0)