Skip to content

Commit

Permalink
Improve minification of background position (fixes #41)
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett committed Jan 14, 2022
1 parent b2f5c90 commit 07c1e79
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 44 deletions.
11 changes: 7 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,7 @@ mod tests {
.foo {
background-position: center center;
}
"#, indoc! {".foo{background-position:50% 50%}"
"#, indoc! {".foo{background-position:50%}"
});

test(r#"
Expand Down Expand Up @@ -1791,7 +1791,7 @@ mod tests {
minify_test(".foo { background-position: bottom right }", ".foo{background-position:100% 100%}");

minify_test(".foo { background: url('img-sprite.png') no-repeat bottom right }", ".foo{background:url(img-sprite.png) 100% 100% no-repeat}");
minify_test(".foo { background: transparent }", ".foo{background:#0000}");
minify_test(".foo { background: transparent }", ".foo{background:0 0}");

minify_test(".foo { background: url(\"data:image/svg+xml,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3C/svg%3E\") }", ".foo{background:url(\"data:image/svg+xml,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3C/svg%3E\")}");

Expand Down Expand Up @@ -1889,6 +1889,9 @@ mod tests {
safari: Some(14 << 16),
..Browsers::default()
});

minify_test(".foo { background: none center }", ".foo{background:50%}");
minify_test(".foo { background: none }", ".foo{background:0 0}");
}

