Skip to content
Permalink
Browse files

Adding support for correct shorthand serialization

  • Loading branch information...
craftytrickster committed Aug 17, 2016
1 parent 49431be commit 3831c0650cba09854888e6cf053f78b8b963df96
Showing with 1,186 additions and 643 deletions.
  1. +74 −12 components/style/properties/helpers.mako.rs
  2. +34 −54 components/style/properties/properties.mako.rs
  3. +161 −74 components/style/properties/shorthand/background.mako.rs
  4. +102 −26 components/style/properties/shorthand/border.mako.rs
  5. +236 −152 components/style/properties/shorthand/box.mako.rs
  6. +40 −27 components/style/properties/shorthand/column.mako.rs
  7. +87 −49 components/style/properties/shorthand/font.mako.rs
  8. +12 −3 components/style/properties/shorthand/inherited_text.mako.rs
  9. +93 −68 components/style/properties/shorthand/list.mako.rs
  10. +79 −39 components/style/properties/shorthand/outline.mako.rs
  11. +81 −48 components/style/properties/shorthand/position.mako.rs
  12. +97 −0 components/style/properties/shorthand/serialize.mako.rs
  13. +51 −24 components/style/properties/shorthand/text.mako.rs
  14. +15 −15 components/style/values/computed/basic_shape.rs
  15. +15 −15 components/style/values/specified/basic_shape.rs
  16. +0 −4 tests/wpt/metadata-css/css-flexbox-1_dev/html/flex-flexitem-percentage-prescation.htm.ini
  17. +0 −3 tests/wpt/metadata-css/css21_dev/html4/run-in-listitem-between-001.htm.ini
  18. +0 −3 tests/wpt/metadata-css/css21_dev/html4/run-in-listitem-between-002.htm.ini
  19. +0 −15 tests/wpt/metadata-css/cssom-1_dev/html/cssom-setProperty-shorthand.htm.ini
  20. +0 −5 tests/wpt/metadata-css/cssom-1_dev/html/index-001.htm.ini
  21. +1 −7 tests/wpt/metadata-css/cssom-1_dev/html/index-002.htm.ini
  22. +3 −0 tests/wpt/mozilla/meta/mozilla/calc.html.ini
  23. +5 −0 tests/wpt/mozilla/meta/mozilla/style_no_trailing_space.html.ini
@@ -403,9 +403,11 @@
%>
% if shorthand:
pub mod ${shorthand.ident} {
use cssparser::Parser;
#[allow(unused_imports)]
use cssparser::{Parser, ToCss};
use parser::ParserContext;
use properties::{longhands, PropertyDeclaration, DeclaredValue, Shorthand};
use std::fmt;

pub struct Longhands {
% for sub_property in shorthand.sub_properties:
@@ -414,6 +416,55 @@
% endfor
}

/// Represents a serializable set of all of the longhand properties that correspond to a shorthand
pub struct LonghandsToSerialize<'a> {
% for sub_property in shorthand.sub_properties:
pub ${sub_property.ident}: &'a DeclaredValue<longhands::${sub_property.ident}::SpecifiedValue>,
% endfor
}

impl<'a> LonghandsToSerialize<'a> {
pub fn from_iter<I: Iterator<Item=&'a PropertyDeclaration>>(iter: I) -> Result<Self, ()> {
// Define all of the expected variables that correspond to the shorthand
% for sub_property in shorthand.sub_properties:
let mut ${sub_property.ident} = None;
% endfor

// Attempt to assign the incoming declarations to the expected variables
for longhand in iter {
match *longhand {
% for sub_property in shorthand.sub_properties:
PropertyDeclaration::${sub_property.camel_case}(ref value) => {
${sub_property.ident} = Some(value)
},
% endfor
_ => {}
};
}

// If any of the expected variables are missing, return an error
match (
% for sub_property in shorthand.sub_properties:
${sub_property.ident},
% endfor
) {

(
% for sub_property in shorthand.sub_properties:
Some(${sub_property.ident}),
% endfor
) =>
Ok(LonghandsToSerialize {
% for sub_property in shorthand.sub_properties:
${sub_property.ident}: ${sub_property.ident},
% endfor
}),
_ => Err(())
}
}
}


