diff --git a/src/lib.rs b/src/lib.rs index fbba61af..6d50f225 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11561,14 +11561,26 @@ mod tests { ".foo { animation-fill-mode: Backwards,forwards }", ".foo{animation-fill-mode:backwards,forwards}", ); - minify_test(".foo { animation: none }", ".foo{animation:none}"); + minify_test(".foo { animation: none }", ".foo{animation:1}"); minify_test(".foo { animation: \"none\" }", ".foo{animation:\"none\"}"); minify_test(".foo { animation: \"None\" }", ".foo{animation:\"None\"}"); - minify_test(".foo { animation: \"none\", none }", ".foo{animation:\"none\",none}"); - minify_test(".foo { animation: none, none }", ".foo{animation:none,none}"); + minify_test(".foo { animation: \"none\", none }", ".foo{animation:\"none\",1}"); + minify_test(".foo { animation: none, none }", ".foo{animation:1,1}"); minify_test(".foo { animation: \"none\" none }", ".foo{animation:\"none\"}"); minify_test(".foo { animation: none none }", ".foo{animation:none}"); + minify_test(".foo { animation: 0s }", ".foo{animation:1}"); + minify_test(".foo { animation: 1s }", ".foo{animation:1s}"); + minify_test(".foo { animation: ease }", ".foo{animation:1}"); + minify_test(".foo { animation: linear }", ".foo{animation:linear}"); + minify_test(".foo { animation: 1 }", ".foo{animation:1}"); + minify_test(".foo { animation: infinite }", ".foo{animation:infinite}"); + minify_test(".foo { animation: normal }", ".foo{animation:1}"); + minify_test(".foo { animation: reverse }", ".foo{animation:reverse}"); + minify_test(".foo { animation: forwards }", ".foo{animation:forwards}"); + minify_test(".foo { animation: running }", ".foo{animation:1}"); + minify_test(".foo { animation: paused }", ".foo{animation:paused}"); + // Test animation-name + animation-fill-mode minify_test( ".foo { animation: 2s both \"none\"}", diff --git a/src/properties/animation.rs b/src/properties/animation.rs index 51bd1ea4..abdf2c54 100644 --- a/src/properties/animation.rs +++ b/src/properties/animation.rs @@ -661,55 +661,96 @@ impl<'i> ToCss for Animation<'i> { where W: std::fmt::Write, { - match &self.name { - AnimationName::None => {} - AnimationName::Ident(CustomIdent(name)) | AnimationName::String(CSSString(name)) => { - if !self.duration.is_zero() || !self.delay.is_zero() { - self.duration.to_css(dest)?; - dest.write_char(' ')?; - } + let name = match &self.name { + AnimationName::None => None, + AnimationName::Ident(CustomIdent(name)) | AnimationName::String(CSSString(name)) => Some(name), + }; - if !self.timing_function.is_ease() || EasingFunction::is_ident(&name) { - self.timing_function.to_css(dest)?; - dest.write_char(' ')?; - } + let mut has_item = false; - if !self.delay.is_zero() { - self.delay.to_css(dest)?; - dest.write_char(' ')?; - } + if !self.duration.is_zero() || !self.delay.is_zero() { + self.duration.to_css(dest)?; + has_item = true; + } - if self.iteration_count != AnimationIterationCount::default() || name.as_ref() == "infinite" { - self.iteration_count.to_css(dest)?; - dest.write_char(' ')?; - } + if !self.timing_function.is_ease() || name.is_some_and(|name| EasingFunction::is_ident(name)) { + if has_item { + dest.write_char(' ')?; + } + self.timing_function.to_css(dest)?; + has_item = true; + } - if self.direction != AnimationDirection::default() || AnimationDirection::parse_string(&name).is_ok() { - self.direction.to_css(dest)?; - dest.write_char(' ')?; - } + if !self.delay.is_zero() { + if has_item { + dest.write_char(' ')?; + } + self.delay.to_css(dest)?; + has_item = true; + } - if self.fill_mode != AnimationFillMode::default() - || (!name.eq_ignore_ascii_case("none") && AnimationFillMode::parse_string(&name).is_ok()) - { - self.fill_mode.to_css(dest)?; - dest.write_char(' ')?; - } + if self.iteration_count != AnimationIterationCount::default() + || name.is_some_and(|name| name.as_ref() == "infinite") + { + if has_item { + dest.write_char(' ')?; + } + self.iteration_count.to_css(dest)?; + has_item = true; + } - if self.play_state != AnimationPlayState::default() || AnimationPlayState::parse_string(&name).is_ok() { - self.play_state.to_css(dest)?; - dest.write_char(' ')?; - } + if self.direction != AnimationDirection::default() + || name.is_some_and(|name| AnimationDirection::parse_string(name).is_ok()) + { + if has_item { + dest.write_char(' ')?; + } + self.direction.to_css(dest)?; + has_item = true; + } + + if self.fill_mode != AnimationFillMode::default() + || name + .is_some_and(|name| !name.eq_ignore_ascii_case("none") && AnimationFillMode::parse_string(name).is_ok()) + { + if has_item { + dest.write_char(' ')?; + } + self.fill_mode.to_css(dest)?; + has_item = true; + } + + if self.play_state != AnimationPlayState::default() + || name.is_some_and(|name| AnimationPlayState::parse_string(name).is_ok()) + { + if has_item { + dest.write_char(' ')?; } + self.play_state.to_css(dest)?; + has_item = true; } // Eventually we could output a string here to avoid duplicating some properties above. // Chrome does not yet support strings, however. - self.name.to_css(dest)?; + if self.name != AnimationName::None { + if has_item { + dest.write_char(' ')?; + } + self.name.to_css(dest)?; + has_item = true; - if self.name != AnimationName::None && self.timeline != AnimationTimeline::default() { - dest.write_char(' ')?; - self.timeline.to_css(dest)?; + if self.timeline != AnimationTimeline::default() { + dest.write_char(' ')?; + self.timeline.to_css(dest)?; + } + } + + if !has_item { + if dest.minify { + dest.write_char('1')?; + } else { + dest.write_str("none")?; + } } Ok(())