#[test]
Expand Down Expand Up @@ -5374,7 +5377,7 @@ mod tests {
"#,
indoc! {r#"
.foo {
background-image: radial-gradient(20px at 0% 0%, red, #00f);
background-image: radial-gradient(20px at 0 0, red, #00f);
}
"#},
Browsers {
Expand All @@ -5392,7 +5395,7 @@ mod tests {
"#,
indoc! {r#"
.foo {
background: radial-gradient(20px at 0% 0%, red, #00f);
background: radial-gradient(20px at 0 0, red, #00f);
}
"#},
Browsers {
Expand Down
9 changes: 7 additions & 2 deletions src/properties/background.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ impl ToCss for Background {
has_output = true;
}

if self.position != Position::default() || self.size != BackgroundSize::default() {
if !self.position.is_zero() || self.size != BackgroundSize::default() {
if has_output {
dest.write_str(" ")?;
}
Expand Down Expand Up @@ -372,7 +372,12 @@ impl ToCss for Background {

// If nothing was output, then this is the initial value, e.g. background: transparent
if !has_output {
self.color.to_css(dest)?;
if dest.minify {
// `0 0` is the shortest valid background value
self.position.to_css(dest)?;
} else {
dest.write_str("none")?;
}
}

Ok(())
Expand Down
85 changes: 47 additions & 38 deletions src/values/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use cssparser::*;
use crate::traits::{Parse, ToCss};
use crate::macros::enum_property;
use crate::printer::Printer;
use super::length::{LengthPercentage, LengthValue};
use super::length::{LengthPercentage};
use super::percentage::Percentage;
use crate::error::{ParserError, PrinterError};

Expand All @@ -22,10 +22,11 @@ impl Position {
}

pub fn is_center(&self) -> bool {
*self == Position::center() || *self == Position {
x: HorizontalPosition::Length(LengthPercentage::Percentage(Percentage(0.5))),
y: VerticalPosition::Length(LengthPercentage::Percentage(Percentage(0.5)))
}
self.x.is_center() && self.y.is_center()
}

pub fn is_zero(&self) -> bool {
self.x.is_zero() && self.y.is_zero()
}
}

Expand Down Expand Up @@ -136,8 +137,8 @@ impl ToCss for Position {
},
(
x_pos @ &HorizontalPosition::Side(side, Some(_)),
&VerticalPosition::Center
) if side != HorizontalPositionKeyword::Left => {
y
) if side != HorizontalPositionKeyword::Left && y.is_center() => {
// If there is a side keyword with an offset, "center" must be a keyword not a percentage.
x_pos.to_css(dest)?;
dest.write_str(" center")
Expand All @@ -151,44 +152,28 @@ impl ToCss for Position {
dest.write_str(" ")?;
y_pos.to_css(dest)
},
(
&HorizontalPosition::Length(ref x_lp),
&VerticalPosition::Center
) => {
// `center` is assumed if omitted.
x_lp.to_css(dest)
},
(
&HorizontalPosition::Side(side, None),
&VerticalPosition::Center,
) => {
let p: LengthPercentage = side.into();
p.to_css(dest)
},
(
&HorizontalPosition::Center,
y_pos @ &VerticalPosition::Side(_, None),
) => {
y_pos.to_css(dest)
(x, y) if x.is_center() && y.is_center() => {
// `center center` => 50%
x.to_css(dest)
},
(
&HorizontalPosition::Length(ref x_lp),
&VerticalPosition::Length(LengthPercentage::Percentage(Percentage(y_lp)))
) if y_lp == 0.5 => {
// 50% is equivalent to `center`, which may be omitted.
y
) if y.is_center() => {
// `center` is assumed if omitted.
x_lp.to_css(dest)
},
(
&HorizontalPosition::Side(side, None),
&VerticalPosition::Length(LengthPercentage::Percentage(Percentage(y_lp))),
) if y_lp == 0.5 => {
y,
) if y.is_center() => {
let p: LengthPercentage = side.into();
p.to_css(dest)
},
(
&HorizontalPosition::Length(LengthPercentage::Percentage(Percentage(x_lp))),
x,
y_pos @ &VerticalPosition::Side(_, None),
) if x_lp == 0.5 => {
) if x.is_center() => {
y_pos.to_css(dest)
},
(
Expand All @@ -202,16 +187,21 @@ impl ToCss for Position {
y.to_css(dest)
},
(x_pos, y_pos) => {
let zero = LengthPercentage::Dimension(LengthValue::Px(0.0));
let zero = LengthPercentage::zero();
let fifty = LengthPercentage::Percentage(Percentage(0.5));
let x_len = match &x_pos {
HorizontalPosition::Side(HorizontalPositionKeyword::Left, len) => {
if let Some(len) = len {
Some(len)
if *len == 0.0 {
Some(&zero)
} else {
Some(len)
}
} else {
Some(&zero)
}
},
HorizontalPosition::Length(len) if *len == 0.0 => Some(&zero),
HorizontalPosition::Length(len) => Some(len),
HorizontalPosition::Center => Some(&fifty),
_ => None
Expand All @@ -220,11 +210,16 @@ impl ToCss for Position {
let y_len = match &y_pos {
VerticalPosition::Side(VerticalPositionKeyword::Top, len) => {
if let Some(len) = len {
Some(len)
if *len == 0.0 {
Some(&zero)
} else {
Some(len)
}
} else {
Some(&zero)
}
},
VerticalPosition::Length(len) if *len == 0.0 => Some(&zero),
VerticalPosition::Length(len) => Some(len),
VerticalPosition::Center => Some(&fifty),
_ => None
Expand Down Expand Up @@ -254,6 +249,20 @@ pub enum PositionComponent<S> {
Side(S, Option<LengthPercentage>),
}

impl<S> PositionComponent<S> {
fn is_center(&self) -> bool {
match self {
PositionComponent::Center => true,
PositionComponent::Length(LengthPercentage::Percentage(Percentage(p))) => *p == 0.5,
_ => false
}
}

fn is_zero(&self) -> bool {
matches!(self, PositionComponent::Length(len) if *len == 0.0)
}
}

impl<S: Parse> Parse for PositionComponent<S> {
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
if input.try_parse(|i| i.expect_ident_matching("center")).is_ok() {
Expand Down Expand Up @@ -302,7 +311,7 @@ enum_property!(HorizontalPositionKeyword,
impl Into<LengthPercentage> for HorizontalPositionKeyword {
fn into(self) -> LengthPercentage {
match self {
HorizontalPositionKeyword::Left => LengthPercentage::Dimension(LengthValue::Px(0.0)),
HorizontalPositionKeyword::Left => LengthPercentage::zero(),
HorizontalPositionKeyword::Right => LengthPercentage::Percentage(Percentage(1.0))
}
}
Expand All @@ -316,7 +325,7 @@ enum_property!(VerticalPositionKeyword,
impl Into<LengthPercentage> for VerticalPositionKeyword {
fn into(self) -> LengthPercentage {
match self {
VerticalPositionKeyword::Top => LengthPercentage::Dimension(LengthValue::Px(0.0)),
VerticalPositionKeyword::Top => LengthPercentage::zero(),
VerticalPositionKeyword::Bottom => LengthPercentage::Percentage(Percentage(1.0))
}
}
Expand Down

0 comments on commit 07c1e79

Please sign in to comment.