pub fn parse(context: &ParserContext, input: &mut Parser,
declarations: &mut Vec<PropertyDeclaration>)
-> Result<(), ()> {
@@ -454,10 +505,7 @@
}
}

#[allow(unused_variables)]
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
${caller.body()}
}
${caller.body()}
}
% endif
</%def>
@@ -468,12 +516,26 @@
for side in ['top', 'right', 'bottom', 'left'])}">
use super::parse_four_sides;
use values::specified;
let _unused = context;
let (top, right, bottom, left) = try!(parse_four_sides(input, ${parser_function}));
Ok(Longhands {
% for side in ["top", "right", "bottom", "left"]:
${to_rust_ident(sub_property_pattern % side)}: Some(${side}),
% endfor
})

pub fn parse_value(_: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
let (top, right, bottom, left) = try!(parse_four_sides(input, ${parser_function}));
Ok(Longhands {
% for side in ["top", "right", "bottom", "left"]:
${to_rust_ident(sub_property_pattern % side)}: Some(${side}),
% endfor
})
}

impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
super::serialize_four_sides(
dest,
self.${to_rust_ident(sub_property_pattern % 'top')},
self.${to_rust_ident(sub_property_pattern % 'right')},
self.${to_rust_ident(sub_property_pattern % 'bottom')},
self.${to_rust_ident(sub_property_pattern % 'left')}
)
}
}
</%self:shorthand>
</%def>
@@ -6,7 +6,7 @@

// Please note that valid Rust syntax may be mangled by the Mako parser.
// For example, Vec<&Foo> will be mangled as Vec&Foo>. To work around these issues, the code
// can be escaped. In the above example, Vec<<&Foo> achieves the desired result of Vec<&Foo>.
// can be escaped. In the above example, Vec<<&Foo> or Vec< &Foo> achieves the desired result of Vec<&Foo>.

<%namespace name="helpers" file="/helpers.mako.rs" />

@@ -74,8 +74,7 @@ pub mod longhands {
}

pub mod shorthands {
use cssparser::{Parser, ToCss};
use std::fmt;
use cssparser::Parser;
use parser::ParserContext;
use values::specified;

@@ -122,33 +121,7 @@ pub mod shorthands {
Ok((top, right, bottom, left))
}

/// Serialize a set of top,left,bottom,right values, in <margin>-shorthand style,
/// attempting to minimize the output
pub fn serialize_four_sides<T, W>(sides: (&T, &T, &T, &T), dest: &mut W) -> fmt::Result
where W: fmt::Write, T: ToCss+PartialEq {
if sides.0 == sides.1 && sides.0 == sides.2 && sides.0 == sides.3 {
sides.0.to_css(dest)
} else if sides.0 == sides.2 && sides.1 == sides.3 {
try!(sides.0.to_css(dest));
try!(dest.write_str(" "));
sides.1.to_css(dest)
} else if sides.1 == sides.3 {
try!(sides.0.to_css(dest));
try!(dest.write_str(" "));
try!(sides.1.to_css(dest));
try!(dest.write_str(" "));
sides.2.to_css(dest)
} else {
try!(sides.0.to_css(dest));
try!(dest.write_str(" "));
try!(sides.1.to_css(dest));
try!(dest.write_str(" "));
try!(sides.2.to_css(dest));
try!(dest.write_str(" "));
sides.3.to_css(dest)
}
}

<%include file="/shorthand/serialize.mako.rs" />
<%include file="/shorthand/background.mako.rs" />
<%include file="/shorthand/border.mako.rs" />
<%include file="/shorthand/box.mako.rs" />
@@ -435,18 +408,14 @@ impl ToCss for PropertyDeclarationBlock {
}
}

