From 7b68d8d8bf9e6fe8a3ea9979ffc58d49fdb68919 Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Tue, 23 May 2017 22:12:42 +0530 Subject: [PATCH] Add shorthand parsing/serialization for grid-template --- .../properties/longhand/position.mako.rs | 7 + .../properties/shorthand/position.mako.rs | 153 ++++++++++++++++++ components/style/values/generics/grid.rs | 6 +- 3 files changed, 164 insertions(+), 2 deletions(-) diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 3f7011c4de54..754fc94732be 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -397,6 +397,13 @@ ${helpers.predefined_type("object-position", while let Ok(string) = input.try(Parser::expect_string) { strings.push(string.into_owned().into_boxed_str()); } + + TemplateAreas::from_vec(strings) + } + } + + impl TemplateAreas { + pub fn from_vec(strings: Vec>) -> Result { if strings.is_empty() { return Err(()); } diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 11b2cd41b0b2..1573a6a43e03 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -241,6 +241,159 @@ } +<%helpers:shorthand name="grid-template" + sub_properties="grid-template-rows grid-template-columns grid-template-areas" + spec="https://drafts.csswg.org/css-grid/#propdef-grid-template" + disable_when_testing="True" + products="gecko"> + use cssparser::serialize_string; + use parser::Parse; + use properties::longhands::grid_template_rows; + use properties::longhands::grid_template_areas::TemplateAreas; + use values::{Either, None_}; + use values::generics::grid::{TrackSize, TrackList, TrackListType, concat_serialize_idents}; + use values::specified::TrackListOrNone; + use values::specified::grid::parse_line_names; + + /// Parsing for `` shorthand (also used by `grid` shorthand). + pub fn parse_grid_template(context: &ParserContext, input: &mut Parser) + -> Result<(TrackListOrNone, TrackListOrNone, Either), ()> { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_))) + } + + let first_line_names = input.try(parse_line_names).unwrap_or(vec![]); + if let Ok(s) = input.try(Parser::expect_string) { + let mut strings = vec![]; + let mut values = vec![]; + let mut line_names = vec![]; + let mut names = first_line_names; + let mut string = s.into_owned().into_boxed_str(); + loop { + line_names.push(names); + strings.push(string); + let size = input.try(|i| TrackSize::parse(context, i)).unwrap_or_default(); + values.push(Either::First(size)); + names = input.try(parse_line_names).unwrap_or(vec![]); + if let Ok(v) = input.try(parse_line_names) { + names.extend(v); + } + + string = match input.try(Parser::expect_string) { + Ok(s) => s.into_owned().into_boxed_str(), + _ => { // only the named area determines whether we should bail out + line_names.push(names); + break + }, + }; + } + + if line_names.len() == values.len() { + line_names.push(vec![]); // should be one longer than track sizes + } + + let template_areas = TemplateAreas::from_vec(strings)?; + let template_rows = TrackList { + list_type: TrackListType::Normal, + values: values, + line_names: line_names, + auto_repeat: None, + }; + + let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() { + let track_list = TrackList::parse(context, input)?; + if track_list.list_type != TrackListType::Explicit { + return Err(()) + } + + Either::First(track_list) + } else { + Either::Second(None_) + }; + + Ok((Either::First(template_rows), template_cols, Either::First(template_areas))) + } else { + let mut template_rows = grid_template_rows::parse(context, input)?; + if let Either::First(ref mut list) = template_rows { + list.line_names[0] = first_line_names; // won't panic + } + + Ok((template_rows, grid_template_rows::parse(context, input)?, Either::Second(None_))) + } + } + + #[inline] + pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result { + let (rows, columns, areas) = parse_grid_template(context, input)?; + Ok(expanded! { + grid_template_rows: rows, + grid_template_columns: columns, + grid_template_areas: areas, + }) + } + + /// Serialization for `` shorthand (also used by `grid` shorthand). + pub fn serialize_grid_template(template_rows: &TrackListOrNone, + template_columns: &TrackListOrNone, + template_areas: &Either, + dest: &mut W) -> fmt::Result where W: fmt::Write { + match *template_areas { + Either::Second(_none) => { + if template_rows == &Either::Second(None_) && + template_columns == &Either::Second(None_) { + dest.write_str("none") + } else { + template_rows.to_css(dest)?; + dest.write_str(" / ")?; + template_columns.to_css(dest) + } + }, + Either::First(ref areas) => { + let track_list = match *template_rows { + Either::First(ref list) => list, + Either::Second(_none) => unreachable!(), // should exist! + }; + + let mut names_iter = track_list.line_names.iter(); + for (((i, string), names), size) in areas.strings.iter().enumerate() + .zip(&mut names_iter) + .zip(track_list.values.iter()) { + if i > 0 { + dest.write_str(" ")?; + } + + if !names.is_empty() { + concat_serialize_idents("[", "] ", names, " ", dest)?; + } + + serialize_string(string, dest)?; + dest.write_str(" ")?; + size.to_css(dest)?; + } + + if let Some(names) = names_iter.next() { + concat_serialize_idents(" [", "]", names, " ", dest)?; + } + + if let Either::First(ref list) = *template_columns { + dest.write_str(" / ")?; + list.to_css(dest)?; + } + + Ok(()) + }, + } + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + #[inline] + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + serialize_grid_template(self.grid_template_rows, self.grid_template_columns, + self.grid_template_areas, dest) + } + } + + <%helpers:shorthand name="place-content" sub_properties="align-content justify-content" spec="https://drafts.csswg.org/css-align/#propdef-place-content" products="gecko" disable_when_testing="True"> diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index b2279c6b3f7c..73640a91e497 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -306,8 +306,10 @@ impl ToComputedValue for TrackSize { } } -fn concat_serialize_idents(prefix: &str, suffix: &str, - slice: &[String], sep: &str, dest: &mut W) -> fmt::Result +/// Helper function for serializing identifiers with a prefix and suffix, used +/// for serializing (in grid). +pub fn concat_serialize_idents(prefix: &str, suffix: &str, + slice: &[String], sep: &str, dest: &mut W) -> fmt::Result where W: fmt::Write { if let Some((ref first, rest)) = slice.split_first() {