Fix old grid code

* Fix <grid-line> parsing/serialization and fit-content parsing
 * Fix <track-size> flex computation
 * Cleanup <grid-line> and <track-size> code
This commit is contained in:
Ravi Shankar 2017-03-23 00:10:59 +05:30
parent 0c68471b5e
commit 4899bb471b
2 changed files with 55 additions and 35 deletions

View file

@ -154,7 +154,7 @@
GridLine::parse(context, input)? GridLine::parse(context, input)?
} else { } else {
let mut line = GridLine::default(); let mut line = GridLine::default();
if start.integer.is_none() && !start.is_span { if start.line_num.is_none() && !start.is_span {
line.ident = start.ident.clone(); // ident from start value should be taken line.ident = start.ident.clone(); // ident from start value should be taken
} }
@ -188,7 +188,7 @@
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> { pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
fn line_with_ident_from(other: &GridLine) -> GridLine { fn line_with_ident_from(other: &GridLine) -> GridLine {
let mut this = GridLine::default(); let mut this = GridLine::default();
if other.integer.is_none() && !other.is_span { if other.line_num.is_none() && !other.is_span {
this.ident = other.ident.clone(); this.ident = other.ident.clone();
} }

View file

@ -26,7 +26,14 @@ pub struct GridLine {
/// https://drafts.csswg.org/css-grid/#grid-placement-slot /// https://drafts.csswg.org/css-grid/#grid-placement-slot
pub ident: Option<String>, pub ident: Option<String>,
/// Denotes the nth grid line from grid item's placement. /// Denotes the nth grid line from grid item's placement.
pub integer: Option<i32>, pub line_num: Option<Integer>,
}
impl GridLine {
/// Check whether this `<grid-line>` represents an `auto` value.
pub fn is_auto(&self) -> bool {
self.ident.is_none() && self.line_num.is_none() && !self.is_span
}
} }
impl Default for GridLine { impl Default for GridLine {
@ -34,27 +41,28 @@ impl Default for GridLine {
GridLine { GridLine {
is_span: false, is_span: false,
ident: None, ident: None,
integer: None, line_num: None,
} }
} }
} }
impl ToCss for GridLine { impl ToCss for GridLine {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if !self.is_span && self.ident.is_none() && self.integer.is_none() { if self.is_auto() {
return dest.write_str("auto") return dest.write_str("auto")
} }
if self.is_span { if self.is_span {
try!(dest.write_str("span")); dest.write_str("span")?;
} }
if let Some(i) = self.integer { if let Some(i) = self.line_num {
try!(write!(dest, " {}", i)); write!(dest, " {}", i.value)?;
} }
if let Some(ref s) = self.ident { if let Some(ref s) = self.ident {
try!(write!(dest, " {}", s)); dest.write_str(" ")?;
serialize_identifier(s, dest)?;
} }
Ok(()) Ok(())
@ -62,7 +70,7 @@ impl ToCss for GridLine {
} }
impl Parse for GridLine { impl Parse for GridLine {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let mut grid_line = Default::default(); let mut grid_line = Default::default();
if input.try(|i| i.expect_ident_matching("auto")).is_ok() { if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(grid_line) return Ok(grid_line)
@ -70,17 +78,17 @@ impl Parse for GridLine {
for _ in 0..3 { // Maximum possible entities for <grid-line> for _ in 0..3 { // Maximum possible entities for <grid-line>
if input.try(|i| i.expect_ident_matching("span")).is_ok() { if input.try(|i| i.expect_ident_matching("span")).is_ok() {
if grid_line.is_span { if grid_line.is_span || grid_line.line_num.is_some() || grid_line.ident.is_some() {
return Err(()) // span (if specified) should be first
}
grid_line.is_span = true; // span (if specified) should be first
} else if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
if i.value == 0 || grid_line.line_num.is_some() {
return Err(()) return Err(())
} }
grid_line.is_span = true; grid_line.line_num = Some(i);
} else if let Ok(i) = input.try(|i| i.expect_integer()) {
if i == 0 || grid_line.integer.is_some() {
return Err(())
}
grid_line.integer = Some(i);
} else if let Ok(name) = input.try(|i| i.expect_ident()) { } else if let Ok(name) = input.try(|i| i.expect_ident()) {
if grid_line.ident.is_some() { if grid_line.ident.is_some() || CustomIdent::from_ident((&*name).into(), &[]).is_err() {
return Err(()) return Err(())
} }
grid_line.ident = Some(name.into_owned()); grid_line.ident = Some(name.into_owned());
@ -89,13 +97,19 @@ impl Parse for GridLine {
} }
} }
if grid_line.is_auto() {
return Err(())
}
if grid_line.is_span { if grid_line.is_span {
if let Some(i) = grid_line.integer { if let Some(i) = grid_line.line_num {
if i < 0 { // disallow negative integers for grid spans if i.value <= 0 { // disallow negative integers for grid spans
return Err(()) return Err(())
} }
} else if grid_line.ident.is_some() { // integer could be omitted
grid_line.line_num = Some(Integer::new(1));
} else { } else {
grid_line.integer = Some(1); return Err(())
} }
} }
@ -142,7 +156,7 @@ impl<L> TrackBreadth<L> {
/// Parse a single flexible length. /// Parse a single flexible length.
pub fn parse_flex(input: &mut Parser) -> Result<CSSFloat, ()> { pub fn parse_flex(input: &mut Parser) -> Result<CSSFloat, ()> {
match try!(input.next()) { match input.next()? {
Token::Dimension(ref value, ref unit) if unit.eq_ignore_ascii_case("fr") && value.value.is_sign_positive() Token::Dimension(ref value, ref unit) if unit.eq_ignore_ascii_case("fr") && value.value.is_sign_positive()
=> Ok(value.value), => Ok(value.value),
_ => Err(()), _ => Err(()),
@ -271,19 +285,19 @@ impl Parse for TrackSize<LengthOrPercentage> {
match input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { match input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
Ok(lop) => TrackBreadth::Breadth(lop), Ok(lop) => TrackBreadth::Breadth(lop),
Err(..) => { Err(..) => {
let keyword = try!(TrackKeyword::parse(input)); let keyword = TrackKeyword::parse(input)?;
TrackBreadth::Keyword(keyword) TrackBreadth::Keyword(keyword)
} }
}; };
try!(input.expect_comma()); input.expect_comma()?;
Ok(TrackSize::MinMax(inflexible_breadth, try!(TrackBreadth::parse(context, input)))) Ok(TrackSize::MinMax(inflexible_breadth, TrackBreadth::parse(context, input)?))
}); });
} }
try!(input.expect_function_matching("fit-content")); input.expect_function_matching("fit-content")?;
// FIXME(emilio): This needs a parse_nested_block, doesn't it? let lop = input.parse_nested_block(|i| LengthOrPercentage::parse_non_negative(context, i))?;
Ok(try!(LengthOrPercentage::parse(context, input).map(TrackSize::FitContent))) Ok(TrackSize::FitContent(lop))
} }
} }
@ -292,15 +306,15 @@ impl<L: ToCss> ToCss for TrackSize<L> {
match *self { match *self {
TrackSize::Breadth(ref b) => b.to_css(dest), TrackSize::Breadth(ref b) => b.to_css(dest),
TrackSize::MinMax(ref infexible, ref flexible) => { TrackSize::MinMax(ref infexible, ref flexible) => {
try!(dest.write_str("minmax(")); dest.write_str("minmax(")?;
try!(infexible.to_css(dest)); infexible.to_css(dest)?;
try!(dest.write_str(", ")); dest.write_str(", ")?;
try!(flexible.to_css(dest)); flexible.to_css(dest)?;
dest.write_str(")") dest.write_str(")")
}, },
TrackSize::FitContent(ref lop) => { TrackSize::FitContent(ref lop) => {
try!(dest.write_str("fit-content(")); dest.write_str("fit-content(")?;
try!(lop.to_css(dest)); lop.to_css(dest)?;
dest.write_str(")") dest.write_str(")")
}, },
} }
@ -324,7 +338,13 @@ impl<L: ToComputedValue> ToComputedValue for TrackSize<L> {
#[inline] #[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self { match *self {
TrackSize::Breadth(ref b) => TrackSize::Breadth(b.to_computed_value(context)), TrackSize::Breadth(ref b) => match *b {
// <flex> outside `minmax()` expands to `mimmax(auto, <flex>)`
// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-flex
TrackBreadth::Flex(f) =>
TrackSize::MinMax(TrackBreadth::Keyword(TrackKeyword::Auto), TrackBreadth::Flex(f)),
_ => TrackSize::Breadth(b.to_computed_value(context)),
},
TrackSize::MinMax(ref b_1, ref b_2) => TrackSize::MinMax(ref b_1, ref b_2) =>
TrackSize::MinMax(b_1.to_computed_value(context), b_2.to_computed_value(context)), TrackSize::MinMax(b_1.to_computed_value(context), b_2.to_computed_value(context)),
TrackSize::FitContent(ref lop) => TrackSize::FitContent(lop.to_computed_value(context)), TrackSize::FitContent(ref lop) => TrackSize::FitContent(lop.to_computed_value(context)),