enum AppendableValue<'a, I>
pub enum AppendableValue<'a, I>
where I: Iterator<Item=&'a PropertyDeclaration> {
Declaration(&'a PropertyDeclaration),
DeclarationsForShorthand(I),
DeclarationsForShorthand(Shorthand, I),
Css(&'a str)
}

fn append_property_name<W>(dest: &mut W,
property_name: &str,
is_first_serialization: &mut bool)
-> fmt::Result where W: fmt::Write {

fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result where W: fmt::Write {
// after first serialization(key: value;) add whitespace between the pairs
if !*is_first_serialization {
try!(write!(dest, " "));
@@ -455,7 +424,7 @@ fn append_property_name<W>(dest: &mut W,
*is_first_serialization = false;
}

write!(dest, "{}", property_name)
Ok(())
}

fn append_declaration_value<'a, W, I>
@@ -471,15 +440,8 @@ fn append_declaration_value<'a, W, I>
AppendableValue::Declaration(decl) => {
try!(decl.to_css(dest));
},
AppendableValue::DeclarationsForShorthand(decls) => {
let mut decls = decls.peekable();
while let Some(decl) = decls.next() {
try!(decl.to_css(dest));

if decls.peek().is_some() {
try!(write!(dest, " "));
}
}
AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
try!(shorthand.longhands_to_css(decls, dest));
}
}

@@ -498,8 +460,15 @@ fn append_serialization<'a, W, I>(dest: &mut W,
-> fmt::Result
where W: fmt::Write, I: Iterator<Item=&'a PropertyDeclaration> {

try!(append_property_name(dest, property_name, is_first_serialization));
try!(write!(dest, ":"));
try!(handle_first_serialization(dest, is_first_serialization));

// Overflow does not behave like a normal shorthand. When overflow-x and overflow-y are not of equal
// values, they no longer use the shared property name "overflow" and must be handled differently
if shorthands::is_overflow_shorthand(&appendable_value) {
return append_declaration_value(dest, appendable_value, is_important);
}

write!(dest, "{}:", property_name);

// for normal parsed values, add a space between key: and value
match &appendable_value {
@@ -512,7 +481,7 @@ fn append_serialization<'a, W, I>(dest: &mut W,
try!(write!(dest, " "));
}
},
&AppendableValue::DeclarationsForShorthand(_) => try!(write!(dest, " "))
&AppendableValue::DeclarationsForShorthand(..) => try!(write!(dest, " "))
}

try!(append_declaration_value(dest, appendable_value, is_important));
@@ -691,6 +660,20 @@ impl Shorthand {
}
}

pub fn longhands_to_css<'a, W, I>(&self, declarations: I, dest: &mut W) -> fmt::Result
where W: fmt::Write, I: Iterator<Item=&'a PropertyDeclaration> {
match *self {
% for property in data.shorthands:
Shorthand::${property.camel_case} => {
match shorthands::${property.ident}::LonghandsToSerialize::from_iter(declarations) {
Ok(longhands) => longhands.to_css(dest),
Err(_) => Err(fmt::Error)
}
},
% endfor
}
}

/// Serializes possible shorthand value to String.
pub fn serialize_shorthand_value_to_string<'a, I>(self, declarations: I, is_important: bool) -> String
where I: Iterator<Item=&'a PropertyDeclaration> + Clone {
@@ -747,10 +730,7 @@ impl Shorthand {
}

if !declarations3.any(|d| d.with_variables()) {
return Some(AppendableValue::DeclarationsForShorthand(declarations));
// FIXME: this needs property-specific code, which probably should be in style/
// "as appropriate according to the grammar of shorthand "
// https://drafts.csswg.org/cssom/#serialize-a-css-value
return Some(AppendableValue::DeclarationsForShorthand(self, declarations));
}

None
Oops, something went wrong.

0 comments on commit 3831c06

Please sign in to comment.
You can’t perform that action at this time.