diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 324b0112f02..3f7011c4de5 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -223,6 +223,7 @@ ${helpers.predefined_type("object-position", ${helpers.predefined_type("grid-%s-gap" % kind, "LengthOrPercentage", "computed::LengthOrPercentage::Length(Au(0))", + "parse_non_negative", spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-gap" % kind, animation_value_type="ComputedValue", products="gecko")} diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 0e11143097b..b2279c6b3f7 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -76,21 +76,35 @@ impl Parse for GridLine { return Ok(grid_line) } + // | [ && ? ] | [ span && [ || ] ] + // This horror is simply, + // [ span? && [ || ] ] + // And, for some magical reason, "span" should be the first or last value and not in-between. + let mut val_before_span = false; + for _ in 0..3 { // Maximum possible entities for if input.try(|i| i.expect_ident_matching("span")).is_ok() { - 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() { + if grid_line.is_span { return Err(()) } + + if grid_line.line_num.is_some() || grid_line.ident.is_some() { + val_before_span = true; + } + + grid_line.is_span = true; + } else if let Ok(i) = input.try(|i| Integer::parse(context, i)) { + if i.value() == 0 || val_before_span || grid_line.line_num.is_some() { + return Err(()) + } + grid_line.line_num = Some(i); } else if let Ok(name) = input.try(|i| i.expect_ident()) { - if grid_line.ident.is_some() || CustomIdent::from_ident((&*name).into(), &[]).is_err() { + if val_before_span || grid_line.ident.is_some() || + CustomIdent::from_ident((&*name).into(), &[]).is_err() { return Err(()) } + grid_line.ident = Some(name.into_owned()); } else { break