Update PropertyDeclarationBlock::to_css so that the iteration of

possible shorthands matches the linked spec.

Previously substep 5 attempted to serialize the complete shorthand
declaration and substep 6 skipped to the next shorthand only if the
current shorthand was not serialized, but this did not catch empty
serializations. The spec on the other hand specifically says that the
*value* should be evaluated first and if the value is empty substep 6
should skip to the next shorthand - which is what happens now.

To do this required some refactoring which mostly simplifies the code.
Specifically:
 - append_declaration_value was refactored so that importance is not
   required as a arg (by moving it to the end of append_serialization)
   and is_overflow_with_name was removed as an arg also (initially I
   refactored it elsewhere, but it turns out it's no longer required at
   all - more below). With these changes, append_declaration_value can
   be used within the algorithm for to_css to obtain just the value for
   substep 5.
 - Substeps 7 and 8 of the algorithm become explicit (they were implicit
   before) by passing the value, shorthand and importance to
   append_serialization.
 - serialize_shorthand_to_buffer is no longer required (as the algorithm
   serializes the value first instead, as per the spec.

A surprising result of this was that I could also remove a lot of code
handling the special case of the overflow properties serialization. This
is because the overflow's LonghandToCss implementation of
to_css_declared already does the right thing according to the spec - it
writes the single value if both overflow-x and -y are equal, and
writes nothing otherwise - so that the algorithm now skips that shorthand
instead rendering the longhands.
This commit is contained in:
Michael Nelson 2017-02-22 20:58:33 +11:00
parent 854d720b21
commit a0998d30d4
4 changed files with 36 additions and 141 deletions

View file

@ -128,10 +128,9 @@ impl PropertyDeclarationBlock {
// Step 1.2.3
// We don't print !important when serializing individual properties,
// so we treat this as a normal-importance property
let importance = Importance::Normal;
match shorthand.get_shorthand_appendable_value(list) {
Some(appendable_value) =>
append_declaration_value(dest, appendable_value, importance, false),
append_declaration_value(dest, appendable_value),
None => return Ok(()),
}
}
@ -343,23 +342,28 @@ impl ToCss for PropertyDeclarationBlock {
Importance::Normal
};
// Substep 5
let was_serialized =
try!(
shorthand.serialize_shorthand_to_buffer(
dest,
current_longhands.iter().cloned(),
&mut is_first_serialization,
importance
)
);
// If serialization occured, Substep 7 & 8 will have been completed
// Substep 5 - Let value be the result of invoking serialize a CSS
// value of current longhands.
let mut value = String::from("");
match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) {
None => continue,
Some(appendable_value) => {
// Also demo test of overflow with important - I think it'll not
// be correct.
try!(append_declaration_value(&mut value, appendable_value));
}
}
// Substep 6
if !was_serialized {
continue;
if value == "" {
continue
}
// Substeps 7 and 8
try!(append_serialization::<W, Cloned<slice::Iter< &PropertyDeclaration>>, _>(
dest, &shorthand, AppendableValue::Css(&value), importance,
&mut is_first_serialization));
for current_longhand in current_longhands {
// Substep 9
already_serialized.push(current_longhand.id());
@ -434,31 +438,22 @@ fn handle_first_serialization<W>(dest: &mut W,
/// Append a given kind of appendable value to a serialization.
pub fn append_declaration_value<'a, W, I>(dest: &mut W,
appendable_value: AppendableValue<'a, I>,
importance: Importance,
is_overflow_with_name: bool)
appendable_value: AppendableValue<'a, I>)
-> fmt::Result
where W: fmt::Write,
I: Iterator<Item=&'a PropertyDeclaration>,
{
match appendable_value {
// Should be able to use this enum to pass the already serialized css?
AppendableValue::Css(css) => {
try!(write!(dest, "{}", css))
},
AppendableValue::Declaration(decl) => {
try!(decl.to_css(dest));
},
AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
if is_overflow_with_name {
try!(shorthand.overflow_longhands_to_css(decls, dest));
} else {
try!(shorthand.longhands_to_css(decls, dest));
}
}
}
if importance.important() {
try!(write!(dest, " !important"));
},
AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
try!(shorthand.longhands_to_css(decls, dest));
}
}
Ok(())
@ -477,12 +472,6 @@ pub fn append_serialization<'a, W, I, N>(dest: &mut W,
{
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, importance, true);
}
try!(property_name.to_css(dest));
try!(dest.write_char(':'));
@ -500,7 +489,12 @@ pub fn append_serialization<'a, W, I, N>(dest: &mut W,
&AppendableValue::DeclarationsForShorthand(..) => try!(write!(dest, " "))
}
try!(append_declaration_value(dest, appendable_value, importance, false));
try!(append_declaration_value(dest, appendable_value));
if importance.important() {
try!(write!(dest, " !important"));
}
write!(dest, ";")
}