aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRavi Shankar <wafflespeanut@gmail.com>2017-05-23 22:12:42 +0530
committerRavi Shankar <wafflespeanut@gmail.com>2017-05-24 19:45:34 +0530
commit7b68d8d8bf9e6fe8a3ea9979ffc58d49fdb68919 (patch)
treed6e2546fa83d48a20565cfd2abc1f5a393c0cfb9
parent7dbd17bf701c2e83b9c63afd63cbc827805b9ffd (diff)
downloadservo-7b68d8d8bf9e6fe8a3ea9979ffc58d49fdb68919.tar.gz
servo-7b68d8d8bf9e6fe8a3ea9979ffc58d49fdb68919.zip
Add shorthand parsing/serialization for grid-template
-rw-r--r--components/style/properties/longhand/position.mako.rs7
-rw-r--r--components/style/properties/shorthand/position.mako.rs153
-rw-r--r--components/style/values/generics/grid.rs6
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 3f7011c4de5..754fc94732b 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<Box<str>>) -> Result<TemplateAreas, ()> {
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 11b2cd41b0b..1573a6a43e0 100644
--- a/components/style/properties/shorthand/position.mako.rs
+++ b/components/style/properties/shorthand/position.mako.rs
@@ -241,6 +241,159 @@
}
</%helpers:shorthand>
+<%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 `<grid-template>` shorthand (also used by `grid` shorthand).
+ pub fn parse_grid_template(context: &ParserContext, input: &mut Parser)
+ -> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>), ()> {
+ 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<Longhands, ()> {
+ 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 `<grid-template>` shorthand (also used by `grid` shorthand).
+ pub fn serialize_grid_template<W>(template_rows: &TrackListOrNone,
+ template_columns: &TrackListOrNone,
+ template_areas: &Either<TemplateAreas, None_>,
+ 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<W>(&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>
+
<%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 b2279c6b3f7..73640a91e49 100644
--- a/components/style/values/generics/grid.rs
+++ b/components/style/values/generics/grid.rs
@@ -306,8 +306,10 @@ impl<L: ToComputedValue> ToComputedValue for TrackSize<L> {
}
}
-fn concat_serialize_idents<W>(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 <line-names> (in grid).
+pub fn concat_serialize_idents<W>(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() {