mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
style: Tidy and document the declaration_block module.
This commit is contained in:
parent
62ff467be8
commit
5241fa35ab
1 changed files with 97 additions and 47 deletions
|
@ -2,6 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! A property declaration block.
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use cssparser::{DeclarationListParser, parse_important};
|
use cssparser::{DeclarationListParser, parse_important};
|
||||||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
|
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
|
||||||
use error_reporting::ParseErrorReporter;
|
use error_reporting::ParseErrorReporter;
|
||||||
|
@ -13,7 +17,9 @@ use style_traits::ToCss;
|
||||||
use stylesheets::Origin;
|
use stylesheets::Origin;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
/// A declaration [importance][importance].
|
||||||
|
///
|
||||||
|
/// [importance]: https://drafts.csswg.org/css-cascade/#importance
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Importance {
|
pub enum Importance {
|
||||||
|
@ -25,6 +31,7 @@ pub enum Importance {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Importance {
|
impl Importance {
|
||||||
|
/// Return whether this is an important declaration.
|
||||||
pub fn important(self) -> bool {
|
pub fn important(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Importance::Normal => false,
|
Importance::Normal => false,
|
||||||
|
@ -34,10 +41,12 @@ impl Importance {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Overridden declarations are skipped.
|
/// Overridden declarations are skipped.
|
||||||
// FIXME (https://github.com/servo/servo/issues/3426)
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct PropertyDeclarationBlock {
|
pub struct PropertyDeclarationBlock {
|
||||||
|
/// The group of declarations, along with their importance.
|
||||||
|
///
|
||||||
|
/// Only deduplicated declarations appear here.
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "#7038")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "#7038")]
|
||||||
pub declarations: Vec<(PropertyDeclaration, Importance)>,
|
pub declarations: Vec<(PropertyDeclaration, Importance)>,
|
||||||
|
|
||||||
|
@ -64,6 +73,9 @@ impl PropertyDeclarationBlock {
|
||||||
self.declarations.len() > self.important_count as usize
|
self.declarations.len() > self.important_count as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a declaration for a given property.
|
||||||
|
///
|
||||||
|
/// NOTE: This is linear time.
|
||||||
pub fn get(&self, property: PropertyDeclarationId) -> Option< &(PropertyDeclaration, Importance)> {
|
pub fn get(&self, property: PropertyDeclarationId) -> Option< &(PropertyDeclaration, Importance)> {
|
||||||
self.declarations.iter().find(|&&(ref decl, _)| decl.id() == property)
|
self.declarations.iter().find(|&&(ref decl, _)| decl.id() == property)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +84,8 @@ impl PropertyDeclarationBlock {
|
||||||
///
|
///
|
||||||
/// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
|
/// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
|
||||||
pub fn property_value_to_css<W>(&self, property: &PropertyId, dest: &mut W) -> fmt::Result
|
pub fn property_value_to_css<W>(&self, property: &PropertyId, dest: &mut W) -> fmt::Result
|
||||||
where W: fmt::Write {
|
where W: fmt::Write,
|
||||||
|
{
|
||||||
// Step 1: done when parsing a string to PropertyId
|
// Step 1: done when parsing a string to PropertyId
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
|
@ -149,7 +162,11 @@ impl PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_parsed_declaration(&mut self, declaration: PropertyDeclaration, importance: Importance) {
|
/// Adds or overrides the declaration for a given property in this block,
|
||||||
|
/// without taking into account any kind of priority.
|
||||||
|
pub fn set_parsed_declaration(&mut self,
|
||||||
|
declaration: PropertyDeclaration,
|
||||||
|
importance: Importance) {
|
||||||
for slot in &mut *self.declarations {
|
for slot in &mut *self.declarations {
|
||||||
if slot.0.id() == declaration.id() {
|
if slot.0.id() == declaration.id() {
|
||||||
match (slot.1, importance) {
|
match (slot.1, importance) {
|
||||||
|
@ -172,6 +189,7 @@ impl PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the declaration importance for a given property, if found.
|
||||||
pub fn set_importance(&mut self, property: &PropertyId, new_importance: Importance) {
|
pub fn set_importance(&mut self, property: &PropertyId, new_importance: Importance) {
|
||||||
for &mut (ref declaration, ref mut importance) in &mut self.declarations {
|
for &mut (ref declaration, ref mut importance) in &mut self.declarations {
|
||||||
if declaration.id().is_or_is_longhand_of(property) {
|
if declaration.id().is_or_is_longhand_of(property) {
|
||||||
|
@ -203,7 +221,8 @@ impl PropertyDeclarationBlock {
|
||||||
|
|
||||||
/// Take a declaration block known to contain a single property and serialize it.
|
/// Take a declaration block known to contain a single property and serialize it.
|
||||||
pub fn single_value_to_css<W>(&self, property: &PropertyId, dest: &mut W) -> fmt::Result
|
pub fn single_value_to_css<W>(&self, property: &PropertyId, dest: &mut W) -> fmt::Result
|
||||||
where W: fmt::Write {
|
where W: fmt::Write,
|
||||||
|
{
|
||||||
match property.as_shorthand() {
|
match property.as_shorthand() {
|
||||||
Err(_longhand_or_custom) => {
|
Err(_longhand_or_custom) => {
|
||||||
if self.declarations.len() == 1 {
|
if self.declarations.len() == 1 {
|
||||||
|
@ -236,7 +255,9 @@ impl PropertyDeclarationBlock {
|
||||||
|
|
||||||
impl ToCss for PropertyDeclarationBlock {
|
impl ToCss for PropertyDeclarationBlock {
|
||||||
// https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block
|
// https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||||
|
where W: fmt::Write,
|
||||||
|
{
|
||||||
let mut is_first_serialization = true; // trailing serializations should have a prepended space
|
let mut is_first_serialization = true; // trailing serializations should have a prepended space
|
||||||
|
|
||||||
// Step 1 -> dest = result list
|
// Step 1 -> dest = result list
|
||||||
|
@ -356,15 +377,28 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A convenient enum to represent different kinds of stuff that can represent a
|
||||||
|
/// _value_ in the serialization of a property declaration.
|
||||||
pub enum AppendableValue<'a, I>
|
pub enum AppendableValue<'a, I>
|
||||||
where I: Iterator<Item=&'a PropertyDeclaration> {
|
where I: Iterator<Item=&'a PropertyDeclaration>,
|
||||||
|
{
|
||||||
|
/// A given declaration, of which we'll serialize just the value.
|
||||||
Declaration(&'a PropertyDeclaration),
|
Declaration(&'a PropertyDeclaration),
|
||||||
|
/// A set of declarations for a given shorthand.
|
||||||
|
///
|
||||||
|
/// FIXME: This needs more docs, where are the shorthands expanded? We print
|
||||||
|
/// the property name before-hand, don't we?
|
||||||
DeclarationsForShorthand(ShorthandId, I),
|
DeclarationsForShorthand(ShorthandId, I),
|
||||||
|
/// A raw CSS string, coming for example from a property with CSS variables.
|
||||||
Css(&'a str)
|
Css(&'a str)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result where W: fmt::Write {
|
/// Potentially appends whitespace after the first (property: value;) pair.
|
||||||
// after first serialization(key: value;) add whitespace between the pairs
|
fn handle_first_serialization<W>(dest: &mut W,
|
||||||
|
is_first_serialization: &mut bool)
|
||||||
|
-> fmt::Result
|
||||||
|
where W: fmt::Write,
|
||||||
|
{
|
||||||
if !*is_first_serialization {
|
if !*is_first_serialization {
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
} else {
|
} else {
|
||||||
|
@ -374,45 +408,48 @@ fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_declaration_value<'a, W, I>
|
/// Append a given kind of appendable value to a serialization.
|
||||||
(dest: &mut W,
|
pub fn append_declaration_value<'a, W, I>(dest: &mut W,
|
||||||
appendable_value: AppendableValue<'a, I>,
|
appendable_value: AppendableValue<'a, I>,
|
||||||
importance: Importance,
|
importance: Importance,
|
||||||
is_overflow_with_name: bool)
|
is_overflow_with_name: bool)
|
||||||
-> fmt::Result
|
-> fmt::Result
|
||||||
where W: fmt::Write, I: Iterator<Item=&'a PropertyDeclaration> {
|
|
||||||
match appendable_value {
|
|
||||||
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_serialization<'a, W, I, N>(dest: &mut W,
|
|
||||||
property_name: &N,
|
|
||||||
appendable_value: AppendableValue<'a, I>,
|
|
||||||
importance: Importance,
|
|
||||||
is_first_serialization: &mut bool)
|
|
||||||
-> fmt::Result
|
|
||||||
where W: fmt::Write,
|
where W: fmt::Write,
|
||||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
I: Iterator<Item=&'a PropertyDeclaration>,
|
||||||
N: ToCss
|
{
|
||||||
|
match appendable_value {
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Append a given property and value pair to a serialization.
|
||||||
|
pub fn append_serialization<'a, W, I, N>(dest: &mut W,
|
||||||
|
property_name: &N,
|
||||||
|
appendable_value: AppendableValue<'a, I>,
|
||||||
|
importance: Importance,
|
||||||
|
is_first_serialization: &mut bool)
|
||||||
|
-> fmt::Result
|
||||||
|
where W: fmt::Write,
|
||||||
|
I: Iterator<Item=&'a PropertyDeclaration>,
|
||||||
|
N: ToCss,
|
||||||
{
|
{
|
||||||
try!(handle_first_serialization(dest, is_first_serialization));
|
try!(handle_first_serialization(dest, is_first_serialization));
|
||||||
|
|
||||||
|
@ -443,6 +480,8 @@ pub fn append_serialization<'a, W, I, N>(dest: &mut W,
|
||||||
write!(dest, ";")
|
write!(dest, ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper to parse the style attribute of an element, in order for this to be
|
||||||
|
/// shared between Servo and Gecko.
|
||||||
pub fn parse_style_attribute(input: &str,
|
pub fn parse_style_attribute(input: &str,
|
||||||
base_url: &ServoUrl,
|
base_url: &ServoUrl,
|
||||||
error_reporter: StdBox<ParseErrorReporter + Send>,
|
error_reporter: StdBox<ParseErrorReporter + Send>,
|
||||||
|
@ -452,6 +491,8 @@ pub fn parse_style_attribute(input: &str,
|
||||||
parse_property_declaration_list(&context, &mut Parser::new(input))
|
parse_property_declaration_list(&context, &mut Parser::new(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a given property declaration. Can result in multiple
|
||||||
|
/// `PropertyDeclaration`s when expanding a longhand, for example.
|
||||||
pub fn parse_one_declaration(id: PropertyId,
|
pub fn parse_one_declaration(id: PropertyId,
|
||||||
input: &str,
|
input: &str,
|
||||||
base_url: &ServoUrl,
|
base_url: &ServoUrl,
|
||||||
|
@ -466,6 +507,7 @@ pub fn parse_one_declaration(id: PropertyId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A struct to parse property declarations.
|
||||||
struct PropertyDeclarationParser<'a, 'b: 'a> {
|
struct PropertyDeclarationParser<'a, 'b: 'a> {
|
||||||
context: &'a ParserContext<'b>,
|
context: &'a ParserContext<'b>,
|
||||||
}
|
}
|
||||||
|
@ -479,6 +521,11 @@ impl<'a, 'b> AtRuleParser for PropertyDeclarationParser<'a, 'b> {
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
|
impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
|
||||||
|
/// A single declaration may be expanded into multiple ones if it's a
|
||||||
|
/// shorthand for example, so that's why this is a vector.
|
||||||
|
///
|
||||||
|
/// TODO(emilio): Seems like there's potentially a bunch of performance work
|
||||||
|
/// we could do here.
|
||||||
type Declaration = (Vec<PropertyDeclaration>, Importance);
|
type Declaration = (Vec<PropertyDeclaration>, Importance);
|
||||||
|
|
||||||
fn parse_value(&mut self, name: &str, input: &mut Parser)
|
fn parse_value(&mut self, name: &str, input: &mut Parser)
|
||||||
|
@ -500,7 +547,10 @@ impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_property_declaration_list(context: &ParserContext, input: &mut Parser)
|
/// Parse a list of property declarations and return a property declaration
|
||||||
|
/// block.
|
||||||
|
pub fn parse_property_declaration_list(context: &ParserContext,
|
||||||
|
input: &mut Parser)
|
||||||
-> PropertyDeclarationBlock {
|
-> PropertyDeclarationBlock {
|
||||||
let mut declarations = Vec::new();
|
let mut declarations = Vec::new();
|
||||||
let mut important_count = 0;
|
let mut important_count = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue