mirror of
https://github.com/servo/servo.git
synced 2025-08-12 00:45:33 +01:00
Update rustc to revision 3dcd2157403163789aaf21a9ab3c4d30a7c6494d.
This commit is contained in:
parent
b8900782b0
commit
466faac2a5
223 changed files with 4414 additions and 4105 deletions
|
@ -8,8 +8,8 @@ use errors::{ErrorLoggerIterator, log_css_error};
|
|||
use std::ascii::AsciiExt;
|
||||
use parsing_utils::{BufferedIter, ParserIter, parse_slice_comma_separated};
|
||||
use properties::longhands::font_family::parse_one_family;
|
||||
use properties::computed_values::font_family::FamilyName;
|
||||
use stylesheets::{CSSRule, CSSFontFaceRule, CSSStyleRule, CSSMediaRule};
|
||||
use properties::computed_values::font_family::FontFamily::FamilyName;
|
||||
use stylesheets::CSSRule;
|
||||
use media_queries::Device;
|
||||
use url::{Url, UrlParser};
|
||||
|
||||
|
@ -18,11 +18,11 @@ pub fn iter_font_face_rules_inner(rules: &[CSSRule], device: &Device,
|
|||
callback: |family: &str, source: &Source|) {
|
||||
for rule in rules.iter() {
|
||||
match *rule {
|
||||
CSSStyleRule(_) => {},
|
||||
CSSMediaRule(ref rule) => if rule.media_queries.evaluate(device) {
|
||||
CSSRule::Style(_) => {},
|
||||
CSSRule::Media(ref rule) => if rule.media_queries.evaluate(device) {
|
||||
iter_font_face_rules_inner(rule.rules.as_slice(), device, |f, s| callback(f, s))
|
||||
},
|
||||
CSSFontFaceRule(ref rule) => {
|
||||
CSSRule::FontFace(ref rule) => {
|
||||
for source in rule.sources.iter() {
|
||||
callback(rule.family.as_slice(), source)
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ pub fn iter_font_face_rules_inner(rules: &[CSSRule], device: &Device,
|
|||
|
||||
#[deriving(Clone)]
|
||||
pub enum Source {
|
||||
UrlSource_(UrlSource),
|
||||
LocalSource(String),
|
||||
Url(UrlSource),
|
||||
Local(String),
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
|
@ -67,9 +67,9 @@ pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec<CSSRule>, base_
|
|||
|
||||
for item in ErrorLoggerIterator(parse_declaration_list(block.into_iter())) {
|
||||
match item {
|
||||
DeclAtRule(rule) => log_css_error(
|
||||
DeclarationListItem::AtRule(rule) => log_css_error(
|
||||
rule.location, format!("Unsupported at-rule in declaration list: @{:s}", rule.name).as_slice()),
|
||||
Declaration_(Declaration{ location, name, value, important }) => {
|
||||
DeclarationListItem::Declaration(Declaration{ location, name, value, important }) => {
|
||||
if important {
|
||||
log_css_error(location, "!important is not allowed on @font-face descriptors");
|
||||
continue
|
||||
|
@ -102,7 +102,7 @@ pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec<CSSRule>, base_
|
|||
}
|
||||
|
||||
match (maybe_family, maybe_sources) {
|
||||
(Some(family), Some(sources)) => parent_rules.push(CSSFontFaceRule(FontFaceRule {
|
||||
(Some(family), Some(sources)) => parent_rules.push(CSSRule::FontFace(FontFaceRule {
|
||||
family: family,
|
||||
sources: sources,
|
||||
})),
|
||||
|
@ -124,7 +124,7 @@ fn parse_one_src(iter: ParserIter, base_url: &Url) -> Result<Source, ()> {
|
|||
if name.as_slice().eq_ignore_ascii_case("local") {
|
||||
let iter = &mut BufferedIter::new(arguments.as_slice().skip_whitespace());
|
||||
match parse_one_family(iter) {
|
||||
Ok(FamilyName(name)) => return Ok(LocalSource(name)),
|
||||
Ok(FamilyName(name)) => return Ok(Source::Local(name)),
|
||||
_ => return Err(())
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ fn parse_one_src(iter: ParserIter, base_url: &Url) -> Result<Source, ()> {
|
|||
None => vec![],
|
||||
};
|
||||
|
||||
Ok(UrlSource_(UrlSource {
|
||||
Ok(Source::Url(UrlSource {
|
||||
url: url,
|
||||
format_hints: format_hints,
|
||||
}))
|
||||
|
|
|
@ -5,29 +5,32 @@
|
|||
//! Legacy presentational attributes defined in the HTML5 specification: `<td width>`,
|
||||
//! `<input size>`, and so forth.
|
||||
|
||||
use self::UnsignedIntegerAttribute::*;
|
||||
use self::SimpleColorAttribute::*;
|
||||
|
||||
use node::{TElement, TElementAttributes, TNode};
|
||||
use properties::{BackgroundColorDeclaration, BorderBottomWidthDeclaration, CSSFloat};
|
||||
use properties::{BorderLeftWidthDeclaration, BorderRightWidthDeclaration, HeightDeclaration};
|
||||
use properties::{BorderTopWidthDeclaration, SpecifiedValue, WidthDeclaration, specified};
|
||||
use properties::DeclaredValue::SpecifiedValue;
|
||||
use properties::PropertyDeclaration::*;
|
||||
use properties::{CSSFloat, specified};
|
||||
use selector_matching::{DeclarationBlock, Stylist};
|
||||
|
||||
use cssparser::RGBAColor;
|
||||
use cssparser::Color;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::smallvec::VecLike;
|
||||
use servo_util::str::{AutoLpa, LengthLpa, PercentageLpa};
|
||||
use servo_util::str::LengthOrPercentageOrAuto;
|
||||
|
||||
/// Legacy presentational attributes that take a length as defined in HTML5 § 2.4.4.4.
|
||||
pub enum LengthAttribute {
|
||||
/// `<td width>`
|
||||
WidthLengthAttribute,
|
||||
Width,
|
||||
}
|
||||
|
||||
/// Legacy presentational attributes that take an integer as defined in HTML5 § 2.4.4.2.
|
||||
pub enum IntegerAttribute {
|
||||
/// `<input size>`
|
||||
SizeIntegerAttribute,
|
||||
ColsIntegerAttribute,
|
||||
RowsIntegerAttribute,
|
||||
Size,
|
||||
Cols,
|
||||
Rows,
|
||||
}
|
||||
|
||||
/// Legacy presentational attributes that take a nonnegative integer as defined in HTML5 § 2.4.4.2.
|
||||
|
@ -100,16 +103,16 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
let element = node.as_element();
|
||||
match element.get_local_name() {
|
||||
name if *name == atom!("td") => {
|
||||
match element.get_length_attribute(WidthLengthAttribute) {
|
||||
AutoLpa => {}
|
||||
PercentageLpa(percentage) => {
|
||||
let width_value = specified::LPA_Percentage(percentage);
|
||||
match element.get_length_attribute(LengthAttribute::Width) {
|
||||
LengthOrPercentageOrAuto::Auto => {}
|
||||
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
||||
let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
WidthDeclaration(SpecifiedValue(width_value))));
|
||||
*shareable = false
|
||||
}
|
||||
LengthLpa(length) => {
|
||||
let width_value = specified::LPA_Length(specified::Au_(length));
|
||||
LengthOrPercentageOrAuto::Length(length) => {
|
||||
let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Au(length));
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
WidthDeclaration(SpecifiedValue(width_value))));
|
||||
*shareable = false
|
||||
|
@ -142,7 +145,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
shareable);
|
||||
}
|
||||
name if *name == atom!("input") => {
|
||||
match element.get_integer_attribute(SizeIntegerAttribute) {
|
||||
match element.get_integer_attribute(IntegerAttribute::Size) {
|
||||
Some(value) if value != 0 => {
|
||||
// Per HTML 4.01 § 17.4, this value is in characters if `type` is `text` or
|
||||
// `password` and in pixels otherwise.
|
||||
|
@ -150,12 +153,12 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
// FIXME(pcwalton): More use of atoms, please!
|
||||
let value = match element.get_attr(&ns!(""), &atom!("type")) {
|
||||
Some("text") | Some("password") => {
|
||||
specified::ServoCharacterWidth(value)
|
||||
specified::Length::ServoCharacterWidth(value)
|
||||
}
|
||||
_ => specified::Au_(Au::from_px(value as int)),
|
||||
_ => specified::Length::Au(Au::from_px(value as int)),
|
||||
};
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
WidthDeclaration(SpecifiedValue(specified::LPA_Length(
|
||||
WidthDeclaration(SpecifiedValue(specified::LengthOrPercentageOrAuto::Length(
|
||||
value)))));
|
||||
*shareable = false
|
||||
}
|
||||
|
@ -163,29 +166,29 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
}
|
||||
}
|
||||
name if *name == atom!("textarea") => {
|
||||
match element.get_integer_attribute(ColsIntegerAttribute) {
|
||||
match element.get_integer_attribute(IntegerAttribute::Cols) {
|
||||
Some(value) if value != 0 => {
|
||||
// TODO(mttr) ServoCharacterWidth uses the size math for <input type="text">, but
|
||||
// the math for <textarea> is a little different since we need to take
|
||||
// scrollbar size into consideration (but we don't have a scrollbar yet!)
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-width
|
||||
let value = specified::ServoCharacterWidth(value);
|
||||
let value = specified::Length::ServoCharacterWidth(value);
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
WidthDeclaration(SpecifiedValue(specified::LPA_Length(
|
||||
WidthDeclaration(SpecifiedValue(specified::LengthOrPercentageOrAuto::Length(
|
||||
value)))));
|
||||
*shareable = false
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
match element.get_integer_attribute(RowsIntegerAttribute) {
|
||||
match element.get_integer_attribute(IntegerAttribute::Rows) {
|
||||
Some(value) if value != 0 => {
|
||||
// TODO(mttr) This should take scrollbar size into consideration.
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-height
|
||||
let value = specified::Em(value as CSSFloat);
|
||||
let value = specified::Length::Em(value as CSSFloat);
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
HeightDeclaration(SpecifiedValue(specified::LPA_Length(
|
||||
HeightDeclaration(SpecifiedValue(specified::LengthOrPercentageOrAuto::Length(
|
||||
value)))));
|
||||
*shareable = false
|
||||
}
|
||||
|
@ -211,7 +214,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
None => {}
|
||||
Some(color) => {
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
BackgroundColorDeclaration(SpecifiedValue(RGBAColor(color)))));
|
||||
BackgroundColorDeclaration(SpecifiedValue(Color::RGBA(color)))));
|
||||
*shareable = false
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +232,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
match element.get_unsigned_integer_attribute(BorderUnsignedIntegerAttribute) {
|
||||
None => {}
|
||||
Some(length) => {
|
||||
let width_value = specified::Au_(Au::from_px(length as int));
|
||||
let width_value = specified::Length::Au(Au::from_px(length as int));
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
BorderTopWidthDeclaration(SpecifiedValue(width_value))));
|
||||
matching_rules_list.vec_push(DeclarationBlock::from_declaration(
|
||||
|
|
|
@ -34,12 +34,11 @@ extern crate "util" as servo_util;
|
|||
|
||||
|
||||
// Public API
|
||||
pub use media_queries::{Device, Screen};
|
||||
pub use media_queries::{Device, MediaType};
|
||||
pub use stylesheets::{Stylesheet, iter_font_face_rules};
|
||||
pub use selector_matching::{Stylist, StylesheetOrigin, UserAgentOrigin, AuthorOrigin, UserOrigin};
|
||||
pub use selector_matching::{Stylist, StylesheetOrigin};
|
||||
pub use selector_matching::{DeclarationBlock, CommonStyleAffectingAttributes};
|
||||
pub use selector_matching::{CommonStyleAffectingAttributeInfo, CommonStyleAffectingAttributeMode};
|
||||
pub use selector_matching::{AttrIsPresentMode, AttrIsEqualMode};
|
||||
pub use selector_matching::{matches, matches_simple_selector, common_style_affecting_attributes};
|
||||
pub use selector_matching::{rare_style_affecting_attributes};
|
||||
pub use selector_matching::{RECOMMENDED_SELECTOR_BLOOM_FILTER_SIZE, SELECTOR_WHITESPACE};
|
||||
|
@ -47,18 +46,16 @@ pub use properties::{cascade, cascade_anonymous, computed};
|
|||
pub use properties::{PropertyDeclaration, ComputedValues, computed_values, style_structs};
|
||||
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
||||
pub use properties::{CSSFloat, DeclaredValue, PropertyDeclarationParseResult};
|
||||
pub use properties::{Angle, AngleOrCorner, AngleAoc, CornerAoc};
|
||||
pub use properties::{Left, Right, Bottom, Top};
|
||||
pub use properties::{Angle, AngleOrCorner};
|
||||
pub use properties::{HorizontalDirection, VerticalDirection};
|
||||
pub use node::{TElement, TElementAttributes, TNode};
|
||||
pub use selectors::{PseudoElement, Before, After, ParserContext, SelectorList};
|
||||
pub use selectors::{AttrSelector, NamespaceConstraint, SpecificNamespace, AnyNamespace};
|
||||
pub use selectors::{SimpleSelector, LocalNameSelector, parse_selector_list_from_str};
|
||||
pub use selectors::{PseudoElement, ParserContext, SelectorList};
|
||||
pub use selectors::{AttrSelector, NamespaceConstraint};
|
||||
pub use selectors::{SimpleSelector, parse_selector_list_from_str};
|
||||
pub use cssparser::{Color, RGBA};
|
||||
pub use legacy::{BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute};
|
||||
pub use legacy::{ColSpanUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute};
|
||||
pub use legacy::{SimpleColorAttribute, SizeIntegerAttribute, UnsignedIntegerAttribute};
|
||||
pub use legacy::{WidthLengthAttribute, ColsIntegerAttribute, RowsIntegerAttribute};
|
||||
pub use font_face::{Source, LocalSource, UrlSource_};
|
||||
pub use legacy::{IntegerAttribute, LengthAttribute};
|
||||
pub use legacy::{SimpleColorAttribute, UnsignedIntegerAttribute};
|
||||
pub use font_face::Source;
|
||||
|
||||
mod stylesheets;
|
||||
mod errors;
|
||||
|
|
|
@ -9,13 +9,12 @@ use cssparser::ast::*;
|
|||
use errors::{ErrorLoggerIterator, log_css_error};
|
||||
use geom::size::TypedSize2D;
|
||||
use selectors::ParserContext;
|
||||
use stylesheets::{CSSRule, CSSMediaRule};
|
||||
use stylesheets::{CSSRule, parse_style_rule, parse_nested_at_rule};
|
||||
use namespaces::NamespaceMap;
|
||||
use parsing_utils::{BufferedIter, ParserIter};
|
||||
use properties::common_types::*;
|
||||
use properties::longhands;
|
||||
use servo_util::geometry::ViewportPx;
|
||||
use stylesheets;
|
||||
use url::Url;
|
||||
|
||||
pub struct MediaRule {
|
||||
|
@ -36,9 +35,9 @@ pub enum Range<T> {
|
|||
impl<T: Ord> Range<T> {
|
||||
fn evaluate(&self, value: T) -> bool {
|
||||
match *self {
|
||||
Min(ref width) => { value >= *width },
|
||||
Max(ref width) => { value <= *width },
|
||||
//Eq(ref width) => { value == *width },
|
||||
Range::Min(ref width) => { value >= *width },
|
||||
Range::Max(ref width) => { value <= *width },
|
||||
//Range::Eq(ref width) => { value == *width },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +72,7 @@ impl MediaQuery {
|
|||
#[deriving(PartialEq)]
|
||||
pub enum MediaQueryType {
|
||||
All, // Always true
|
||||
MediaType_(MediaType),
|
||||
MediaType(MediaType),
|
||||
}
|
||||
|
||||
#[deriving(PartialEq)]
|
||||
|
@ -113,20 +112,19 @@ pub fn parse_media_rule(context: &ParserContext,
|
|||
let mut rules = vec!();
|
||||
for rule in ErrorLoggerIterator(parse_rule_list(block.into_iter())) {
|
||||
match rule {
|
||||
QualifiedRule_(rule) => {
|
||||
stylesheets::parse_style_rule(context, rule, &mut rules, namespaces, base_url)
|
||||
}
|
||||
AtRule_(rule) => {
|
||||
stylesheets::parse_nested_at_rule(context,
|
||||
rule.name.as_slice().to_ascii_lower().as_slice(),
|
||||
rule,
|
||||
&mut rules,
|
||||
namespaces,
|
||||
base_url)
|
||||
Rule::QualifiedRule(rule) => {
|
||||
parse_style_rule(context, rule, &mut rules, namespaces, base_url)
|
||||
}
|
||||
Rule::AtRule(rule) => parse_nested_at_rule(
|
||||
context,
|
||||
rule.name.as_slice().to_ascii_lower().as_slice(),
|
||||
rule,
|
||||
&mut rules,
|
||||
namespaces,
|
||||
base_url),
|
||||
}
|
||||
}
|
||||
parent_rules.push(CSSMediaRule(MediaRule {
|
||||
parent_rules.push(CSSRule::Media(MediaRule {
|
||||
media_queries: media_queries,
|
||||
rules: rules,
|
||||
}))
|
||||
|
@ -166,11 +164,11 @@ fn parse_media_query_expression(iter: ParserIter) -> Result<Expression, ()> {
|
|||
let expression = match variable.as_slice().to_ascii_lower().as_slice() {
|
||||
"min-width" => {
|
||||
let au = try!(parse_value_as_length(value));
|
||||
Width(Min(au))
|
||||
Expression::Width(Range::Min(au))
|
||||
}
|
||||
"max-width" => {
|
||||
let au = try!(parse_value_as_length(value));
|
||||
Width(Max(au))
|
||||
Expression::Width(Range::Max(au))
|
||||
}
|
||||
_ => return Err(())
|
||||
};
|
||||
|
@ -190,8 +188,8 @@ fn parse_media_query(iter: ParserIter) -> Result<MediaQuery, ()> {
|
|||
|
||||
// Check for optional 'only' or 'not'
|
||||
let qualifier = match iter.next() {
|
||||
Some(&Ident(ref value)) if value.as_slice().to_ascii_lower().as_slice() == "only" => Some(Only),
|
||||
Some(&Ident(ref value)) if value.as_slice().to_ascii_lower().as_slice() == "not" => Some(Not),
|
||||
Some(&Ident(ref value)) if value.as_slice().to_ascii_lower().as_slice() == "only" => Some(Qualifier::Only),
|
||||
Some(&Ident(ref value)) if value.as_slice().to_ascii_lower().as_slice() == "not" => Some(Qualifier::Not),
|
||||
Some(component_value) => {
|
||||
iter.push_back(component_value);
|
||||
None
|
||||
|
@ -203,10 +201,10 @@ fn parse_media_query(iter: ParserIter) -> Result<MediaQuery, ()> {
|
|||
let media_type = match iter.next() {
|
||||
Some(&Ident(ref value)) => {
|
||||
match value.as_slice().to_ascii_lower().as_slice() {
|
||||
"screen" => MediaType_(Screen),
|
||||
"print" => MediaType_(Print),
|
||||
"all" => All,
|
||||
_ => MediaType_(Unknown), // Unknown media types never match
|
||||
"screen" => MediaQueryType::MediaType(MediaType::Screen),
|
||||
"print" => MediaQueryType::MediaType(MediaType::Print),
|
||||
"all" => MediaQueryType::All,
|
||||
_ => MediaQueryType::MediaType(MediaType::Unknown), // Unknown media types never match
|
||||
}
|
||||
}
|
||||
Some(component_value) => {
|
||||
|
@ -220,7 +218,7 @@ fn parse_media_query(iter: ParserIter) -> Result<MediaQuery, ()> {
|
|||
let expression = try!(parse_media_query_expression(iter));
|
||||
expressions.push(expression);
|
||||
|
||||
All
|
||||
MediaQueryType::All
|
||||
}
|
||||
None => return Err(()),
|
||||
};
|
||||
|
@ -254,7 +252,7 @@ pub fn parse_media_query_list(input: &[ComponentValue]) -> MediaQueryList {
|
|||
let mut media_queries = vec!();
|
||||
|
||||
if iter.is_eof() {
|
||||
media_queries.push(MediaQuery::new(None, All, vec!()));
|
||||
media_queries.push(MediaQuery::new(None, MediaQueryType::All, vec!()));
|
||||
} else {
|
||||
loop {
|
||||
// Attempt to parse a media query.
|
||||
|
@ -278,7 +276,7 @@ pub fn parse_media_query_list(input: &[ComponentValue]) -> MediaQueryList {
|
|||
// Otherwise, create a 'not all' media query, that will never match.
|
||||
let media_query = match (media_query_result, trailing_tokens) {
|
||||
(Ok(media_query), false) => media_query,
|
||||
_ => MediaQuery::new(Some(Not), All, vec!()),
|
||||
_ => MediaQuery::new(Some(Qualifier::Not), MediaQueryType::All, vec!()),
|
||||
};
|
||||
media_queries.push(media_query);
|
||||
|
||||
|
@ -297,22 +295,22 @@ impl MediaQueryList {
|
|||
self.media_queries.iter().any(|mq| {
|
||||
// Check if media matches. Unknown media never matches.
|
||||
let media_match = match mq.media_type {
|
||||
MediaType_(Unknown) => false,
|
||||
MediaType_(media_type) => media_type == device.media_type,
|
||||
All => true,
|
||||
MediaQueryType::MediaType(MediaType::Unknown) => false,
|
||||
MediaQueryType::MediaType(media_type) => media_type == device.media_type,
|
||||
MediaQueryType::All => true,
|
||||
};
|
||||
|
||||
// Check if all conditions match (AND condition)
|
||||
let query_match = media_match && mq.expressions.iter().all(|expression| {
|
||||
match expression {
|
||||
&Width(value) => value.evaluate(
|
||||
&Expression::Width(value) => value.evaluate(
|
||||
Au::from_frac_px(device.viewport_size.to_untyped().width as f64)),
|
||||
}
|
||||
});
|
||||
|
||||
// Apply the logical NOT qualifier to the result
|
||||
match mq.qualifier {
|
||||
Some(Not) => !query_match,
|
||||
Some(Qualifier::Not) => !query_match,
|
||||
_ => query_match,
|
||||
}
|
||||
})
|
||||
|
@ -324,13 +322,14 @@ mod tests {
|
|||
use geom::size::TypedSize2D;
|
||||
use properties::common_types::*;
|
||||
use stylesheets::{iter_stylesheet_media_rules, iter_stylesheet_style_rules, Stylesheet};
|
||||
use selector_matching::AuthorOrigin;
|
||||
use selector_matching::StylesheetOrigin;
|
||||
use super::*;
|
||||
use url::Url;
|
||||
|
||||
fn test_media_rule(css: &str, callback: |&MediaQueryList, &str|) {
|
||||
let url = Url::parse("http://localhost").unwrap();
|
||||
let stylesheet = Stylesheet::from_str(css, url, AuthorOrigin);
|
||||
let stylesheet = Stylesheet::from_str(css, url,
|
||||
StylesheetOrigin::Author);
|
||||
let mut rule_count: int = 0;
|
||||
iter_stylesheet_media_rules(&stylesheet, |rule| {
|
||||
rule_count += 1;
|
||||
|
@ -341,7 +340,7 @@ mod tests {
|
|||
|
||||
fn media_query_test(device: &Device, css: &str, expected_rule_count: int) {
|
||||
let url = Url::parse("http://localhost").unwrap();
|
||||
let ss = Stylesheet::from_str(css, url, AuthorOrigin);
|
||||
let ss = Stylesheet::from_str(css, url, StylesheetOrigin::Author);
|
||||
let mut rule_count: int = 0;
|
||||
iter_stylesheet_style_rules(&ss, device, |_| rule_count += 1);
|
||||
assert!(rule_count == expected_rule_count, css.to_string());
|
||||
|
@ -353,7 +352,7 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -364,23 +363,23 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media only screen { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Only), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media not screen { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -391,23 +390,23 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == MediaType_(Print), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media only print { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Only), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Print), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media not print { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Print), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -418,23 +417,23 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == MediaType_(Unknown), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media only glass { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Only), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Unknown), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media not wood { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Unknown), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -445,23 +444,23 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media only all { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Only), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media not all { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -472,12 +471,12 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 2, css.to_string());
|
||||
let q0 = &list.media_queries[0];
|
||||
assert!(q0.qualifier == None, css.to_string());
|
||||
assert!(q0.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q0.expressions.len() == 0, css.to_string());
|
||||
|
||||
let q1 = &list.media_queries[1];
|
||||
assert!(q1.qualifier == None, css.to_string());
|
||||
assert!(q1.media_type == MediaType_(Print), css.to_string());
|
||||
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_string());
|
||||
assert!(q1.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -488,10 +487,10 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 1, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Min(w)) => assert!(w == Au::from_px(100)),
|
||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -500,10 +499,10 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 1, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Max(w)) => assert!(w == Au::from_px(43)),
|
||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(43)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -515,10 +514,10 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q.expressions.len() == 1, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Min(w)) => assert!(w == Au::from_px(100)),
|
||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -527,10 +526,10 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == MediaType_(Print), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_string());
|
||||
assert!(q.expressions.len() == 1, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Max(w)) => assert!(w == Au::from_px(43)),
|
||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(43)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -539,10 +538,10 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == MediaType_(Unknown), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_string());
|
||||
assert!(q.expressions.len() == 1, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Max(w)) => assert!(w == Au::from_px(52)),
|
||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(52)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -554,14 +553,14 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 2, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Min(w)) => assert!(w == Au::from_px(100)),
|
||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
match q.expressions[1] {
|
||||
Width(Max(w)) => assert!(w == Au::from_px(200)),
|
||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(200)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -569,15 +568,15 @@ mod tests {
|
|||
test_media_rule("@media not screen and (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q.expressions.len() == 2, css.to_string());
|
||||
match q.expressions[0] {
|
||||
Width(Min(w)) => assert!(w == Au::from_px(100)),
|
||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
match q.expressions[1] {
|
||||
Width(Max(w)) => assert!(w == Au::from_px(200)),
|
||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(200)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
@ -588,60 +587,60 @@ mod tests {
|
|||
test_media_rule("@media (min-width: 100blah) and (max-width: 200px) { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media screen and (height: 200px) { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media (min-width: 30em foo bar) {}", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media not {}", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media not (min-width: 300px) {}", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media , {}", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_string());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Not), css.to_string());
|
||||
assert!(q.media_type == All, css.to_string());
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
test_media_rule("@media screen 4px, print {}", |list, css| {
|
||||
assert!(list.media_queries.len() == 2, css.to_string());
|
||||
let q0 = &list.media_queries[0];
|
||||
assert!(q0.qualifier == Some(Not), css.to_string());
|
||||
assert!(q0.media_type == All, css.to_string());
|
||||
assert!(q0.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q0.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q0.expressions.len() == 0, css.to_string());
|
||||
let q1 = &list.media_queries[1];
|
||||
assert!(q1.qualifier == None, css.to_string());
|
||||
assert!(q1.media_type == MediaType_(Print), css.to_string());
|
||||
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_string());
|
||||
assert!(q1.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
|
||||
|
@ -649,11 +648,11 @@ mod tests {
|
|||
assert!(list.media_queries.len() == 2, css.to_string());
|
||||
let q0 = &list.media_queries[0];
|
||||
assert!(q0.qualifier == None, css.to_string());
|
||||
assert!(q0.media_type == MediaType_(Screen), css.to_string());
|
||||
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_string());
|
||||
assert!(q0.expressions.len() == 0, css.to_string());
|
||||
let q1 = &list.media_queries[1];
|
||||
assert!(q1.qualifier == Some(Not), css.to_string());
|
||||
assert!(q1.media_type == All, css.to_string());
|
||||
assert!(q1.qualifier == Some(Qualifier::Not), css.to_string());
|
||||
assert!(q1.media_type == MediaQueryType::All, css.to_string());
|
||||
assert!(q1.expressions.len() == 0, css.to_string());
|
||||
});
|
||||
}
|
||||
|
@ -661,7 +660,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_matching_simple() {
|
||||
let device = Device {
|
||||
media_type: Screen,
|
||||
media_type: MediaType::Screen,
|
||||
viewport_size: TypedSize2D(200.0, 100.0),
|
||||
};
|
||||
|
||||
|
@ -680,7 +679,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_matching_width() {
|
||||
let device = Device {
|
||||
media_type: Screen,
|
||||
media_type: MediaType::Screen,
|
||||
viewport_size: TypedSize2D(200.0, 100.0),
|
||||
};
|
||||
|
||||
|
@ -718,7 +717,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_matching_invalid() {
|
||||
let device = Device {
|
||||
media_type: Screen,
|
||||
media_type: MediaType::Screen,
|
||||
viewport_size: TypedSize2D(200.0, 100.0),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ pub mod specified {
|
|||
|
||||
#[deriving(Clone, Show)]
|
||||
pub enum Length {
|
||||
Au_(Au), // application units
|
||||
Au(Au), // application units
|
||||
Em(CSSFloat),
|
||||
Ex(CSSFloat),
|
||||
Rem(CSSFloat),
|
||||
|
@ -52,7 +52,7 @@ pub mod specified {
|
|||
match input {
|
||||
&Dimension(ref value, ref unit) if negative_ok || value.value >= 0.
|
||||
=> Length::parse_dimension(value.value, unit.as_slice()),
|
||||
&Number(ref value) if value.value == 0. => Ok(Au_(Au(0))),
|
||||
&Number(ref value) if value.value == 0. => Ok(Length::Au(Au(0))),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -66,38 +66,40 @@ pub mod specified {
|
|||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||
match unit.to_ascii_lower().as_slice() {
|
||||
"px" => Ok(Length::from_px(value)),
|
||||
"in" => Ok(Au_(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(Au_(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(Au_(Au((value * AU_PER_MM) as i32))),
|
||||
"pt" => Ok(Au_(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(Au_(Au((value * AU_PER_PC) as i32))),
|
||||
"em" => Ok(Em(value)),
|
||||
"ex" => Ok(Ex(value)),
|
||||
"rem" => Ok(Rem(value)),
|
||||
"in" => Ok(Length::Au(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(Length::Au(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(Length::Au(Au((value * AU_PER_MM) as i32))),
|
||||
"pt" => Ok(Length::Au(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(Length::Au(Au((value * AU_PER_PC) as i32))),
|
||||
"em" => Ok(Length::Em(value)),
|
||||
"ex" => Ok(Length::Ex(value)),
|
||||
"rem" => Ok(Length::Rem(value)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn from_px(px_value: CSSFloat) -> Length {
|
||||
Au_(Au((px_value * AU_PER_PX) as i32))
|
||||
Length::Au(Au((px_value * AU_PER_PX) as i32))
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Show)]
|
||||
pub enum LengthOrPercentage {
|
||||
LP_Length(Length),
|
||||
LP_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
Length(Length),
|
||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
}
|
||||
|
||||
impl LengthOrPercentage {
|
||||
fn parse_internal(input: &ComponentValue, negative_ok: bool)
|
||||
-> Result<LengthOrPercentage, ()> {
|
||||
match input {
|
||||
&Dimension(ref value, ref unit) if negative_ok || value.value >= 0.
|
||||
=> Length::parse_dimension(value.value, unit.as_slice()).map(LP_Length),
|
||||
&ast::Percentage(ref value) if negative_ok || value.value >= 0.
|
||||
=> Ok(LP_Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. => Ok(LP_Length(Au_(Au(0)))),
|
||||
&Dimension(ref value, ref unit) if negative_ok || value.value >= 0. =>
|
||||
Length::parse_dimension(value.value, unit.as_slice())
|
||||
.map(LengthOrPercentage::Length),
|
||||
&ast::Percentage(ref value) if negative_ok || value.value >= 0. =>
|
||||
Ok(LengthOrPercentage::Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. =>
|
||||
Ok(LengthOrPercentage::Length(Length::Au(Au(0)))),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -114,20 +116,22 @@ pub mod specified {
|
|||
|
||||
#[deriving(Clone)]
|
||||
pub enum LengthOrPercentageOrAuto {
|
||||
LPA_Length(Length),
|
||||
LPA_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
LPA_Auto,
|
||||
Length(Length),
|
||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
Auto,
|
||||
}
|
||||
impl LengthOrPercentageOrAuto {
|
||||
fn parse_internal(input: &ComponentValue, negative_ok: bool)
|
||||
-> Result<LengthOrPercentageOrAuto, ()> {
|
||||
match input {
|
||||
&Dimension(ref value, ref unit) if negative_ok || value.value >= 0.
|
||||
=> Length::parse_dimension(value.value, unit.as_slice()).map(LPA_Length),
|
||||
&ast::Percentage(ref value) if negative_ok || value.value >= 0.
|
||||
=> Ok(LPA_Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. => Ok(LPA_Length(Au_(Au(0)))),
|
||||
&Ident(ref value) if value.as_slice().eq_ignore_ascii_case("auto") => Ok(LPA_Auto),
|
||||
&Dimension(ref value, ref unit) if negative_ok || value.value >= 0. =>
|
||||
Length::parse_dimension(value.value, unit.as_slice()).map(LengthOrPercentageOrAuto::Length),
|
||||
&ast::Percentage(ref value) if negative_ok || value.value >= 0. =>
|
||||
Ok(LengthOrPercentageOrAuto::Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. =>
|
||||
Ok(LengthOrPercentageOrAuto::Length(Length::Au(Au(0)))),
|
||||
&Ident(ref value) if value.as_slice().eq_ignore_ascii_case("auto") =>
|
||||
Ok(LengthOrPercentageOrAuto::Auto),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -143,20 +147,20 @@ pub mod specified {
|
|||
|
||||
#[deriving(Clone)]
|
||||
pub enum LengthOrPercentageOrNone {
|
||||
LPN_Length(Length),
|
||||
LPN_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
LPN_None,
|
||||
Length(Length),
|
||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
None,
|
||||
}
|
||||
impl LengthOrPercentageOrNone {
|
||||
fn parse_internal(input: &ComponentValue, negative_ok: bool)
|
||||
-> Result<LengthOrPercentageOrNone, ()> {
|
||||
match input {
|
||||
&Dimension(ref value, ref unit) if negative_ok || value.value >= 0.
|
||||
=> Length::parse_dimension(value.value, unit.as_slice()).map(LPN_Length),
|
||||
=> Length::parse_dimension(value.value, unit.as_slice()).map(LengthOrPercentageOrNone::Length),
|
||||
&ast::Percentage(ref value) if negative_ok || value.value >= 0.
|
||||
=> Ok(LPN_Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. => Ok(LPN_Length(Au_(Au(0)))),
|
||||
&Ident(ref value) if value.as_slice().eq_ignore_ascii_case("none") => Ok(LPN_None),
|
||||
=> Ok(LengthOrPercentageOrNone::Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. => Ok(LengthOrPercentageOrNone::Length(Length::Au(Au(0)))),
|
||||
&Ident(ref value) if value.as_slice().eq_ignore_ascii_case("none") => Ok(LengthOrPercentageOrNone::None),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -174,27 +178,27 @@ pub mod specified {
|
|||
// http://dev.w3.org/csswg/css2/colors.html#propdef-background-position
|
||||
#[deriving(Clone)]
|
||||
pub enum PositionComponent {
|
||||
Pos_Length(Length),
|
||||
Pos_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
Pos_Center,
|
||||
Pos_Left,
|
||||
Pos_Right,
|
||||
Pos_Top,
|
||||
Pos_Bottom,
|
||||
Length(Length),
|
||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
Center,
|
||||
Left,
|
||||
Right,
|
||||
Top,
|
||||
Bottom,
|
||||
}
|
||||
impl PositionComponent {
|
||||
pub fn parse(input: &ComponentValue) -> Result<PositionComponent, ()> {
|
||||
match input {
|
||||
&Dimension(ref value, ref unit) =>
|
||||
Length::parse_dimension(value.value, unit.as_slice()).map(Pos_Length),
|
||||
&ast::Percentage(ref value) => Ok(Pos_Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. => Ok(Pos_Length(Au_(Au(0)))),
|
||||
Length::parse_dimension(value.value, unit.as_slice()).map(PositionComponent::Length),
|
||||
&ast::Percentage(ref value) => Ok(PositionComponent::Percentage(value.value / 100.)),
|
||||
&Number(ref value) if value.value == 0. => Ok(PositionComponent::Length(Length::Au(Au(0)))),
|
||||
&Ident(ref value) => {
|
||||
if value.as_slice().eq_ignore_ascii_case("center") { Ok(Pos_Center) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("left") { Ok(Pos_Left) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("right") { Ok(Pos_Right) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("top") { Ok(Pos_Top) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("bottom") { Ok(Pos_Bottom) }
|
||||
if value.as_slice().eq_ignore_ascii_case("center") { Ok(PositionComponent::Center) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("left") { Ok(PositionComponent::Left) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("right") { Ok(PositionComponent::Right) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("top") { Ok(PositionComponent::Top) }
|
||||
else if value.as_slice().eq_ignore_ascii_case("bottom") { Ok(PositionComponent::Bottom) }
|
||||
else { Err(()) }
|
||||
}
|
||||
_ => Err(())
|
||||
|
@ -203,11 +207,11 @@ pub mod specified {
|
|||
#[inline]
|
||||
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
||||
match self {
|
||||
Pos_Length(x) => LP_Length(x),
|
||||
Pos_Percentage(x) => LP_Percentage(x),
|
||||
Pos_Center => LP_Percentage(0.5),
|
||||
Pos_Left | Pos_Top => LP_Percentage(0.0),
|
||||
Pos_Right | Pos_Bottom => LP_Percentage(1.0),
|
||||
PositionComponent::Length(x) => LengthOrPercentage::Length(x),
|
||||
PositionComponent::Percentage(x) => LengthOrPercentage::Percentage(x),
|
||||
PositionComponent::Center => LengthOrPercentage::Percentage(0.5),
|
||||
PositionComponent::Left | PositionComponent::Top => LengthOrPercentage::Percentage(0.0),
|
||||
PositionComponent::Right | PositionComponent::Bottom => LengthOrPercentage::Percentage(1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,8 +249,8 @@ pub mod specified {
|
|||
/// Specified values for an image according to CSS-IMAGES.
|
||||
#[deriving(Clone)]
|
||||
pub enum Image {
|
||||
UrlImage(Url),
|
||||
LinearGradientImage(LinearGradient),
|
||||
Url(Url),
|
||||
LinearGradient(LinearGradient),
|
||||
}
|
||||
|
||||
impl Image {
|
||||
|
@ -255,11 +259,11 @@ pub mod specified {
|
|||
match component_value {
|
||||
&ast::URL(ref url) => {
|
||||
let image_url = super::parse_url(url.as_slice(), base_url);
|
||||
Ok(UrlImage(image_url))
|
||||
Ok(Image::Url(image_url))
|
||||
},
|
||||
&ast::Function(ref name, ref args) => {
|
||||
if name.as_slice().eq_ignore_ascii_case("linear-gradient") {
|
||||
Ok(LinearGradientImage(try!(
|
||||
Ok(Image::LinearGradient(try!(
|
||||
super::specified::LinearGradient::parse_function(
|
||||
args.as_slice()))))
|
||||
} else {
|
||||
|
@ -273,9 +277,9 @@ pub mod specified {
|
|||
pub fn to_computed_value(self, context: &super::computed::Context)
|
||||
-> super::computed::Image {
|
||||
match self {
|
||||
UrlImage(url) => super::computed::UrlImage(url),
|
||||
LinearGradientImage(linear_gradient) => {
|
||||
super::computed::LinearGradientImage(
|
||||
Image::Url(url) => super::computed::Image::Url(url),
|
||||
Image::LinearGradient(linear_gradient) => {
|
||||
super::computed::Image::LinearGradient(
|
||||
super::computed::LinearGradient::compute(linear_gradient, context))
|
||||
}
|
||||
}
|
||||
|
@ -295,8 +299,8 @@ pub mod specified {
|
|||
/// Specified values for an angle or a corner in a linear gradient.
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub enum AngleOrCorner {
|
||||
AngleAoc(Angle),
|
||||
CornerAoc(HorizontalDirection, VerticalDirection),
|
||||
Angle(Angle),
|
||||
Corner(HorizontalDirection, VerticalDirection),
|
||||
}
|
||||
|
||||
/// Specified values for one color stop in a linear gradient.
|
||||
|
@ -360,11 +364,11 @@ pub mod specified {
|
|||
Dimension(ref value, ref unit) => {
|
||||
match Angle::parse_dimension(value.value, unit.as_slice()) {
|
||||
Ok(angle) => {
|
||||
(AngleAoc(angle), true)
|
||||
(AngleOrCorner::Angle(angle), true)
|
||||
}
|
||||
Err(()) => {
|
||||
source.push_back(token);
|
||||
(AngleAoc(Angle(PI)), false)
|
||||
(AngleOrCorner::Angle(Angle(PI)), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,16 +383,16 @@ pub mod specified {
|
|||
let ident = ident.as_slice();
|
||||
if ident.eq_ignore_ascii_case("top") &&
|
||||
vertical.is_none() {
|
||||
vertical = Some(Top)
|
||||
vertical = Some(VerticalDirection::Top)
|
||||
} else if ident.eq_ignore_ascii_case("bottom") &&
|
||||
vertical.is_none() {
|
||||
vertical = Some(Bottom)
|
||||
vertical = Some(VerticalDirection::Bottom)
|
||||
} else if ident.eq_ignore_ascii_case("left") &&
|
||||
horizontal.is_none() {
|
||||
horizontal = Some(Left)
|
||||
horizontal = Some(HorizontalDirection::Left)
|
||||
} else if ident.eq_ignore_ascii_case("right") &&
|
||||
horizontal.is_none() {
|
||||
horizontal = Some(Right)
|
||||
horizontal = Some(HorizontalDirection::Right)
|
||||
} else {
|
||||
return Err(())
|
||||
}
|
||||
|
@ -404,19 +408,27 @@ pub mod specified {
|
|||
}
|
||||
|
||||
(match (horizontal, vertical) {
|
||||
(None, Some(Top)) => AngleAoc(Angle(0.0)),
|
||||
(Some(Right), None) => AngleAoc(Angle(PI * 0.5)),
|
||||
(None, Some(Bottom)) => AngleAoc(Angle(PI)),
|
||||
(Some(Left), None) => AngleAoc(Angle(PI * 1.5)),
|
||||
(None, Some(VerticalDirection::Top)) => {
|
||||
AngleOrCorner::Angle(Angle(0.0))
|
||||
},
|
||||
(Some(HorizontalDirection::Right), None) => {
|
||||
AngleOrCorner::Angle(Angle(PI * 0.5))
|
||||
},
|
||||
(None, Some(VerticalDirection::Bottom)) => {
|
||||
AngleOrCorner::Angle(Angle(PI))
|
||||
},
|
||||
(Some(HorizontalDirection::Left), None) => {
|
||||
AngleOrCorner::Angle(Angle(PI * 1.5))
|
||||
},
|
||||
(Some(horizontal), Some(vertical)) => {
|
||||
CornerAoc(horizontal, vertical)
|
||||
AngleOrCorner::Corner(horizontal, vertical)
|
||||
}
|
||||
(None, None) => return Err(()),
|
||||
}, true)
|
||||
}
|
||||
_ => {
|
||||
source.push_back(token);
|
||||
(AngleAoc(Angle(PI)), false)
|
||||
(AngleOrCorner::Angle(Angle(PI)), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +460,7 @@ pub mod specified {
|
|||
}
|
||||
|
||||
pub mod computed {
|
||||
pub use super::specified::{Angle, AngleAoc, AngleOrCorner, CornerAoc, HorizontalDirection};
|
||||
pub use super::specified::{Angle, AngleOrCorner, HorizontalDirection};
|
||||
pub use super::specified::{VerticalDirection};
|
||||
pub use cssparser::Color as CSSColor;
|
||||
pub use super::super::longhands::computed_as_specified as compute_CSSColor;
|
||||
|
@ -487,14 +499,14 @@ pub mod computed {
|
|||
#[inline]
|
||||
pub fn compute_Au_with_font_size(value: specified::Length, reference_font_size: Au, root_font_size: Au) -> Au {
|
||||
match value {
|
||||
specified::Au_(value) => value,
|
||||
specified::Em(value) => reference_font_size.scale_by(value),
|
||||
specified::Ex(value) => {
|
||||
specified::Length::Au(value) => value,
|
||||
specified::Length::Em(value) => reference_font_size.scale_by(value),
|
||||
specified::Length::Ex(value) => {
|
||||
let x_height = 0.5; // TODO: find that from the font
|
||||
reference_font_size.scale_by(value * x_height)
|
||||
},
|
||||
specified::Rem(value) => root_font_size.scale_by(value),
|
||||
specified::ServoCharacterWidth(value) => {
|
||||
specified::Length::Rem(value) => root_font_size.scale_by(value),
|
||||
specified::Length::ServoCharacterWidth(value) => {
|
||||
// This applies the *converting a character width to pixels* algorithm as specified
|
||||
// in HTML5 § 14.5.4.
|
||||
//
|
||||
|
@ -508,56 +520,64 @@ pub mod computed {
|
|||
|
||||
#[deriving(PartialEq, Clone, Show)]
|
||||
pub enum LengthOrPercentage {
|
||||
LP_Length(Au),
|
||||
LP_Percentage(CSSFloat),
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
|
||||
-> LengthOrPercentage {
|
||||
match value {
|
||||
specified::LP_Length(value) => LP_Length(compute_Au(value, context)),
|
||||
specified::LP_Percentage(value) => LP_Percentage(value),
|
||||
specified::LengthOrPercentage::Length(value) =>
|
||||
LengthOrPercentage::Length(compute_Au(value, context)),
|
||||
specified::LengthOrPercentage::Percentage(value) =>
|
||||
LengthOrPercentage::Percentage(value),
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Clone, Show)]
|
||||
pub enum LengthOrPercentageOrAuto {
|
||||
LPA_Length(Au),
|
||||
LPA_Percentage(CSSFloat),
|
||||
LPA_Auto,
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
Auto,
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto,
|
||||
context: &Context) -> LengthOrPercentageOrAuto {
|
||||
match value {
|
||||
specified::LPA_Length(value) => LPA_Length(compute_Au(value, context)),
|
||||
specified::LPA_Percentage(value) => LPA_Percentage(value),
|
||||
specified::LPA_Auto => LPA_Auto,
|
||||
specified::LengthOrPercentageOrAuto::Length(value) =>
|
||||
LengthOrPercentageOrAuto::Length(compute_Au(value, context)),
|
||||
specified::LengthOrPercentageOrAuto::Percentage(value) =>
|
||||
LengthOrPercentageOrAuto::Percentage(value),
|
||||
specified::LengthOrPercentageOrAuto::Auto =>
|
||||
LengthOrPercentageOrAuto::Auto,
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Clone, Show)]
|
||||
pub enum LengthOrPercentageOrNone {
|
||||
LPN_Length(Au),
|
||||
LPN_Percentage(CSSFloat),
|
||||
LPN_None,
|
||||
Length(Au),
|
||||
Percentage(CSSFloat),
|
||||
None,
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone,
|
||||
context: &Context) -> LengthOrPercentageOrNone {
|
||||
match value {
|
||||
specified::LPN_Length(value) => LPN_Length(compute_Au(value, context)),
|
||||
specified::LPN_Percentage(value) => LPN_Percentage(value),
|
||||
specified::LPN_None => LPN_None,
|
||||
specified::LengthOrPercentageOrNone::Length(value) =>
|
||||
LengthOrPercentageOrNone::Length(compute_Au(value, context)),
|
||||
specified::LengthOrPercentageOrNone::Percentage(value) =>
|
||||
LengthOrPercentageOrNone::Percentage(value),
|
||||
specified::LengthOrPercentageOrNone::None =>
|
||||
LengthOrPercentageOrNone::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Computed values for an image according to CSS-IMAGES.
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub enum Image {
|
||||
UrlImage(Url),
|
||||
LinearGradientImage(LinearGradient),
|
||||
Url(Url),
|
||||
LinearGradient(LinearGradient),
|
||||
}
|
||||
|
||||
/// Computed values for a CSS linear gradient.
|
||||
|
|
|
@ -13,8 +13,8 @@ pub use url::Url;
|
|||
pub use cssparser::*;
|
||||
pub use cssparser::ast::*;
|
||||
pub use geom::SideOffsets2D;
|
||||
pub use self::common_types::specified::{Angle, AngleAoc, AngleOrCorner, Bottom, CornerAoc};
|
||||
pub use self::common_types::specified::{Left, Right, Top};
|
||||
pub use self::common_types::specified::{Angle, AngleOrCorner};
|
||||
pub use self::common_types::specified::{HorizontalDirection, VerticalDirection};
|
||||
|
||||
use errors::{ErrorLoggerIterator, log_css_error};
|
||||
pub use parsing_utils::*;
|
||||
|
@ -121,9 +121,9 @@ pub mod longhands {
|
|||
pub fn parse_declared(input: &[ComponentValue], base_url: &Url)
|
||||
-> Result<DeclaredValue<SpecifiedValue>, ()> {
|
||||
match CSSWideKeyword::parse(input) {
|
||||
Ok(InheritKeyword) => Ok(Inherit),
|
||||
Ok(InitialKeyword) => Ok(Initial),
|
||||
Ok(UnsetKeyword) => Ok(${
|
||||
Ok(CSSWideKeyword::InheritKeyword) => Ok(DeclaredValue::Inherit),
|
||||
Ok(CSSWideKeyword::InitialKeyword) => Ok(DeclaredValue::Initial),
|
||||
Ok(CSSWideKeyword::UnsetKeyword) => Ok(DeclaredValue::${
|
||||
"Inherit" if THIS_STYLE_STRUCT.inherited else "Initial"}),
|
||||
Err(()) => parse_specified(input, base_url),
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ pub mod longhands {
|
|||
% if derived_from is None:
|
||||
pub fn parse_specified(_input: &[ComponentValue], _base_url: &Url)
|
||||
-> Result<DeclaredValue<SpecifiedValue>, ()> {
|
||||
parse(_input, _base_url).map(super::SpecifiedValue)
|
||||
parse(_input, _base_url).map(super::DeclaredValue::SpecifiedValue)
|
||||
}
|
||||
% endif
|
||||
</%self:raw_longhand>
|
||||
|
@ -169,14 +169,14 @@ pub mod longhands {
|
|||
}
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
||||
${to_rust_ident(values.split()[0])}
|
||||
T::${to_rust_ident(values.split()[0])}
|
||||
}
|
||||
pub fn from_component_value(v: &ComponentValue, _base_url: &Url)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
get_ident_lower(v).and_then(|keyword| {
|
||||
match keyword.as_slice() {
|
||||
% for value in values.split():
|
||||
"${value}" => Ok(${to_rust_ident(value)}),
|
||||
"${value}" => Ok(T::${to_rust_ident(value)}),
|
||||
% endfor
|
||||
_ => Err(()),
|
||||
}
|
||||
|
@ -216,21 +216,21 @@ pub mod longhands {
|
|||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type("margin-" + side, "LengthOrPercentageOrAuto",
|
||||
"computed::LPA_Length(Au(0))")}
|
||||
"computed::LengthOrPercentageOrAuto::Length(Au(0))")}
|
||||
% endfor
|
||||
|
||||
${new_style_struct("Padding", is_inherited=False)}
|
||||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type("padding-" + side, "LengthOrPercentage",
|
||||
"computed::LP_Length(Au(0))",
|
||||
"computed::LengthOrPercentage::Length(Au(0))",
|
||||
"parse_non_negative")}
|
||||
% endfor
|
||||
|
||||
${new_style_struct("Border", is_inherited=False)}
|
||||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
|
||||
${predefined_type("border-%s-color" % side, "CSSColor", "super::super::computed::CSSColor::CurrentColor")}
|
||||
% endfor
|
||||
|
||||
${single_keyword("border-top-style", values="none solid double dotted dashed hidden groove ridge inset outset")}
|
||||
|
@ -302,7 +302,7 @@ pub mod longhands {
|
|||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T {
|
||||
radius: computed::LP_Length(Au(0)),
|
||||
radius: computed::LengthOrPercentage::Length(Au(0)),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
|
@ -358,7 +358,7 @@ pub mod longhands {
|
|||
${new_style_struct("Outline", is_inherited=False)}
|
||||
|
||||
// TODO(pcwalton): `invert`
|
||||
${predefined_type("outline-color", "CSSColor", "CurrentColor")}
|
||||
${predefined_type("outline-color", "CSSColor", "super::super::computed::CSSColor::CurrentColor")}
|
||||
|
||||
<%self:single_component_value name="outline-style">
|
||||
pub use super::border_top_style::{get_initial_value, to_computed_value};
|
||||
|
@ -391,7 +391,7 @@ pub mod longhands {
|
|||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type(side, "LengthOrPercentageOrAuto",
|
||||
"computed::LPA_Auto")}
|
||||
"computed::LengthOrPercentageOrAuto::Auto")}
|
||||
% endfor
|
||||
|
||||
// CSS 2.1, Section 9 - Visual formatting model
|
||||
|
@ -413,12 +413,13 @@ pub mod longhands {
|
|||
// }
|
||||
if context.positioned || context.floated || context.is_root_element {
|
||||
match value {
|
||||
inline_table => table,
|
||||
inline | inline_block
|
||||
| table_row_group | table_column | table_column_group
|
||||
| table_header_group | table_footer_group | table_row
|
||||
| table_cell | table_caption
|
||||
=> block,
|
||||
T::inline_table => T::table,
|
||||
T::inline | T::inline_block |
|
||||
T::table_row_group | T::table_column |
|
||||
T::table_column_group | T::table_header_group |
|
||||
T::table_footer_group | T::table_row | T::table_cell |
|
||||
T::table_caption
|
||||
=> T::block,
|
||||
_ => value,
|
||||
}
|
||||
} else {
|
||||
|
@ -463,23 +464,23 @@ pub mod longhands {
|
|||
impl T {
|
||||
pub fn number_or_zero(self) -> i32 {
|
||||
match self {
|
||||
Auto => 0,
|
||||
Number(value) => value,
|
||||
T::Auto => 0,
|
||||
T::Number(value) => value,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
Auto
|
||||
T::Auto
|
||||
}
|
||||
fn from_component_value(input: &ComponentValue, _: &Url) -> Result<SpecifiedValue,()> {
|
||||
match *input {
|
||||
Ident(ref keyword) if keyword.as_slice().eq_ignore_ascii_case("auto") => Ok(Auto),
|
||||
Ident(ref keyword) if keyword.as_slice().eq_ignore_ascii_case("auto") => Ok(T::Auto),
|
||||
ast::Number(ast::NumericValue {
|
||||
int_value: Some(value),
|
||||
..
|
||||
}) => Ok(Number(value as i32)),
|
||||
}) => Ok(T::Number(value as i32)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -494,7 +495,7 @@ pub mod longhands {
|
|||
${switch_to_style_struct("Box")}
|
||||
|
||||
${predefined_type("width", "LengthOrPercentageOrAuto",
|
||||
"computed::LPA_Auto",
|
||||
"computed::LengthOrPercentageOrAuto::Auto",
|
||||
"parse_non_negative")}
|
||||
<%self:single_component_value name="height">
|
||||
pub type SpecifiedValue = specified::LengthOrPercentageOrAuto;
|
||||
|
@ -502,7 +503,7 @@ pub mod longhands {
|
|||
pub type T = super::super::computed::LengthOrPercentageOrAuto;
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T { computed::LPA_Auto }
|
||||
pub fn get_initial_value() -> computed_value::T { computed::LengthOrPercentageOrAuto::Auto }
|
||||
#[inline]
|
||||
pub fn from_component_value(v: &ComponentValue, _base_url: &Url)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
|
@ -511,9 +512,9 @@ pub mod longhands {
|
|||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
match (value, context.inherited_height) {
|
||||
(specified::LPA_Percentage(_), computed::LPA_Auto)
|
||||
(specified::LengthOrPercentageOrAuto::Percentage(_), computed::LengthOrPercentageOrAuto::Auto)
|
||||
if !context.is_root_element && !context.positioned => {
|
||||
computed::LPA_Auto
|
||||
computed::LengthOrPercentageOrAuto::Auto
|
||||
},
|
||||
_ => computed::compute_LengthOrPercentageOrAuto(value, context)
|
||||
}
|
||||
|
@ -521,17 +522,17 @@ pub mod longhands {
|
|||
</%self:single_component_value>
|
||||
|
||||
${predefined_type("min-width", "LengthOrPercentage",
|
||||
"computed::LP_Length(Au(0))",
|
||||
"computed::LengthOrPercentage::Length(Au(0))",
|
||||
"parse_non_negative")}
|
||||
${predefined_type("max-width", "LengthOrPercentageOrNone",
|
||||
"computed::LPN_None",
|
||||
"computed::LengthOrPercentageOrNone::None",
|
||||
"parse_non_negative")}
|
||||
|
||||
${predefined_type("min-height", "LengthOrPercentage",
|
||||
"computed::LP_Length(Au(0))",
|
||||
"computed::LengthOrPercentage::Length(Au(0))",
|
||||
"parse_non_negative")}
|
||||
${predefined_type("max-height", "LengthOrPercentageOrNone",
|
||||
"computed::LPN_None",
|
||||
"computed::LengthOrPercentageOrNone::None",
|
||||
"parse_non_negative")}
|
||||
|
||||
${switch_to_style_struct("InheritedBox")}
|
||||
|
@ -539,24 +540,24 @@ pub mod longhands {
|
|||
<%self:single_component_value name="line-height">
|
||||
#[deriving(Clone)]
|
||||
pub enum SpecifiedValue {
|
||||
SpecifiedNormal,
|
||||
SpecifiedLength(specified::Length),
|
||||
SpecifiedNumber(CSSFloat),
|
||||
Normal,
|
||||
Length(specified::Length),
|
||||
Number(CSSFloat),
|
||||
// percentage are the same as em.
|
||||
}
|
||||
/// normal | <number> | <length> | <percentage>
|
||||
pub fn from_component_value(input: &ComponentValue, _base_url: &Url)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
match input {
|
||||
&ast::Number(ref value) if value.value >= 0.
|
||||
=> Ok(SpecifiedNumber(value.value)),
|
||||
&ast::Percentage(ref value) if value.value >= 0.
|
||||
=> Ok(SpecifiedLength(specified::Em(value.value / 100.))),
|
||||
&Dimension(ref value, ref unit) if value.value >= 0.
|
||||
=> specified::Length::parse_dimension(value.value, unit.as_slice())
|
||||
.map(SpecifiedLength),
|
||||
&Ident(ref value) if value.as_slice().eq_ignore_ascii_case("normal")
|
||||
=> Ok(SpecifiedNormal),
|
||||
&ast::Number(ref value) if value.value >= 0. =>
|
||||
Ok(SpecifiedValue::Number(value.value)),
|
||||
&ast::Percentage(ref value) if value.value >= 0. =>
|
||||
Ok(SpecifiedValue::Length(specified::Length::Em(value.value / 100.))),
|
||||
&Dimension(ref value, ref unit) if value.value >= 0. =>
|
||||
specified::Length::parse_dimension(value.value, unit.as_slice())
|
||||
.map(SpecifiedValue::Length),
|
||||
&Ident(ref value) if value.as_slice().eq_ignore_ascii_case("normal") =>
|
||||
Ok(SpecifiedValue::Normal),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -570,14 +571,14 @@ pub mod longhands {
|
|||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T { Normal }
|
||||
pub fn get_initial_value() -> computed_value::T { T::Normal }
|
||||
#[inline]
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
match value {
|
||||
SpecifiedNormal => Normal,
|
||||
SpecifiedLength(value) => Length(computed::compute_Au(value, context)),
|
||||
SpecifiedNumber(value) => Number(value),
|
||||
SpecifiedValue::Normal => T::Normal,
|
||||
SpecifiedValue::Length(value) => T::Length(computed::compute_Au(value, context)),
|
||||
SpecifiedValue::Number(value) => T::Number(value),
|
||||
}
|
||||
}
|
||||
</%self:single_component_value>
|
||||
|
@ -591,9 +592,9 @@ pub mod longhands {
|
|||
#[deriving(Clone)]
|
||||
pub enum SpecifiedValue {
|
||||
% for keyword in vertical_align_keywords:
|
||||
Specified_${to_rust_ident(keyword)},
|
||||
${to_rust_ident(keyword)},
|
||||
% endfor
|
||||
SpecifiedLengthOrPercentage(specified::LengthOrPercentage),
|
||||
LengthOrPercentage(specified::LengthOrPercentage),
|
||||
}
|
||||
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
||||
/// | <percentage> | <length>
|
||||
|
@ -603,13 +604,13 @@ pub mod longhands {
|
|||
&Ident(ref value) => {
|
||||
match value.as_slice().to_ascii_lower().as_slice() {
|
||||
% for keyword in vertical_align_keywords:
|
||||
"${keyword}" => Ok(Specified_${to_rust_ident(keyword)}),
|
||||
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
|
||||
% endfor
|
||||
_ => Err(()),
|
||||
}
|
||||
},
|
||||
_ => specified::LengthOrPercentage::parse_non_negative(input)
|
||||
.map(SpecifiedLengthOrPercentage)
|
||||
.map(SpecifiedValue::LengthOrPercentage)
|
||||
}
|
||||
}
|
||||
pub mod computed_value {
|
||||
|
@ -625,18 +626,18 @@ pub mod longhands {
|
|||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T { baseline }
|
||||
pub fn get_initial_value() -> computed_value::T { T::baseline }
|
||||
#[inline]
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
match value {
|
||||
% for keyword in vertical_align_keywords:
|
||||
Specified_${to_rust_ident(keyword)} => ${to_rust_ident(keyword)},
|
||||
SpecifiedValue::${to_rust_ident(keyword)} => computed_value::T::${to_rust_ident(keyword)},
|
||||
% endfor
|
||||
SpecifiedLengthOrPercentage(value)
|
||||
SpecifiedValue::LengthOrPercentage(value)
|
||||
=> match computed::compute_LengthOrPercentage(value, context) {
|
||||
computed::LP_Length(value) => Length(value),
|
||||
computed::LP_Percentage(value) => Percentage(value)
|
||||
computed::LengthOrPercentage::Length(value) => T::Length(value),
|
||||
computed::LengthOrPercentage::Percentage(value) => T::Percentage(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -672,7 +673,7 @@ pub mod longhands {
|
|||
}
|
||||
}
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T { normal }
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T { T::normal }
|
||||
|
||||
// normal | none | [ <string> ]+
|
||||
// TODO: <uri>, <counter>, attr(<identifier>), open-quote, close-quote, no-open-quote, no-close-quote
|
||||
|
@ -680,8 +681,8 @@ pub mod longhands {
|
|||
match one_component_value(input) {
|
||||
Ok(&Ident(ref keyword)) => {
|
||||
match keyword.as_slice().to_ascii_lower().as_slice() {
|
||||
"normal" => return Ok(normal),
|
||||
"none" => return Ok(none),
|
||||
"normal" => return Ok(T::normal),
|
||||
"none" => return Ok(T::none),
|
||||
_ => ()
|
||||
}
|
||||
},
|
||||
|
@ -691,11 +692,11 @@ pub mod longhands {
|
|||
for component_value in input.skip_whitespace() {
|
||||
match component_value {
|
||||
&QuotedString(ref value)
|
||||
=> content.push(StringContent(value.clone())),
|
||||
=> content.push(ContentItem::StringContent(value.clone())),
|
||||
_ => return Err(()) // invalid/unsupported value
|
||||
}
|
||||
}
|
||||
Ok(Content(content))
|
||||
Ok(T::Content(content))
|
||||
}
|
||||
</%self:longhand>
|
||||
|
||||
|
@ -743,7 +744,7 @@ pub mod longhands {
|
|||
|
||||
${new_style_struct("Background", is_inherited=False)}
|
||||
${predefined_type("background-color", "CSSColor",
|
||||
"RGBAColor(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}
|
||||
"Color::RGBA(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}
|
||||
|
||||
<%self:single_component_value name="background-image">
|
||||
use super::common_types::specified as common_specified;
|
||||
|
@ -804,13 +805,13 @@ pub mod longhands {
|
|||
-> Result<SpecifiedValue,()> {
|
||||
let (horiz, vert) = match (category(first), category(second)) {
|
||||
// Don't allow two vertical keywords or two horizontal keywords.
|
||||
(HorizontalKeyword, HorizontalKeyword) |
|
||||
(VerticalKeyword, VerticalKeyword) => return Err(()),
|
||||
(PositionCategory::HorizontalKeyword, PositionCategory::HorizontalKeyword) |
|
||||
(PositionCategory::VerticalKeyword, PositionCategory::VerticalKeyword) => return Err(()),
|
||||
|
||||
// Swap if both are keywords and vertical precedes horizontal.
|
||||
(VerticalKeyword, HorizontalKeyword) |
|
||||
(VerticalKeyword, OtherKeyword) |
|
||||
(OtherKeyword, HorizontalKeyword) => (second, first),
|
||||
(PositionCategory::VerticalKeyword, PositionCategory::HorizontalKeyword) |
|
||||
(PositionCategory::VerticalKeyword, PositionCategory::OtherKeyword) |
|
||||
(PositionCategory::OtherKeyword, PositionCategory::HorizontalKeyword) => (second, first),
|
||||
|
||||
// By default, horizontal is first.
|
||||
_ => (first, second),
|
||||
|
@ -831,11 +832,17 @@ pub mod longhands {
|
|||
}
|
||||
fn category(p: specified::PositionComponent) -> PositionCategory {
|
||||
match p {
|
||||
specified::Pos_Left | specified::Pos_Right => HorizontalKeyword,
|
||||
specified::Pos_Top | specified::Pos_Bottom => VerticalKeyword,
|
||||
specified::Pos_Center => OtherKeyword,
|
||||
specified::Pos_Length(_) |
|
||||
specified::Pos_Percentage(_) => LengthOrPercentage,
|
||||
specified::PositionComponent::Left |
|
||||
specified::PositionComponent::Right =>
|
||||
PositionCategory::HorizontalKeyword,
|
||||
specified::PositionComponent::Top |
|
||||
specified::PositionComponent::Bottom =>
|
||||
PositionCategory::VerticalKeyword,
|
||||
specified::PositionComponent::Center =>
|
||||
PositionCategory::OtherKeyword,
|
||||
specified::PositionComponent::Length(_) |
|
||||
specified::PositionComponent::Percentage(_) =>
|
||||
PositionCategory::LengthOrPercentage,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -851,15 +858,15 @@ pub mod longhands {
|
|||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T {
|
||||
horizontal: computed::LP_Percentage(0.0),
|
||||
vertical: computed::LP_Percentage(0.0),
|
||||
horizontal: computed::LengthOrPercentage::Percentage(0.0),
|
||||
vertical: computed::LengthOrPercentage::Percentage(0.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_one(first: &ComponentValue) -> Result<SpecifiedValue, ()> {
|
||||
let first = try!(specified::PositionComponent::parse(first));
|
||||
// If only one value is provided, use `center` for the second.
|
||||
SpecifiedValue::new(first, specified::Pos_Center)
|
||||
SpecifiedValue::new(first, specified::PositionComponent::Center)
|
||||
}
|
||||
|
||||
pub fn parse_two(first: &ComponentValue, second: &ComponentValue)
|
||||
|
@ -906,8 +913,8 @@ pub mod longhands {
|
|||
pub fn parse_specified(input: &[ComponentValue], _base_url: &Url)
|
||||
-> Result<DeclaredValue<SpecifiedValue>, ()> {
|
||||
match one_component_value(input).and_then(Color::parse) {
|
||||
Ok(RGBAColor(rgba)) => Ok(SpecifiedValue(rgba)),
|
||||
Ok(CurrentColor) => Ok(Inherit),
|
||||
Ok(Color::RGBA(rgba)) => Ok(DeclaredValue::SpecifiedValue(rgba)),
|
||||
Ok(Color::CurrentColor) => Ok(DeclaredValue::Inherit),
|
||||
Err(()) => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -933,7 +940,7 @@ pub mod longhands {
|
|||
impl FontFamily {
|
||||
pub fn name(&self) -> &str {
|
||||
match *self {
|
||||
FamilyName(ref name) => name.as_slice(),
|
||||
FontFamily::FamilyName(ref name) => name.as_slice(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -943,7 +950,7 @@ pub mod longhands {
|
|||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
vec![FamilyName("serif".to_string())]
|
||||
vec![FontFamily::FamilyName("serif".to_string())]
|
||||
}
|
||||
/// <familiy-name>#
|
||||
/// <familiy-name> = <string> | [ <ident>+ ]
|
||||
|
@ -954,7 +961,7 @@ pub mod longhands {
|
|||
pub fn parse_one_family<'a>(iter: ParserIter) -> Result<FontFamily, ()> {
|
||||
// TODO: avoid copying strings?
|
||||
let mut idents = match iter.next() {
|
||||
Some(&QuotedString(ref value)) => return Ok(FamilyName(value.clone())),
|
||||
Some(&QuotedString(ref value)) => return Ok(FontFamily::FamilyName(value.clone())),
|
||||
Some(&Ident(ref value)) => {
|
||||
// match value.as_slice().to_ascii_lower().as_slice() {
|
||||
// "serif" => return Ok(Serif),
|
||||
|
@ -982,7 +989,7 @@ pub mod longhands {
|
|||
None => break,
|
||||
}
|
||||
}
|
||||
Ok(FamilyName(idents.connect(" ")))
|
||||
Ok(FontFamily::FamilyName(idents.connect(" ")))
|
||||
}
|
||||
</%self:longhand>
|
||||
|
||||
|
@ -1005,23 +1012,23 @@ pub mod longhands {
|
|||
match input {
|
||||
&Ident(ref value) => {
|
||||
match value.as_slice().to_ascii_lower().as_slice() {
|
||||
"bold" => Ok(SpecifiedWeight700),
|
||||
"normal" => Ok(SpecifiedWeight400),
|
||||
"bolder" => Ok(Bolder),
|
||||
"lighter" => Ok(Lighter),
|
||||
"bold" => Ok(SpecifiedValue::SpecifiedWeight700),
|
||||
"normal" => Ok(SpecifiedValue::SpecifiedWeight400),
|
||||
"bolder" => Ok(SpecifiedValue::Bolder),
|
||||
"lighter" => Ok(SpecifiedValue::Lighter),
|
||||
_ => Err(()),
|
||||
}
|
||||
},
|
||||
&Number(ref value) => match value.int_value {
|
||||
Some(100) => Ok(SpecifiedWeight100),
|
||||
Some(200) => Ok(SpecifiedWeight200),
|
||||
Some(300) => Ok(SpecifiedWeight300),
|
||||
Some(400) => Ok(SpecifiedWeight400),
|
||||
Some(500) => Ok(SpecifiedWeight500),
|
||||
Some(600) => Ok(SpecifiedWeight600),
|
||||
Some(700) => Ok(SpecifiedWeight700),
|
||||
Some(800) => Ok(SpecifiedWeight800),
|
||||
Some(900) => Ok(SpecifiedWeight900),
|
||||
Some(100) => Ok(SpecifiedValue::SpecifiedWeight100),
|
||||
Some(200) => Ok(SpecifiedValue::SpecifiedWeight200),
|
||||
Some(300) => Ok(SpecifiedValue::SpecifiedWeight300),
|
||||
Some(400) => Ok(SpecifiedValue::SpecifiedWeight400),
|
||||
Some(500) => Ok(SpecifiedValue::SpecifiedWeight500),
|
||||
Some(600) => Ok(SpecifiedValue::SpecifiedWeight600),
|
||||
Some(700) => Ok(SpecifiedValue::SpecifiedWeight700),
|
||||
Some(800) => Ok(SpecifiedValue::SpecifiedWeight800),
|
||||
Some(900) => Ok(SpecifiedValue::SpecifiedWeight900),
|
||||
_ => Err(()),
|
||||
},
|
||||
_ => Err(())
|
||||
|
@ -1037,42 +1044,45 @@ pub mod longhands {
|
|||
impl T {
|
||||
pub fn is_bold(self) -> bool {
|
||||
match self {
|
||||
Weight900 | Weight800 | Weight700 | Weight600 => true,
|
||||
T::Weight900 | T::Weight800 |
|
||||
T::Weight700 | T::Weight600 => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T { Weight400 } // normal
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::Weight400 // normal
|
||||
}
|
||||
#[inline]
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
match value {
|
||||
% for weight in range(100, 901, 100):
|
||||
SpecifiedWeight${weight} => Weight${weight},
|
||||
SpecifiedValue::SpecifiedWeight${weight} => computed_value::T::Weight${weight},
|
||||
% endfor
|
||||
Bolder => match context.inherited_font_weight {
|
||||
Weight100 => Weight400,
|
||||
Weight200 => Weight400,
|
||||
Weight300 => Weight400,
|
||||
Weight400 => Weight700,
|
||||
Weight500 => Weight700,
|
||||
Weight600 => Weight900,
|
||||
Weight700 => Weight900,
|
||||
Weight800 => Weight900,
|
||||
Weight900 => Weight900,
|
||||
SpecifiedValue::Bolder => match context.inherited_font_weight {
|
||||
computed_value::T::Weight100 => computed_value::T::Weight400,
|
||||
computed_value::T::Weight200 => computed_value::T::Weight400,
|
||||
computed_value::T::Weight300 => computed_value::T::Weight400,
|
||||
computed_value::T::Weight400 => computed_value::T::Weight700,
|
||||
computed_value::T::Weight500 => computed_value::T::Weight700,
|
||||
computed_value::T::Weight600 => computed_value::T::Weight900,
|
||||
computed_value::T::Weight700 => computed_value::T::Weight900,
|
||||
computed_value::T::Weight800 => computed_value::T::Weight900,
|
||||
computed_value::T::Weight900 => computed_value::T::Weight900,
|
||||
},
|
||||
Lighter => match context.inherited_font_weight {
|
||||
Weight100 => Weight100,
|
||||
Weight200 => Weight100,
|
||||
Weight300 => Weight100,
|
||||
Weight400 => Weight100,
|
||||
Weight500 => Weight100,
|
||||
Weight600 => Weight400,
|
||||
Weight700 => Weight400,
|
||||
Weight800 => Weight700,
|
||||
Weight900 => Weight700,
|
||||
SpecifiedValue::Lighter => match context.inherited_font_weight {
|
||||
computed_value::T::Weight100 => computed_value::T::Weight100,
|
||||
computed_value::T::Weight200 => computed_value::T::Weight100,
|
||||
computed_value::T::Weight300 => computed_value::T::Weight100,
|
||||
computed_value::T::Weight400 => computed_value::T::Weight100,
|
||||
computed_value::T::Weight500 => computed_value::T::Weight100,
|
||||
computed_value::T::Weight600 => computed_value::T::Weight400,
|
||||
computed_value::T::Weight700 => computed_value::T::Weight400,
|
||||
computed_value::T::Weight800 => computed_value::T::Weight700,
|
||||
computed_value::T::Weight900 => computed_value::T::Weight700,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1098,22 +1108,22 @@ pub mod longhands {
|
|||
pub fn from_component_value(input: &ComponentValue, _base_url: &Url)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
match specified::LengthOrPercentage::parse_non_negative(input) {
|
||||
Ok(specified::LP_Length(value)) => return Ok(value),
|
||||
Ok(specified::LP_Percentage(value)) => return Ok(specified::Em(value)),
|
||||
Ok(specified::LengthOrPercentage::Length(value)) => return Ok(value),
|
||||
Ok(specified::LengthOrPercentage::Percentage(value)) => return Ok(specified::Length::Em(value)),
|
||||
Err(()) => (),
|
||||
}
|
||||
match try!(get_ident_lower(input)).as_slice() {
|
||||
"xx-small" => Ok(specified::Au_(Au::from_px(MEDIUM_PX) * 3 / 5)),
|
||||
"x-small" => Ok(specified::Au_(Au::from_px(MEDIUM_PX) * 3 / 4)),
|
||||
"small" => Ok(specified::Au_(Au::from_px(MEDIUM_PX) * 8 / 9)),
|
||||
"medium" => Ok(specified::Au_(Au::from_px(MEDIUM_PX))),
|
||||
"large" => Ok(specified::Au_(Au::from_px(MEDIUM_PX) * 6 / 5)),
|
||||
"x-large" => Ok(specified::Au_(Au::from_px(MEDIUM_PX) * 3 / 2)),
|
||||
"xx-large" => Ok(specified::Au_(Au::from_px(MEDIUM_PX) * 2)),
|
||||
"xx-small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 5)),
|
||||
"x-small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 4)),
|
||||
"small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 8 / 9)),
|
||||
"medium" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX))),
|
||||
"large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 6 / 5)),
|
||||
"x-large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 2)),
|
||||
"xx-large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 2)),
|
||||
|
||||
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
||||
"smaller" => Ok(specified::Em(0.85)),
|
||||
"larger" => Ok(specified::Em(1.2)),
|
||||
"smaller" => Ok(specified::Length::Em(0.85)),
|
||||
"larger" => Ok(specified::Length::Em(1.2)),
|
||||
|
||||
_ => return Err(())
|
||||
}
|
||||
|
@ -1173,7 +1183,7 @@ pub mod longhands {
|
|||
}
|
||||
</%self:single_component_value>
|
||||
|
||||
${predefined_type("text-indent", "LengthOrPercentage", "computed::LP_Length(Au(0))")}
|
||||
${predefined_type("text-indent", "LengthOrPercentage", "computed::LengthOrPercentage::Length(Au(0))")}
|
||||
|
||||
// Also known as "word-wrap" (which is more popular because of IE), but this is the preferred
|
||||
// name per CSS-TEXT 6.2.
|
||||
|
@ -1269,7 +1279,7 @@ pub mod longhands {
|
|||
// Start with no declarations if this is a block; otherwise, start with the
|
||||
// declarations in effect and add in the text decorations that this inline specifies.
|
||||
let mut result = match context.display {
|
||||
display::computed_value::inline => context.inherited_text_decorations_in_effect,
|
||||
display::computed_value::T::inline => context.inherited_text_decorations_in_effect,
|
||||
_ => {
|
||||
SpecifiedValue {
|
||||
underline: None,
|
||||
|
@ -1422,14 +1432,14 @@ pub mod longhands {
|
|||
offset_y: computed::compute_Au(value.offset_y, context),
|
||||
blur_radius: computed::compute_Au(value.blur_radius, context),
|
||||
spread_radius: computed::compute_Au(value.spread_radius, context),
|
||||
color: value.color.unwrap_or(cssparser::CurrentColor),
|
||||
color: value.color.unwrap_or(cssparser::Color::CurrentColor),
|
||||
inset: value.inset,
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn parse_one_box_shadow(iter: ParserIter) -> Result<SpecifiedBoxShadow,()> {
|
||||
let mut lengths = [specified::Au_(Au(0)), ..4];
|
||||
let mut lengths = [specified::Length::Au(Au(0)), ..4];
|
||||
let mut lengths_parsed = false;
|
||||
let mut color = None;
|
||||
let mut inset = false;
|
||||
|
@ -1766,7 +1776,7 @@ pub mod shorthands {
|
|||
fn parse_one_set_of_border_radii<'a,I>(mut input: Peekable< &'a ComponentValue,I >)
|
||||
-> Result<[specified::LengthOrPercentage, ..4],()>
|
||||
where I: Iterator< &'a ComponentValue > {
|
||||
let (mut count, mut values) = (0u, [specified::LP_Length(specified::Au_(Au(0))), ..4]);
|
||||
let (mut count, mut values) = (0u, [specified::LengthOrPercentage::Length(specified::Length::Au(Au(0))), ..4]);
|
||||
while count < 4 {
|
||||
let token = match input.peek() {
|
||||
None => break,
|
||||
|
@ -2004,14 +2014,14 @@ pub mod shorthands {
|
|||
Ok(Longhands {
|
||||
list_style_position: position,
|
||||
list_style_image: Some(None),
|
||||
list_style_type: Some(list_style_type::none),
|
||||
list_style_type: Some(list_style_type::T::none),
|
||||
})
|
||||
}
|
||||
(true, 1, None, Some(image)) => {
|
||||
Ok(Longhands {
|
||||
list_style_position: position,
|
||||
list_style_image: Some(image),
|
||||
list_style_type: Some(list_style_type::none),
|
||||
list_style_type: Some(list_style_type::T::none),
|
||||
})
|
||||
}
|
||||
(true, 1, Some(list_style_type), None) => {
|
||||
|
@ -2025,7 +2035,7 @@ pub mod shorthands {
|
|||
Ok(Longhands {
|
||||
list_style_position: position,
|
||||
list_style_image: Some(None),
|
||||
list_style_type: Some(list_style_type::none),
|
||||
list_style_type: Some(list_style_type::T::none),
|
||||
})
|
||||
}
|
||||
(true, 0, list_style_type, image) => {
|
||||
|
@ -2105,9 +2115,9 @@ pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I, base_url: &U
|
|||
ErrorLoggerIterator(parse_declaration_list(input)).collect();
|
||||
for item in items.into_iter().rev() {
|
||||
match item {
|
||||
DeclAtRule(rule) => log_css_error(
|
||||
DeclarationListItem::AtRule(rule) => log_css_error(
|
||||
rule.location, format!("Unsupported at-rule in declaration list: @{:s}", rule.name).as_slice()),
|
||||
Declaration_(Declaration{ location: l, name: n, value: v, important: i}) => {
|
||||
DeclarationListItem::Declaration(Declaration{ location: l, name: n, value: v, important: i}) => {
|
||||
// TODO: only keep the last valid declaration for a given name.
|
||||
let (list, seen) = if i {
|
||||
(&mut important_declarations, &mut important_seen)
|
||||
|
@ -2115,15 +2125,15 @@ pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I, base_url: &U
|
|||
(&mut normal_declarations, &mut normal_seen)
|
||||
};
|
||||
match PropertyDeclaration::parse(n.as_slice(), v.as_slice(), list, base_url, seen) {
|
||||
UnknownProperty => log_css_error(l, format!(
|
||||
PropertyDeclarationParseResult::UnknownProperty => log_css_error(l, format!(
|
||||
"Unsupported property: {}:{}", n, v.iter().to_css()).as_slice()),
|
||||
ExperimentalProperty => log_css_error(l, format!(
|
||||
PropertyDeclarationParseResult::ExperimentalProperty => log_css_error(l, format!(
|
||||
"Experimental property, use `servo --enable_experimental` \
|
||||
or `servo -e` to enable: {}:{}",
|
||||
n, v.iter().to_css()).as_slice()),
|
||||
InvalidValue => log_css_error(l, format!(
|
||||
PropertyDeclarationParseResult::InvalidValue => log_css_error(l, format!(
|
||||
"Invalid value: {}:{}", n, v.iter().to_css()).as_slice()),
|
||||
ValidOrIgnoredDeclaration => (),
|
||||
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2145,9 +2155,9 @@ impl CSSWideKeyword {
|
|||
pub fn parse(input: &[ComponentValue]) -> Result<CSSWideKeyword, ()> {
|
||||
one_component_value(input).and_then(get_ident_lower).and_then(|keyword| {
|
||||
match keyword.as_slice() {
|
||||
"initial" => Ok(InitialKeyword),
|
||||
"inherit" => Ok(InheritKeyword),
|
||||
"unset" => Ok(UnsetKeyword),
|
||||
"initial" => Ok(CSSWideKeyword::InitialKeyword),
|
||||
"inherit" => Ok(CSSWideKeyword::InheritKeyword),
|
||||
"unset" => Ok(CSSWideKeyword::UnsetKeyword),
|
||||
_ => Err(())
|
||||
}
|
||||
})
|
||||
|
@ -2192,84 +2202,86 @@ impl PropertyDeclaration {
|
|||
"${property.name}" => {
|
||||
% if property.experimental:
|
||||
if !::servo_util::opts::experimental_enabled() {
|
||||
return ExperimentalProperty
|
||||
return PropertyDeclarationParseResult::ExperimentalProperty
|
||||
}
|
||||
% endif
|
||||
if seen.get_${property.ident}() {
|
||||
return ValidOrIgnoredDeclaration
|
||||
return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
}
|
||||
match longhands::${property.ident}::parse_declared(value, base_url) {
|
||||
Ok(value) => {
|
||||
seen.set_${property.ident}();
|
||||
result_list.push(${property.camel_case}Declaration(value));
|
||||
ValidOrIgnoredDeclaration
|
||||
result_list.push(PropertyDeclaration::${property.camel_case}Declaration(value));
|
||||
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
},
|
||||
Err(()) => InvalidValue,
|
||||
Err(()) => PropertyDeclarationParseResult::InvalidValue,
|
||||
}
|
||||
},
|
||||
% else:
|
||||
"${property.name}" => UnknownProperty,
|
||||
"${property.name}" => PropertyDeclarationParseResult::UnknownProperty,
|
||||
% endif
|
||||
% endfor
|
||||
% for shorthand in SHORTHANDS:
|
||||
"${shorthand.name}" => {
|
||||
if ${" && ".join("seen.get_%s()" % sub_property.ident
|
||||
for sub_property in shorthand.sub_properties)} {
|
||||
return ValidOrIgnoredDeclaration
|
||||
return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
}
|
||||
match CSSWideKeyword::parse(value) {
|
||||
Ok(InheritKeyword) => {
|
||||
Ok(CSSWideKeyword::InheritKeyword) => {
|
||||
% for sub_property in shorthand.sub_properties:
|
||||
if !seen.get_${sub_property.ident}() {
|
||||
seen.set_${sub_property.ident}();
|
||||
result_list.push(
|
||||
${sub_property.camel_case}Declaration(Inherit));
|
||||
PropertyDeclaration::${sub_property.camel_case}Declaration(
|
||||
DeclaredValue::Inherit));
|
||||
}
|
||||
% endfor
|
||||
ValidOrIgnoredDeclaration
|
||||
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
},
|
||||
Ok(InitialKeyword) => {
|
||||
Ok(CSSWideKeyword::InitialKeyword) => {
|
||||
% for sub_property in shorthand.sub_properties:
|
||||
if !seen.get_${sub_property.ident}() {
|
||||
seen.set_${sub_property.ident}();
|
||||
result_list.push(
|
||||
${sub_property.camel_case}Declaration(Initial));
|
||||
PropertyDeclaration::${sub_property.camel_case}Declaration(
|
||||
DeclaredValue::Initial));
|
||||
}
|
||||
% endfor
|
||||
ValidOrIgnoredDeclaration
|
||||
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
},
|
||||
Ok(UnsetKeyword) => {
|
||||
Ok(CSSWideKeyword::UnsetKeyword) => {
|
||||
% for sub_property in shorthand.sub_properties:
|
||||
if !seen.get_${sub_property.ident}() {
|
||||
seen.set_${sub_property.ident}();
|
||||
result_list.push(${sub_property.camel_case}Declaration(
|
||||
${"Inherit" if sub_property.style_struct.inherited else "Initial"}
|
||||
result_list.push(PropertyDeclaration::${sub_property.camel_case}Declaration(
|
||||
DeclaredValue::${"Inherit" if sub_property.style_struct.inherited else "Initial"}
|
||||
));
|
||||
}
|
||||
% endfor
|
||||
ValidOrIgnoredDeclaration
|
||||
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
},
|
||||
Err(()) => match shorthands::${shorthand.ident}::parse(value, base_url) {
|
||||
Ok(result) => {
|
||||
% for sub_property in shorthand.sub_properties:
|
||||
if !seen.get_${sub_property.ident}() {
|
||||
seen.set_${sub_property.ident}();
|
||||
result_list.push(${sub_property.camel_case}Declaration(
|
||||
result_list.push(PropertyDeclaration::${sub_property.camel_case}Declaration(
|
||||
match result.${sub_property.ident} {
|
||||
Some(value) => SpecifiedValue(value),
|
||||
None => Initial,
|
||||
Some(value) => DeclaredValue::SpecifiedValue(value),
|
||||
None => DeclaredValue::Initial,
|
||||
}
|
||||
));
|
||||
}
|
||||
% endfor
|
||||
ValidOrIgnoredDeclaration
|
||||
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration
|
||||
},
|
||||
Err(()) => InvalidValue,
|
||||
Err(()) => PropertyDeclarationParseResult::InvalidValue,
|
||||
}
|
||||
}
|
||||
},
|
||||
% endfor
|
||||
_ => UnknownProperty,
|
||||
_ => PropertyDeclarationParseResult::UnknownProperty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2308,8 +2320,8 @@ impl ComputedValues {
|
|||
#[inline]
|
||||
pub fn resolve_color(&self, color: computed::CSSColor) -> RGBA {
|
||||
match color {
|
||||
RGBAColor(rgba) => rgba,
|
||||
CurrentColor => self.get_color().color,
|
||||
Color::RGBA(rgba) => rgba,
|
||||
Color::CurrentColor => self.get_color().color,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2414,27 +2426,27 @@ fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> Writing
|
|||
use servo_util::logical_geometry;
|
||||
let mut flags = WritingMode::empty();
|
||||
match inheritedbox_style.direction {
|
||||
computed_values::direction::ltr => {},
|
||||
computed_values::direction::rtl => {
|
||||
computed_values::direction::T::ltr => {},
|
||||
computed_values::direction::T::rtl => {
|
||||
flags.insert(logical_geometry::FLAG_RTL);
|
||||
},
|
||||
}
|
||||
match inheritedbox_style.writing_mode {
|
||||
computed_values::writing_mode::horizontal_tb => {},
|
||||
computed_values::writing_mode::vertical_rl => {
|
||||
computed_values::writing_mode::T::horizontal_tb => {},
|
||||
computed_values::writing_mode::T::vertical_rl => {
|
||||
flags.insert(logical_geometry::FLAG_VERTICAL);
|
||||
},
|
||||
computed_values::writing_mode::vertical_lr => {
|
||||
computed_values::writing_mode::T::vertical_lr => {
|
||||
flags.insert(logical_geometry::FLAG_VERTICAL);
|
||||
flags.insert(logical_geometry::FLAG_VERTICAL_LR);
|
||||
},
|
||||
}
|
||||
match inheritedbox_style.text_orientation {
|
||||
computed_values::text_orientation::sideways_right => {},
|
||||
computed_values::text_orientation::sideways_left => {
|
||||
computed_values::text_orientation::T::sideways_right => {},
|
||||
computed_values::text_orientation::T::sideways_left => {
|
||||
flags.insert(logical_geometry::FLAG_VERTICAL_LR);
|
||||
},
|
||||
computed_values::text_orientation::sideways => {
|
||||
computed_values::text_orientation::T::sideways => {
|
||||
if flags.intersects(logical_geometry::FLAG_VERTICAL_LR) {
|
||||
flags.insert(logical_geometry::FLAG_SIDEWAYS_LEFT);
|
||||
}
|
||||
|
@ -2492,21 +2504,21 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock]
|
|||
% for style_struct in STYLE_STRUCTS:
|
||||
% for property in style_struct.longhands:
|
||||
% if property.derived_from is None:
|
||||
${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value) => {
|
||||
PropertyDeclaration::${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value) => {
|
||||
% if style_struct.inherited:
|
||||
if seen.get_${property.ident}() {
|
||||
continue
|
||||
}
|
||||
seen.set_${property.ident}();
|
||||
let computed_value = match *declared_value {
|
||||
SpecifiedValue(ref specified_value)
|
||||
DeclaredValue::SpecifiedValue(ref specified_value)
|
||||
=> longhands::${property.ident}::to_computed_value(
|
||||
(*specified_value).clone(),
|
||||
context
|
||||
),
|
||||
Initial
|
||||
DeclaredValue::Initial
|
||||
=> longhands::${property.ident}::get_initial_value(),
|
||||
Inherit => {
|
||||
DeclaredValue::Inherit => {
|
||||
// This is a bit slow, but this is rare so it shouldn't
|
||||
// matter.
|
||||
//
|
||||
|
@ -2538,7 +2550,7 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock]
|
|||
% endif
|
||||
}
|
||||
% else:
|
||||
${property.camel_case}Declaration(_) => {
|
||||
PropertyDeclaration::${property.camel_case}Declaration(_) => {
|
||||
// Do not allow stylesheets to set derived properties.
|
||||
}
|
||||
% endif
|
||||
|
@ -2613,9 +2625,9 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
|
|||
macro_rules! get_specified(
|
||||
($style_struct_getter: ident, $property: ident, $declared_value: expr) => {
|
||||
match *$declared_value {
|
||||
SpecifiedValue(specified_value) => specified_value,
|
||||
Initial => longhands::$property::get_initial_value(),
|
||||
Inherit => inherited_style.$style_struct_getter().$property.clone(),
|
||||
DeclaredValue::SpecifiedValue(specified_value) => specified_value,
|
||||
DeclaredValue::Initial => longhands::$property::get_initial_value(),
|
||||
DeclaredValue::Inherit => inherited_style.$style_struct_getter().$property.clone(),
|
||||
}
|
||||
};
|
||||
)
|
||||
|
@ -2626,39 +2638,39 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
|
|||
// Declarations are stored in reverse source order, we want them in forward order here.
|
||||
for declaration in sub_list.declarations.iter().rev() {
|
||||
match *declaration {
|
||||
FontSizeDeclaration(ref value) => {
|
||||
PropertyDeclaration::FontSizeDeclaration(ref value) => {
|
||||
context.font_size = match *value {
|
||||
SpecifiedValue(specified_value) => computed::compute_Au_with_font_size(
|
||||
DeclaredValue::SpecifiedValue(specified_value) => computed::compute_Au_with_font_size(
|
||||
specified_value, context.inherited_font_size, context.root_font_size),
|
||||
Initial => longhands::font_size::get_initial_value(),
|
||||
Inherit => context.inherited_font_size,
|
||||
DeclaredValue::Initial => longhands::font_size::get_initial_value(),
|
||||
DeclaredValue::Inherit => context.inherited_font_size,
|
||||
}
|
||||
}
|
||||
ColorDeclaration(ref value) => {
|
||||
PropertyDeclaration::ColorDeclaration(ref value) => {
|
||||
context.color = get_specified!(get_color, color, value);
|
||||
}
|
||||
DisplayDeclaration(ref value) => {
|
||||
PropertyDeclaration::DisplayDeclaration(ref value) => {
|
||||
context.display = get_specified!(get_box, display, value);
|
||||
}
|
||||
PositionDeclaration(ref value) => {
|
||||
PropertyDeclaration::PositionDeclaration(ref value) => {
|
||||
context.positioned = match get_specified!(get_box, position, value) {
|
||||
longhands::position::absolute | longhands::position::fixed => true,
|
||||
longhands::position::T::absolute | longhands::position::T::fixed => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
FloatDeclaration(ref value) => {
|
||||
PropertyDeclaration::FloatDeclaration(ref value) => {
|
||||
context.floated = get_specified!(get_box, float, value)
|
||||
!= longhands::float::none;
|
||||
!= longhands::float::T::none;
|
||||
}
|
||||
TextDecorationDeclaration(ref value) => {
|
||||
PropertyDeclaration::TextDecorationDeclaration(ref value) => {
|
||||
context.text_decoration = get_specified!(get_text, text_decoration, value);
|
||||
}
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
Border${side.capitalize()}StyleDeclaration(ref value) => {
|
||||
PropertyDeclaration::Border${side.capitalize()}StyleDeclaration(ref value) => {
|
||||
context.border_${side}_present =
|
||||
match get_specified!(get_border, border_${side}_style, value) {
|
||||
longhands::border_top_style::none |
|
||||
longhands::border_top_style::hidden => false,
|
||||
longhands::border_top_style::T::none |
|
||||
longhands::border_top_style::T::hidden => false,
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
@ -2700,20 +2712,20 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
|
|||
% for style_struct in STYLE_STRUCTS:
|
||||
% for property in style_struct.longhands:
|
||||
% if property.derived_from is None:
|
||||
${property.camel_case}Declaration(ref declared_value) => {
|
||||
PropertyDeclaration::${property.camel_case}Declaration(ref declared_value) => {
|
||||
if seen.get_${property.ident}() {
|
||||
continue
|
||||
}
|
||||
seen.set_${property.ident}();
|
||||
let computed_value = match *declared_value {
|
||||
SpecifiedValue(ref specified_value)
|
||||
DeclaredValue::SpecifiedValue(ref specified_value)
|
||||
=> longhands::${property.ident}::to_computed_value(
|
||||
(*specified_value).clone(),
|
||||
&context
|
||||
),
|
||||
Initial
|
||||
DeclaredValue::Initial
|
||||
=> longhands::${property.ident}::get_initial_value(),
|
||||
Inherit => {
|
||||
DeclaredValue::Inherit => {
|
||||
// This is a bit slow, but this is rare so it shouldn't
|
||||
// matter.
|
||||
//
|
||||
|
@ -2740,7 +2752,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
|
|||
% endif
|
||||
}
|
||||
% else:
|
||||
${property.camel_case}Declaration(_) => {
|
||||
PropertyDeclaration::${property.camel_case}Declaration(_) => {
|
||||
// Do not allow stylesheets to set derived properties.
|
||||
}
|
||||
% endif
|
||||
|
@ -2824,7 +2836,7 @@ pub mod computed_values {
|
|||
|
||||
pub use cssparser::RGBA;
|
||||
pub use super::common_types::computed::{
|
||||
LengthOrPercentage, LP_Length, LP_Percentage,
|
||||
LengthOrPercentageOrAuto, LPA_Length, LPA_Percentage, LPA_Auto,
|
||||
LengthOrPercentageOrNone, LPN_Length, LPN_Percentage, LPN_None};
|
||||
LengthOrPercentage,
|
||||
LengthOrPercentageOrAuto,
|
||||
LengthOrPercentageOrNone};
|
||||
}
|
||||
|
|
|
@ -20,26 +20,16 @@ use legacy::PresentationalHintSynthesis;
|
|||
use media_queries::Device;
|
||||
use node::{TElement, TElementAttributes, TNode};
|
||||
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use selectors::{After, AnyLink, AttrDashMatch, AttrEqual};
|
||||
use selectors::{AttrExists, AttrIncludes, AttrPrefixMatch};
|
||||
use selectors::{AttrSubstringMatch, AttrSuffixMatch, Before, CaseInsensitive, CaseSensitive};
|
||||
use selectors::{Checked, Child, ClassSelector, Indeterminate};
|
||||
use selectors::{CompoundSelector, Descendant, Disabled, Enabled, FirstChild, FirstOfType};
|
||||
use selectors::{Hover, IDSelector, LastChild, LastOfType};
|
||||
use selectors::{LaterSibling, LocalName, LocalNameSelector};
|
||||
use selectors::{NamespaceSelector, Link, Negation};
|
||||
use selectors::{NextSibling, NthChild};
|
||||
use selectors::{NthLastChild, NthLastOfType};
|
||||
use selectors::{NthOfType, OnlyChild, OnlyOfType, PseudoElement, Root};
|
||||
use selectors::{SelectorList, ServoNonzeroBorder, SimpleSelector, Visited};
|
||||
use selectors::{CaseSensitivity, Combinator, CompoundSelector, LocalName};
|
||||
use selectors::{PseudoElement, SelectorList, SimpleSelector};
|
||||
use selectors::{get_selector_list_selectors};
|
||||
use stylesheets::{Stylesheet, iter_stylesheet_media_rules, iter_stylesheet_style_rules};
|
||||
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub enum StylesheetOrigin {
|
||||
UserAgentOrigin,
|
||||
AuthorOrigin,
|
||||
UserOrigin,
|
||||
UserAgent,
|
||||
Author,
|
||||
User,
|
||||
}
|
||||
|
||||
/// The definition of whitespace per CSS Selectors Level 3 § 4.
|
||||
|
@ -232,7 +222,7 @@ impl SelectorMap {
|
|||
match *ss {
|
||||
// TODO(pradeep): Implement case-sensitivity based on the document type and quirks
|
||||
// mode.
|
||||
IDSelector(ref id) => return Some(id.clone()),
|
||||
SimpleSelector::IDSelector(ref id) => return Some(id.clone()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +236,7 @@ impl SelectorMap {
|
|||
match *ss {
|
||||
// TODO(pradeep): Implement case-sensitivity based on the document type and quirks
|
||||
// mode.
|
||||
ClassSelector(ref class) => return Some(class.clone()),
|
||||
SimpleSelector::ClassSelector(ref class) => return Some(class.clone()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +248,7 @@ impl SelectorMap {
|
|||
let simple_selector_sequence = &rule.selector.simple_selectors;
|
||||
for ss in simple_selector_sequence.iter() {
|
||||
match *ss {
|
||||
LocalNameSelector(ref name) => {
|
||||
SimpleSelector::LocalNameSelector(ref name) => {
|
||||
return Some(name.clone())
|
||||
}
|
||||
_ => {}
|
||||
|
@ -314,7 +304,7 @@ impl Stylist {
|
|||
Url::parse(format!("chrome:///{}", filename).as_slice()).unwrap(),
|
||||
None,
|
||||
None,
|
||||
UserAgentOrigin);
|
||||
StylesheetOrigin::UserAgent);
|
||||
stylist.add_stylesheet(ua_stylesheet);
|
||||
}
|
||||
stylist
|
||||
|
@ -329,17 +319,17 @@ impl Stylist {
|
|||
|
||||
for stylesheet in self.stylesheets.iter() {
|
||||
let (mut element_map, mut before_map, mut after_map) = match stylesheet.origin {
|
||||
UserAgentOrigin => (
|
||||
StylesheetOrigin::UserAgent => (
|
||||
&mut self.element_map.user_agent,
|
||||
&mut self.before_map.user_agent,
|
||||
&mut self.after_map.user_agent,
|
||||
),
|
||||
AuthorOrigin => (
|
||||
StylesheetOrigin::Author => (
|
||||
&mut self.element_map.author,
|
||||
&mut self.before_map.author,
|
||||
&mut self.after_map.author,
|
||||
),
|
||||
UserOrigin => (
|
||||
StylesheetOrigin::User => (
|
||||
&mut self.element_map.user,
|
||||
&mut self.before_map.user,
|
||||
&mut self.after_map.user,
|
||||
|
@ -355,8 +345,8 @@ impl Stylist {
|
|||
for selector in $style_rule.selectors.iter() {
|
||||
let map = match selector.pseudo_element {
|
||||
None => &mut element_map,
|
||||
Some(Before) => &mut before_map,
|
||||
Some(After) => &mut after_map,
|
||||
Some(PseudoElement::Before) => &mut before_map,
|
||||
Some(PseudoElement::After) => &mut after_map,
|
||||
};
|
||||
map.$priority.insert(Rule {
|
||||
selector: selector.compound_selectors.clone(),
|
||||
|
@ -406,7 +396,7 @@ impl Stylist {
|
|||
Url::parse("chrome:///quirks-mode.css").unwrap(),
|
||||
None,
|
||||
None,
|
||||
UserAgentOrigin))
|
||||
StylesheetOrigin::UserAgent))
|
||||
}
|
||||
|
||||
pub fn add_stylesheet(&mut self, stylesheet: Stylesheet) {
|
||||
|
@ -438,8 +428,8 @@ impl Stylist {
|
|||
|
||||
let map = match pseudo_element {
|
||||
None => &self.element_map,
|
||||
Some(Before) => &self.before_map,
|
||||
Some(After) => &self.after_map,
|
||||
Some(PseudoElement::Before) => &self.before_map,
|
||||
Some(PseudoElement::After) => &self.after_map,
|
||||
};
|
||||
|
||||
let mut shareable = true;
|
||||
|
@ -588,7 +578,7 @@ fn matches_compound_selector<'a,E,N>(selector: &CompoundSelector,
|
|||
-> bool
|
||||
where E: TElement<'a>, N: TNode<'a,E> {
|
||||
match matches_compound_selector_internal(selector, element, parent_bf, shareable) {
|
||||
Matched => true,
|
||||
SelectorMatchingResult::Matched => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +643,7 @@ fn can_fast_reject<'a,E,N>(mut selector: &CompoundSelector,
|
|||
where E: TElement<'a>, N: TNode<'a,E> {
|
||||
if !selector.simple_selectors.iter().all(|simple_selector| {
|
||||
matches_simple_selector(simple_selector, element, shareable) }) {
|
||||
return Some(NotMatchedAndRestartFromClosestLaterSibling);
|
||||
return Some(SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling);
|
||||
}
|
||||
|
||||
let bf: &BloomFilter = match *parent_bf {
|
||||
|
@ -666,7 +656,7 @@ fn can_fast_reject<'a,E,N>(mut selector: &CompoundSelector,
|
|||
loop {
|
||||
match selector.next {
|
||||
None => break,
|
||||
Some((ref cs, Descendant)) => selector = &**cs,
|
||||
Some((ref cs, Combinator::Descendant)) => selector = &**cs,
|
||||
Some((ref cs, _)) => {
|
||||
selector = &**cs;
|
||||
continue;
|
||||
|
@ -675,25 +665,25 @@ fn can_fast_reject<'a,E,N>(mut selector: &CompoundSelector,
|
|||
|
||||
for ss in selector.simple_selectors.iter() {
|
||||
match *ss {
|
||||
LocalNameSelector(LocalName { ref name, ref lower_name }) => {
|
||||
SimpleSelector::LocalNameSelector(LocalName { ref name, ref lower_name }) => {
|
||||
if !bf.might_contain(name)
|
||||
&& !bf.might_contain(lower_name) {
|
||||
return Some(NotMatchedGlobally);
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
NamespaceSelector(ref namespace) => {
|
||||
SimpleSelector::NamespaceSelector(ref namespace) => {
|
||||
if !bf.might_contain(namespace) {
|
||||
return Some(NotMatchedGlobally);
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
IDSelector(ref id) => {
|
||||
SimpleSelector::IDSelector(ref id) => {
|
||||
if !bf.might_contain(id) {
|
||||
return Some(NotMatchedGlobally);
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
ClassSelector(ref class) => {
|
||||
SimpleSelector::ClassSelector(ref class) => {
|
||||
if !bf.might_contain(class) {
|
||||
return Some(NotMatchedGlobally);
|
||||
return Some(SelectorMatchingResult::NotMatchedGlobally);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
|
@ -718,13 +708,13 @@ fn matches_compound_selector_internal<'a,E,N>(selector: &CompoundSelector,
|
|||
};
|
||||
|
||||
match selector.next {
|
||||
None => Matched,
|
||||
None => SelectorMatchingResult::Matched,
|
||||
Some((ref next_selector, combinator)) => {
|
||||
let (siblings, candidate_not_found) = match combinator {
|
||||
Child => (false, NotMatchedGlobally),
|
||||
Descendant => (false, NotMatchedGlobally),
|
||||
NextSibling => (true, NotMatchedAndRestartFromClosestDescendant),
|
||||
LaterSibling => (true, NotMatchedAndRestartFromClosestDescendant),
|
||||
Combinator::Child => (false, SelectorMatchingResult::NotMatchedGlobally),
|
||||
Combinator::Descendant => (false, SelectorMatchingResult::NotMatchedGlobally),
|
||||
Combinator::NextSibling => (true, SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant),
|
||||
Combinator::LaterSibling => (true, SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant),
|
||||
};
|
||||
let mut node = (*element).clone();
|
||||
loop {
|
||||
|
@ -744,25 +734,25 @@ fn matches_compound_selector_internal<'a,E,N>(selector: &CompoundSelector,
|
|||
shareable);
|
||||
match (result, combinator) {
|
||||
// Return the status immediately.
|
||||
(Matched, _) => return result,
|
||||
(NotMatchedGlobally, _) => return result,
|
||||
(SelectorMatchingResult::Matched, _) => return result,
|
||||
(SelectorMatchingResult::NotMatchedGlobally, _) => return result,
|
||||
|
||||
// Upgrade the failure status to
|
||||
// NotMatchedAndRestartFromClosestDescendant.
|
||||
(_, Child) => return NotMatchedAndRestartFromClosestDescendant,
|
||||
(_, Combinator::Child) => return SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant,
|
||||
|
||||
// Return the status directly.
|
||||
(_, NextSibling) => return result,
|
||||
(_, Combinator::NextSibling) => return result,
|
||||
|
||||
// If the failure status is NotMatchedAndRestartFromClosestDescendant
|
||||
// and combinator is LaterSibling, give up this LaterSibling matching
|
||||
// and combinator is Combinator::LaterSibling, give up this Combinator::LaterSibling matching
|
||||
// and restart from the closest descendant combinator.
|
||||
(NotMatchedAndRestartFromClosestDescendant, LaterSibling) => return result,
|
||||
(SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant, Combinator::LaterSibling) => return result,
|
||||
|
||||
// The Descendant combinator and the status is
|
||||
// The Combinator::Descendant combinator and the status is
|
||||
// NotMatchedAndRestartFromClosestLaterSibling or
|
||||
// NotMatchedAndRestartFromClosestDescendant,
|
||||
// or the LaterSibling combinator and the status is
|
||||
// or the Combinator::LaterSibling combinator and the status is
|
||||
// NotMatchedAndRestartFromClosestDescendant
|
||||
// can continue to matching on the next candidate element.
|
||||
_ => {},
|
||||
|
@ -789,8 +779,8 @@ pub struct CommonStyleAffectingAttributeInfo {
|
|||
}
|
||||
|
||||
pub enum CommonStyleAffectingAttributeMode {
|
||||
AttrIsPresentMode(CommonStyleAffectingAttributes),
|
||||
AttrIsEqualMode(&'static str, CommonStyleAffectingAttributes),
|
||||
IsPresent(CommonStyleAffectingAttributes),
|
||||
IsEqual(&'static str, CommonStyleAffectingAttributes),
|
||||
}
|
||||
|
||||
// NB: This must match the order in `layout::css::matching::CommonStyleAffectingAttributes`.
|
||||
|
@ -799,23 +789,23 @@ pub fn common_style_affecting_attributes() -> [CommonStyleAffectingAttributeInfo
|
|||
[
|
||||
CommonStyleAffectingAttributeInfo {
|
||||
atom: atom!("hidden"),
|
||||
mode: AttrIsPresentMode(HIDDEN_ATTRIBUTE),
|
||||
mode: CommonStyleAffectingAttributeMode::IsPresent(HIDDEN_ATTRIBUTE),
|
||||
},
|
||||
CommonStyleAffectingAttributeInfo {
|
||||
atom: atom!("nowrap"),
|
||||
mode: AttrIsPresentMode(NO_WRAP_ATTRIBUTE),
|
||||
mode: CommonStyleAffectingAttributeMode::IsPresent(NO_WRAP_ATTRIBUTE),
|
||||
},
|
||||
CommonStyleAffectingAttributeInfo {
|
||||
atom: atom!("align"),
|
||||
mode: AttrIsEqualMode("left", ALIGN_LEFT_ATTRIBUTE),
|
||||
mode: CommonStyleAffectingAttributeMode::IsEqual("left", ALIGN_LEFT_ATTRIBUTE),
|
||||
},
|
||||
CommonStyleAffectingAttributeInfo {
|
||||
atom: atom!("align"),
|
||||
mode: AttrIsEqualMode("center", ALIGN_CENTER_ATTRIBUTE),
|
||||
mode: CommonStyleAffectingAttributeMode::IsEqual("center", ALIGN_CENTER_ATTRIBUTE),
|
||||
},
|
||||
CommonStyleAffectingAttributeInfo {
|
||||
atom: atom!("align"),
|
||||
mode: AttrIsEqualMode("right", ALIGN_RIGHT_ATTRIBUTE),
|
||||
mode: CommonStyleAffectingAttributeMode::IsEqual("right", ALIGN_RIGHT_ATTRIBUTE),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -840,48 +830,48 @@ pub fn matches_simple_selector<'a,E,N>(selector: &SimpleSelector,
|
|||
-> bool
|
||||
where E: TElement<'a>, N: TNode<'a,E> {
|
||||
match *selector {
|
||||
LocalNameSelector(LocalName { ref name, ref lower_name }) => {
|
||||
SimpleSelector::LocalNameSelector(LocalName { ref name, ref lower_name }) => {
|
||||
let name = if element.is_html_element_in_html_document() { lower_name } else { name };
|
||||
let element = element.as_element();
|
||||
element.get_local_name() == name
|
||||
}
|
||||
|
||||
NamespaceSelector(ref namespace) => {
|
||||
SimpleSelector::NamespaceSelector(ref namespace) => {
|
||||
let element = element.as_element();
|
||||
element.get_namespace() == namespace
|
||||
}
|
||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||
IDSelector(ref id) => {
|
||||
SimpleSelector::IDSelector(ref id) => {
|
||||
*shareable = false;
|
||||
let element = element.as_element();
|
||||
element.get_id().map_or(false, |attr| {
|
||||
attr == *id
|
||||
})
|
||||
}
|
||||
ClassSelector(ref class) => {
|
||||
SimpleSelector::ClassSelector(ref class) => {
|
||||
let element = element.as_element();
|
||||
element.has_class(class)
|
||||
}
|
||||
|
||||
AttrExists(ref attr) => {
|
||||
SimpleSelector::AttrExists(ref attr) => {
|
||||
// NB(pcwalton): If you update this, remember to update the corresponding list in
|
||||
// `can_share_style_with()` as well.
|
||||
if common_style_affecting_attributes().iter().all(|common_attr_info| {
|
||||
!(common_attr_info.atom == attr.name && match common_attr_info.mode {
|
||||
AttrIsPresentMode(_) => true,
|
||||
AttrIsEqualMode(..) => false,
|
||||
CommonStyleAffectingAttributeMode::IsPresent(_) => true,
|
||||
CommonStyleAffectingAttributeMode::IsEqual(..) => false,
|
||||
})
|
||||
}) {
|
||||
*shareable = false;
|
||||
}
|
||||
element.match_attr(attr, |_| true)
|
||||
}
|
||||
AttrEqual(ref attr, ref value, case_sensitivity) => {
|
||||
SimpleSelector::AttrEqual(ref attr, ref value, case_sensitivity) => {
|
||||
if value.as_slice() != "DIR" &&
|
||||
common_style_affecting_attributes().iter().all(|common_attr_info| {
|
||||
!(common_attr_info.atom == attr.name && match common_attr_info.mode {
|
||||
AttrIsEqualMode(target_value, _) => target_value == value.as_slice(),
|
||||
AttrIsPresentMode(_) => false,
|
||||
CommonStyleAffectingAttributeMode::IsEqual(target_value, _) => target_value == value.as_slice(),
|
||||
CommonStyleAffectingAttributeMode::IsPresent(_) => false,
|
||||
})
|
||||
}) {
|
||||
// FIXME(pcwalton): Remove once we start actually supporting RTL text. This is in
|
||||
|
@ -890,56 +880,56 @@ pub fn matches_simple_selector<'a,E,N>(selector: &SimpleSelector,
|
|||
}
|
||||
element.match_attr(attr, |attr_value| {
|
||||
match case_sensitivity {
|
||||
CaseSensitive => attr_value == value.as_slice(),
|
||||
CaseInsensitive => attr_value.eq_ignore_ascii_case(value.as_slice()),
|
||||
CaseSensitivity::CaseSensitive => attr_value == value.as_slice(),
|
||||
CaseSensitivity::CaseInsensitive => attr_value.eq_ignore_ascii_case(value.as_slice()),
|
||||
}
|
||||
})
|
||||
}
|
||||
AttrIncludes(ref attr, ref value) => {
|
||||
SimpleSelector::AttrIncludes(ref attr, ref value) => {
|
||||
*shareable = false;
|
||||
element.match_attr(attr, |attr_value| {
|
||||
attr_value.split(SELECTOR_WHITESPACE).any(|v| v == value.as_slice())
|
||||
})
|
||||
}
|
||||
AttrDashMatch(ref attr, ref value, ref dashing_value) => {
|
||||
SimpleSelector::AttrDashMatch(ref attr, ref value, ref dashing_value) => {
|
||||
*shareable = false;
|
||||
element.match_attr(attr, |attr_value| {
|
||||
attr_value == value.as_slice() ||
|
||||
attr_value.starts_with(dashing_value.as_slice())
|
||||
})
|
||||
}
|
||||
AttrPrefixMatch(ref attr, ref value) => {
|
||||
SimpleSelector::AttrPrefixMatch(ref attr, ref value) => {
|
||||
*shareable = false;
|
||||
element.match_attr(attr, |attr_value| {
|
||||
attr_value.starts_with(value.as_slice())
|
||||
})
|
||||
}
|
||||
AttrSubstringMatch(ref attr, ref value) => {
|
||||
SimpleSelector::AttrSubstringMatch(ref attr, ref value) => {
|
||||
*shareable = false;
|
||||
element.match_attr(attr, |attr_value| {
|
||||
attr_value.contains(value.as_slice())
|
||||
})
|
||||
}
|
||||
AttrSuffixMatch(ref attr, ref value) => {
|
||||
SimpleSelector::AttrSuffixMatch(ref attr, ref value) => {
|
||||
*shareable = false;
|
||||
element.match_attr(attr, |attr_value| {
|
||||
attr_value.ends_with(value.as_slice())
|
||||
})
|
||||
}
|
||||
|
||||
AnyLink => {
|
||||
SimpleSelector::AnyLink => {
|
||||
*shareable = false;
|
||||
let element = element.as_element();
|
||||
element.get_link().is_some()
|
||||
}
|
||||
Link => {
|
||||
SimpleSelector::Link => {
|
||||
let elem = element.as_element();
|
||||
match elem.get_link() {
|
||||
Some(url) => !url_is_visited(url),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
Visited => {
|
||||
SimpleSelector::Visited => {
|
||||
// NB(pcwalton): When we actually start supporting visited links, remember to update
|
||||
// `can_share_style_with`.
|
||||
let elem = element.as_element();
|
||||
|
@ -949,91 +939,91 @@ pub fn matches_simple_selector<'a,E,N>(selector: &SimpleSelector,
|
|||
}
|
||||
}
|
||||
|
||||
Hover => {
|
||||
SimpleSelector::Hover => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_hover_state()
|
||||
},
|
||||
// http://www.whatwg.org/html/#selector-disabled
|
||||
Disabled => {
|
||||
SimpleSelector::Disabled => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_disabled_state()
|
||||
},
|
||||
// http://www.whatwg.org/html/#selector-enabled
|
||||
Enabled => {
|
||||
SimpleSelector::Enabled => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_enabled_state()
|
||||
},
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#selector-checked
|
||||
Checked => {
|
||||
SimpleSelector::Checked => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_checked_state()
|
||||
}
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#selector-indeterminate
|
||||
Indeterminate => {
|
||||
SimpleSelector::Indeterminate => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_indeterminate_state()
|
||||
}
|
||||
FirstChild => {
|
||||
SimpleSelector::FirstChild => {
|
||||
*shareable = false;
|
||||
matches_first_child(element)
|
||||
}
|
||||
LastChild => {
|
||||
SimpleSelector::LastChild => {
|
||||
*shareable = false;
|
||||
matches_last_child(element)
|
||||
}
|
||||
OnlyChild => {
|
||||
SimpleSelector::OnlyChild => {
|
||||
*shareable = false;
|
||||
matches_first_child(element) && matches_last_child(element)
|
||||
}
|
||||
|
||||
Root => {
|
||||
SimpleSelector::Root => {
|
||||
*shareable = false;
|
||||
matches_root(element)
|
||||
}
|
||||
|
||||
NthChild(a, b) => {
|
||||
SimpleSelector::NthChild(a, b) => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, a, b, false, false)
|
||||
}
|
||||
NthLastChild(a, b) => {
|
||||
SimpleSelector::NthLastChild(a, b) => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, a, b, false, true)
|
||||
}
|
||||
NthOfType(a, b) => {
|
||||
SimpleSelector::NthOfType(a, b) => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, a, b, true, false)
|
||||
}
|
||||
NthLastOfType(a, b) => {
|
||||
SimpleSelector::NthLastOfType(a, b) => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, a, b, true, true)
|
||||
}
|
||||
|
||||
FirstOfType => {
|
||||
SimpleSelector::FirstOfType => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, 0, 1, true, false)
|
||||
}
|
||||
LastOfType => {
|
||||
SimpleSelector::LastOfType => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, 0, 1, true, true)
|
||||
}
|
||||
OnlyOfType => {
|
||||
SimpleSelector::OnlyOfType => {
|
||||
*shareable = false;
|
||||
matches_generic_nth_child(element, 0, 1, true, false) &&
|
||||
matches_generic_nth_child(element, 0, 1, true, true)
|
||||
}
|
||||
|
||||
ServoNonzeroBorder => {
|
||||
SimpleSelector::ServoNonzeroBorder => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.has_nonzero_border()
|
||||
}
|
||||
|
||||
Negation(ref negated) => {
|
||||
SimpleSelector::Negation(ref negated) => {
|
||||
*shareable = false;
|
||||
!negated.iter().all(|s| matches_simple_selector(s, element, shareable))
|
||||
},
|
||||
|
@ -1186,13 +1176,13 @@ mod tests {
|
|||
fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
|
||||
use namespaces::NamespaceMap;
|
||||
use selectors::{ParserContext, parse_selector_list};
|
||||
use selector_matching::AuthorOrigin;
|
||||
use selector_matching::StylesheetOrigin;
|
||||
use cssparser::tokenize;
|
||||
|
||||
let namespaces = NamespaceMap::new();
|
||||
css_selectors.iter().enumerate().map(|(i, selectors)| {
|
||||
let context = ParserContext {
|
||||
origin: AuthorOrigin,
|
||||
origin: StylesheetOrigin::Author,
|
||||
};
|
||||
parse_selector_list(&context, tokenize(*selectors).map(|(c, _)| c), &namespaces)
|
||||
.unwrap().into_iter().map(|s| {
|
||||
|
|
|
@ -9,7 +9,7 @@ use sync::Arc;
|
|||
use cssparser::ast::*;
|
||||
use cssparser::{tokenize, parse_nth};
|
||||
|
||||
use selector_matching::{StylesheetOrigin, UserAgentOrigin};
|
||||
use selector_matching::StylesheetOrigin;
|
||||
use string_cache::{Atom, Namespace};
|
||||
|
||||
use namespaces::NamespaceMap;
|
||||
|
@ -114,8 +114,8 @@ pub struct AttrSelector {
|
|||
|
||||
#[deriving(Eq, PartialEq, Clone, Hash)]
|
||||
pub enum NamespaceConstraint {
|
||||
AnyNamespace,
|
||||
SpecificNamespace(Namespace),
|
||||
Any,
|
||||
Specific(Namespace),
|
||||
}
|
||||
|
||||
|
||||
|
@ -162,21 +162,37 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
|||
specificity: &mut Specificity) {
|
||||
for simple_selector in simple_selectors.iter() {
|
||||
match simple_selector {
|
||||
&LocalNameSelector(..) => specificity.element_selectors += 1,
|
||||
&IDSelector(..) => specificity.id_selectors += 1,
|
||||
&ClassSelector(..)
|
||||
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
||||
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
||||
| &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled
|
||||
| &FirstChild | &LastChild | &OnlyChild | &Root | &Checked | &Indeterminate
|
||||
// | &Empty | &Lang(*)
|
||||
| &NthChild(..) | &NthLastChild(..)
|
||||
| &NthOfType(..) | &NthLastOfType(..)
|
||||
| &FirstOfType | &LastOfType | &OnlyOfType | &ServoNonzeroBorder
|
||||
=> specificity.class_like_selectors += 1,
|
||||
&NamespaceSelector(..) => (),
|
||||
&Negation(ref negated)
|
||||
=> simple_selectors_specificity(negated.as_slice(), specificity),
|
||||
&SimpleSelector::LocalNameSelector(..) =>
|
||||
specificity.element_selectors += 1,
|
||||
&SimpleSelector::IDSelector(..) =>
|
||||
specificity.id_selectors += 1,
|
||||
&SimpleSelector::ClassSelector(..) |
|
||||
&SimpleSelector::AttrExists(..) |
|
||||
&SimpleSelector::AttrEqual(..) |
|
||||
&SimpleSelector::AttrIncludes(..) |
|
||||
&SimpleSelector::AttrDashMatch(..) |
|
||||
&SimpleSelector::AttrPrefixMatch(..) |
|
||||
&SimpleSelector::AttrSubstringMatch(..) |
|
||||
&SimpleSelector::AttrSuffixMatch(..) |
|
||||
&SimpleSelector::AnyLink | &SimpleSelector::Link |
|
||||
&SimpleSelector::Visited | &SimpleSelector::Hover |
|
||||
&SimpleSelector::Disabled | &SimpleSelector::Enabled |
|
||||
&SimpleSelector::FirstChild | &SimpleSelector::LastChild |
|
||||
&SimpleSelector::OnlyChild | &SimpleSelector::Root |
|
||||
&SimpleSelector::Checked |
|
||||
&SimpleSelector::Indeterminate |
|
||||
// &SimpleSelector::Empty | &SimpleSelector::Lang(*) |
|
||||
&SimpleSelector::NthChild(..) |
|
||||
&SimpleSelector::NthLastChild(..) |
|
||||
&SimpleSelector::NthOfType(..) |
|
||||
&SimpleSelector::NthLastOfType(..) |
|
||||
&SimpleSelector::FirstOfType | &SimpleSelector::LastOfType |
|
||||
&SimpleSelector::OnlyOfType |
|
||||
&SimpleSelector::ServoNonzeroBorder =>
|
||||
specificity.class_like_selectors += 1,
|
||||
&SimpleSelector::NamespaceSelector(..) => (),
|
||||
&SimpleSelector::Negation(ref negated) =>
|
||||
simple_selectors_specificity(negated.as_slice(), specificity),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,12 +217,14 @@ fn parse_type_selector<I: Iterator<ComponentValue>>(
|
|||
Some((namespace, local_name)) => {
|
||||
let mut simple_selectors = vec!();
|
||||
match namespace {
|
||||
SpecificNamespace(ns) => simple_selectors.push(NamespaceSelector(ns)),
|
||||
AnyNamespace => (),
|
||||
NamespaceConstraint::Specific(ns) => {
|
||||
simple_selectors.push(SimpleSelector::NamespaceSelector(ns))
|
||||
},
|
||||
NamespaceConstraint::Any => (),
|
||||
}
|
||||
match local_name {
|
||||
Some(name) => {
|
||||
simple_selectors.push(LocalNameSelector(LocalName {
|
||||
simple_selectors.push(SimpleSelector::LocalNameSelector(LocalName {
|
||||
name: Atom::from_slice(name.as_slice()),
|
||||
lower_name: Atom::from_slice(name.into_ascii_lower().as_slice())
|
||||
}))
|
||||
|
@ -220,8 +238,8 @@ fn parse_type_selector<I: Iterator<ComponentValue>>(
|
|||
|
||||
|
||||
enum SimpleSelectorParseResult {
|
||||
SimpleSelectorResult(SimpleSelector),
|
||||
PseudoElementResult(PseudoElement),
|
||||
SimpleSelector(SimpleSelector),
|
||||
PseudoElement(PseudoElement),
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,8 +251,8 @@ fn parse_qualified_name<I: Iterator<ComponentValue>>(
|
|||
-> Result<Option<(NamespaceConstraint, Option<String>)>, ()> {
|
||||
let default_namespace = |local_name| {
|
||||
let namespace = match namespaces.default {
|
||||
Some(ref ns) => SpecificNamespace(ns.clone()),
|
||||
None => AnyNamespace,
|
||||
Some(ref ns) => NamespaceConstraint::Specific(ns.clone()),
|
||||
None => NamespaceConstraint::Any,
|
||||
};
|
||||
Ok(Some((namespace, local_name)))
|
||||
};
|
||||
|
@ -264,24 +282,24 @@ fn parse_qualified_name<I: Iterator<ComponentValue>>(
|
|||
None => return Err(()), // Undeclared namespace prefix
|
||||
Some(ref ns) => (*ns).clone(),
|
||||
};
|
||||
explicit_namespace(iter, SpecificNamespace(namespace))
|
||||
explicit_namespace(iter, NamespaceConstraint::Specific(namespace))
|
||||
},
|
||||
_ if in_attr_selector => Ok(Some(
|
||||
(SpecificNamespace(ns!("")), Some(value)))),
|
||||
(NamespaceConstraint::Specific(ns!("")), Some(value)))),
|
||||
_ => default_namespace(Some(value)),
|
||||
}
|
||||
},
|
||||
Some(&Delim('*')) => {
|
||||
iter.next(); // Consume '*'
|
||||
match iter.peek() {
|
||||
Some(&Delim('|')) => explicit_namespace(iter, AnyNamespace),
|
||||
Some(&Delim('|')) => explicit_namespace(iter, NamespaceConstraint::Any),
|
||||
_ => {
|
||||
if !in_attr_selector { default_namespace(None) }
|
||||
else { Err(()) }
|
||||
},
|
||||
}
|
||||
},
|
||||
Some(&Delim('|')) => explicit_namespace(iter, SpecificNamespace(ns!(""))),
|
||||
Some(&Delim('|')) => explicit_namespace(iter, NamespaceConstraint::Specific(ns!(""))),
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
@ -302,20 +320,37 @@ fn parse_attribute_selector(content: Vec<ComponentValue>, namespaces: &Namespace
|
|||
skip_whitespace(iter);
|
||||
// TODO: deal with empty value or value containing whitespace (see spec)
|
||||
let result = match iter.next() {
|
||||
None => AttrExists(attr), // [foo]
|
||||
Some(Delim('=')) => AttrEqual(
|
||||
attr, try!(parse_attribute_value(iter)),
|
||||
try!(parse_attribute_flags(iter))), // [foo=bar]
|
||||
Some(IncludeMatch) => AttrIncludes(attr, try!(parse_attribute_value(iter))), // [foo~=bar]
|
||||
// [foo]
|
||||
None => SimpleSelector::AttrExists(attr),
|
||||
|
||||
// [foo=bar]
|
||||
Some(Delim('=')) =>
|
||||
SimpleSelector::AttrEqual(attr, try!(parse_attribute_value(iter)),
|
||||
try!(parse_attribute_flags(iter))),
|
||||
|
||||
// [foo~=bar]
|
||||
Some(IncludeMatch) =>
|
||||
SimpleSelector::AttrIncludes(attr, try!(parse_attribute_value(iter))),
|
||||
|
||||
// [foo|=bar]
|
||||
Some(DashMatch) => {
|
||||
let value = try!(parse_attribute_value(iter));
|
||||
let dashing_value = format!("{}-", value);
|
||||
AttrDashMatch(attr, value, dashing_value) // [foo|=bar]
|
||||
SimpleSelector::AttrDashMatch(attr, value, dashing_value)
|
||||
},
|
||||
Some(PrefixMatch) => AttrPrefixMatch(attr, try!(parse_attribute_value(iter))), // [foo^=bar]
|
||||
|
||||
// [foo^=bar]
|
||||
Some(PrefixMatch) =>
|
||||
SimpleSelector::AttrPrefixMatch(attr, try!(parse_attribute_value(iter))),
|
||||
|
||||
// [foo*=bar]
|
||||
Some(SubstringMatch) => AttrSubstringMatch(attr, try!(parse_attribute_value(iter))),
|
||||
Some(SuffixMatch) => AttrSuffixMatch(attr, try!(parse_attribute_value(iter))), // [foo$=bar]
|
||||
Some(SubstringMatch) =>
|
||||
SimpleSelector::AttrSubstringMatch(attr, try!(parse_attribute_value(iter))),
|
||||
|
||||
// [foo$=bar]
|
||||
Some(SuffixMatch) =>
|
||||
SimpleSelector::AttrSuffixMatch(attr, try!(parse_attribute_value(iter))),
|
||||
|
||||
_ => return Err(())
|
||||
};
|
||||
skip_whitespace(iter);
|
||||
|
@ -336,9 +371,9 @@ fn parse_attribute_flags<I: Iterator<ComponentValue>>(iter: &mut Iter<I>)
|
|||
-> Result<CaseSensitivity, ()> {
|
||||
skip_whitespace(iter);
|
||||
match iter.next() {
|
||||
None => Ok(CaseSensitive),
|
||||
None => Ok(CaseSensitivity::CaseSensitive),
|
||||
Some(Ident(ref value)) if value.as_slice().eq_ignore_ascii_case("i")
|
||||
=> Ok(CaseInsensitive),
|
||||
=> Ok(CaseSensitivity::CaseInsensitive),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -388,11 +423,11 @@ fn parse_selector<I>(context: &ParserContext, iter: &mut Iter<I>, namespaces: &N
|
|||
let combinator = match iter.peek() {
|
||||
None => break, // EOF
|
||||
Some(&Comma) => break,
|
||||
Some(&Delim('>')) => { iter.next(); Child },
|
||||
Some(&Delim('+')) => { iter.next(); NextSibling },
|
||||
Some(&Delim('~')) => { iter.next(); LaterSibling },
|
||||
Some(&Delim('>')) => { iter.next(); Combinator::Child },
|
||||
Some(&Delim('+')) => { iter.next(); Combinator::NextSibling },
|
||||
Some(&Delim('~')) => { iter.next(); Combinator::LaterSibling },
|
||||
Some(_) => {
|
||||
if any_whitespace { Descendant }
|
||||
if any_whitespace { Combinator::Descendant }
|
||||
else { return Err(()) }
|
||||
}
|
||||
};
|
||||
|
@ -417,14 +452,14 @@ fn parse_negation(context: &ParserContext,
|
|||
-> Result<SimpleSelector,()> {
|
||||
let iter = &mut arguments.into_iter().peekable();
|
||||
match try!(parse_type_selector(iter, namespaces)) {
|
||||
Some(type_selector) => Ok(Negation(type_selector)),
|
||||
Some(type_selector) => Ok(SimpleSelector::Negation(type_selector)),
|
||||
None => {
|
||||
match try!(parse_one_simple_selector(context,
|
||||
iter,
|
||||
namespaces,
|
||||
/* inside_negation = */ true)) {
|
||||
Some(SimpleSelectorResult(simple_selector)) => {
|
||||
Ok(Negation(vec![simple_selector]))
|
||||
Some(SimpleSelectorParseResult::SimpleSelector(simple_selector)) => {
|
||||
Ok(SimpleSelector::Negation(vec![simple_selector]))
|
||||
}
|
||||
_ => Err(())
|
||||
}
|
||||
|
@ -455,8 +490,8 @@ fn parse_simple_selectors<I>(context: &ParserContext,
|
|||
namespaces,
|
||||
/* inside_negation = */ false)) {
|
||||
None => break,
|
||||
Some(SimpleSelectorResult(s)) => { simple_selectors.push(s); empty = false },
|
||||
Some(PseudoElementResult(p)) => { pseudo_element = Some(p); empty = false; break },
|
||||
Some(SimpleSelectorParseResult::SimpleSelector(s)) => { simple_selectors.push(s); empty = false },
|
||||
Some(SimpleSelectorParseResult::PseudoElement(p)) => { pseudo_element = Some(p); empty = false; break },
|
||||
}
|
||||
}
|
||||
if empty {
|
||||
|
@ -475,10 +510,10 @@ fn parse_functional_pseudo_class(context: &ParserContext,
|
|||
-> Result<SimpleSelector,()> {
|
||||
match name.as_slice().to_ascii_lower().as_slice() {
|
||||
// "lang" => parse_lang(arguments),
|
||||
"nth-child" => parse_nth(arguments.as_slice()).map(|(a, b)| NthChild(a, b)),
|
||||
"nth-last-child" => parse_nth(arguments.as_slice()).map(|(a, b)| NthLastChild(a, b)),
|
||||
"nth-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| NthOfType(a, b)),
|
||||
"nth-last-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| NthLastOfType(a, b)),
|
||||
"nth-child" => parse_nth(arguments.as_slice()).map(|(a, b)| SimpleSelector::NthChild(a, b)),
|
||||
"nth-last-child" => parse_nth(arguments.as_slice()).map(|(a, b)| SimpleSelector::NthLastChild(a, b)),
|
||||
"nth-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| SimpleSelector::NthOfType(a, b)),
|
||||
"nth-last-of-type" => parse_nth(arguments.as_slice()).map(|(a, b)| SimpleSelector::NthLastOfType(a, b)),
|
||||
"not" => {
|
||||
if inside_negation {
|
||||
Err(())
|
||||
|
@ -503,21 +538,21 @@ fn parse_one_simple_selector<I>(context: &ParserContext,
|
|||
where I: Iterator<ComponentValue> {
|
||||
match iter.peek() {
|
||||
Some(&IDHash(_)) => match iter.next() {
|
||||
Some(IDHash(id)) => Ok(Some(SimpleSelectorResult(
|
||||
IDSelector(Atom::from_slice(id.as_slice()))))),
|
||||
Some(IDHash(id)) => Ok(Some(SimpleSelectorParseResult::SimpleSelector(
|
||||
SimpleSelector::IDSelector(Atom::from_slice(id.as_slice()))))),
|
||||
_ => panic!("Implementation error, this should not happen."),
|
||||
},
|
||||
Some(&Delim('.')) => {
|
||||
iter.next();
|
||||
match iter.next() {
|
||||
Some(Ident(class)) => Ok(Some(SimpleSelectorResult(
|
||||
ClassSelector(Atom::from_slice(class.as_slice()))))),
|
||||
Some(Ident(class)) => Ok(Some(SimpleSelectorParseResult::SimpleSelector(
|
||||
SimpleSelector::ClassSelector(Atom::from_slice(class.as_slice()))))),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
Some(&SquareBracketBlock(_)) => match iter.next() {
|
||||
Some(SquareBracketBlock(content))
|
||||
=> Ok(Some(SimpleSelectorResult(try!(parse_attribute_selector(content, namespaces))))),
|
||||
=> Ok(Some(SimpleSelectorParseResult::SimpleSelector(try!(parse_attribute_selector(content, namespaces))))),
|
||||
_ => panic!("Implementation error, this should not happen."),
|
||||
},
|
||||
Some(&Colon) => {
|
||||
|
@ -528,18 +563,18 @@ fn parse_one_simple_selector<I>(context: &ParserContext,
|
|||
match name.as_slice().to_ascii_lower().as_slice() {
|
||||
// Supported CSS 2.1 pseudo-elements only.
|
||||
// ** Do not add to this list! **
|
||||
"before" => Ok(Some(PseudoElementResult(Before))),
|
||||
"after" => Ok(Some(PseudoElementResult(After))),
|
||||
// "first-line" => PseudoElementResult(FirstLine),
|
||||
// "first-letter" => PseudoElementResult(FirstLetter),
|
||||
"before" => Ok(Some(SimpleSelectorParseResult::PseudoElement(PseudoElement::Before))),
|
||||
"after" => Ok(Some(SimpleSelectorParseResult::PseudoElement(PseudoElement::After))),
|
||||
// "first-line" => SimpleSelectorParseResult::PseudoElement(FirstLine),
|
||||
// "first-letter" => SimpleSelectorParseResult::PseudoElement(FirstLetter),
|
||||
_ => Err(())
|
||||
}
|
||||
},
|
||||
Ok(result) => Ok(Some(SimpleSelectorResult(result))),
|
||||
Ok(result) => Ok(Some(SimpleSelectorParseResult::SimpleSelector(result))),
|
||||
},
|
||||
Some(Function(name, arguments))
|
||||
=> {
|
||||
Ok(Some(SimpleSelectorResult(try!(parse_functional_pseudo_class(
|
||||
Ok(Some(SimpleSelectorParseResult::SimpleSelector(try!(parse_functional_pseudo_class(
|
||||
context,
|
||||
name,
|
||||
arguments,
|
||||
|
@ -549,7 +584,7 @@ fn parse_one_simple_selector<I>(context: &ParserContext,
|
|||
Some(Colon) => {
|
||||
match iter.next() {
|
||||
Some(Ident(name))
|
||||
=> Ok(Some(PseudoElementResult(try!(parse_pseudo_element(name))))),
|
||||
=> Ok(Some(SimpleSelectorParseResult::PseudoElement(try!(parse_pseudo_element(name))))),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -562,23 +597,23 @@ fn parse_one_simple_selector<I>(context: &ParserContext,
|
|||
|
||||
fn parse_simple_pseudo_class(context: &ParserContext, name: &str) -> Result<SimpleSelector,()> {
|
||||
match name.to_ascii_lower().as_slice() {
|
||||
"any-link" => Ok(AnyLink),
|
||||
"link" => Ok(Link),
|
||||
"visited" => Ok(Visited),
|
||||
"hover" => Ok(Hover),
|
||||
"disabled" => Ok(Disabled),
|
||||
"enabled" => Ok(Enabled),
|
||||
"checked" => Ok(Checked),
|
||||
"indeterminate" => Ok(Indeterminate),
|
||||
"first-child" => Ok(FirstChild),
|
||||
"last-child" => Ok(LastChild),
|
||||
"only-child" => Ok(OnlyChild),
|
||||
"root" => Ok(Root),
|
||||
"first-of-type" => Ok(FirstOfType),
|
||||
"last-of-type" => Ok(LastOfType),
|
||||
"only-of-type" => Ok(OnlyOfType),
|
||||
"-servo-nonzero-border" if context.origin == UserAgentOrigin => Ok(ServoNonzeroBorder),
|
||||
// "empty" => Ok(Empty),
|
||||
"any-link" => Ok(SimpleSelector::AnyLink),
|
||||
"link" => Ok(SimpleSelector::Link),
|
||||
"visited" => Ok(SimpleSelector::Visited),
|
||||
"hover" => Ok(SimpleSelector::Hover),
|
||||
"disabled" => Ok(SimpleSelector::Disabled),
|
||||
"enabled" => Ok(SimpleSelector::Enabled),
|
||||
"checked" => Ok(SimpleSelector::Checked),
|
||||
"indeterminate" => Ok(SimpleSelector::Indeterminate),
|
||||
"first-child" => Ok(SimpleSelector::FirstChild),
|
||||
"last-child" => Ok(SimpleSelector::LastChild),
|
||||
"only-child" => Ok(SimpleSelector::OnlyChild),
|
||||
"root" => Ok(SimpleSelector::Root),
|
||||
"first-of-type" => Ok(SimpleSelector::FirstOfType),
|
||||
"last-of-type" => Ok(SimpleSelector::LastOfType),
|
||||
"only-of-type" => Ok(SimpleSelector::OnlyOfType),
|
||||
"-servo-nonzero-border" if context.origin == StylesheetOrigin::UserAgent => Ok(SimpleSelector::ServoNonzeroBorder),
|
||||
// "empty" => Ok(Empty),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -586,8 +621,8 @@ fn parse_simple_pseudo_class(context: &ParserContext, name: &str) -> Result<Simp
|
|||
fn parse_pseudo_element(name: String) -> Result<PseudoElement, ()> {
|
||||
match name.as_slice().to_ascii_lower().as_slice() {
|
||||
// All supported pseudo-elements
|
||||
"before" => Ok(Before),
|
||||
"after" => Ok(After),
|
||||
"before" => Ok(PseudoElement::Before),
|
||||
"after" => Ok(PseudoElement::After),
|
||||
// "first-line" => Some(FirstLine),
|
||||
// "first-letter" => Some(FirstLetter),
|
||||
_ => Err(())
|
||||
|
@ -634,9 +669,11 @@ mod tests {
|
|||
use sync::Arc;
|
||||
use cssparser;
|
||||
use namespaces::NamespaceMap;
|
||||
use selector_matching::AuthorOrigin;
|
||||
use selector_matching::StylesheetOrigin;
|
||||
use string_cache::Atom;
|
||||
use super::*;
|
||||
use super::SimpleSelector::*;
|
||||
use super::PseudoElement::*;
|
||||
|
||||
fn parse(input: &str) -> Result<Vec<Selector>, ()> {
|
||||
parse_ns(input, &NamespaceMap::new())
|
||||
|
@ -644,7 +681,7 @@ mod tests {
|
|||
|
||||
fn parse_ns(input: &str, namespaces: &NamespaceMap) -> Result<Vec<Selector>, ()> {
|
||||
let context = ParserContext {
|
||||
origin: AuthorOrigin,
|
||||
origin: StylesheetOrigin::Author,
|
||||
};
|
||||
parse_selector_list(&context, cssparser::tokenize(input).map(|(v, _)| v), namespaces)
|
||||
}
|
||||
|
@ -658,7 +695,7 @@ mod tests {
|
|||
assert!(parse("") == Err(()))
|
||||
assert!(parse("EeÉ") == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(LocalNameSelector(LocalName {
|
||||
simple_selectors: vec!(SimpleSelector::LocalNameSelector(LocalName {
|
||||
name: Atom::from_slice("EeÉ"),
|
||||
lower_name: Atom::from_slice("eeÉ") })),
|
||||
next: None,
|
||||
|
@ -668,7 +705,7 @@ mod tests {
|
|||
})))
|
||||
assert!(parse(".foo") == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(ClassSelector(Atom::from_slice("foo"))),
|
||||
simple_selectors: vec!(SimpleSelector::ClassSelector(Atom::from_slice("foo"))),
|
||||
next: None,
|
||||
}),
|
||||
pseudo_element: None,
|
||||
|
@ -676,7 +713,7 @@ mod tests {
|
|||
})))
|
||||
assert!(parse("#bar") == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(IDSelector(Atom::from_slice("bar"))),
|
||||
simple_selectors: vec!(SimpleSelector::IDSelector(Atom::from_slice("bar"))),
|
||||
next: None,
|
||||
}),
|
||||
pseudo_element: None,
|
||||
|
@ -684,11 +721,11 @@ mod tests {
|
|||
})))
|
||||
assert!(parse("e.foo#bar") == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(LocalNameSelector(LocalName {
|
||||
simple_selectors: vec!(SimpleSelector::LocalNameSelector(LocalName {
|
||||
name: Atom::from_slice("e"),
|
||||
lower_name: Atom::from_slice("e") }),
|
||||
ClassSelector(Atom::from_slice("foo")),
|
||||
IDSelector(Atom::from_slice("bar"))),
|
||||
SimpleSelector::ClassSelector(Atom::from_slice("foo")),
|
||||
SimpleSelector::IDSelector(Atom::from_slice("bar"))),
|
||||
next: None,
|
||||
}),
|
||||
pseudo_element: None,
|
||||
|
@ -698,12 +735,12 @@ mod tests {
|
|||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(IDSelector(Atom::from_slice("bar"))),
|
||||
next: Some((box CompoundSelector {
|
||||
simple_selectors: vec!(LocalNameSelector(LocalName {
|
||||
simple_selectors: vec!(SimpleSelector::LocalNameSelector(LocalName {
|
||||
name: Atom::from_slice("e"),
|
||||
lower_name: Atom::from_slice("e") }),
|
||||
ClassSelector(Atom::from_slice("foo"))),
|
||||
SimpleSelector::ClassSelector(Atom::from_slice("foo"))),
|
||||
next: None,
|
||||
}, Descendant)),
|
||||
}, Combinator::Descendant)),
|
||||
}),
|
||||
pseudo_element: None,
|
||||
specificity: specificity(1, 1, 1),
|
||||
|
@ -716,7 +753,7 @@ mod tests {
|
|||
simple_selectors: vec!(AttrExists(AttrSelector {
|
||||
name: Atom::from_slice("Foo"),
|
||||
lower_name: Atom::from_slice("foo"),
|
||||
namespace: SpecificNamespace(ns!("")),
|
||||
namespace: NamespaceConstraint::Specific(ns!("")),
|
||||
})),
|
||||
next: None,
|
||||
}),
|
||||
|
@ -731,7 +768,7 @@ mod tests {
|
|||
simple_selectors: vec!(AttrExists(AttrSelector {
|
||||
name: Atom::from_slice("Foo"),
|
||||
lower_name: Atom::from_slice("foo"),
|
||||
namespace: SpecificNamespace(ns!("")),
|
||||
namespace: NamespaceConstraint::Specific(ns!("")),
|
||||
})),
|
||||
next: None,
|
||||
}),
|
||||
|
@ -769,7 +806,7 @@ mod tests {
|
|||
name: atom!("div"),
|
||||
lower_name: atom!("div") })),
|
||||
next: None,
|
||||
}, Descendant)),
|
||||
}, Combinator::Descendant)),
|
||||
}),
|
||||
pseudo_element: Some(After),
|
||||
specificity: specificity(0, 0, 2),
|
||||
|
|
|
@ -28,9 +28,9 @@ pub struct Stylesheet {
|
|||
|
||||
|
||||
pub enum CSSRule {
|
||||
CSSStyleRule(StyleRule),
|
||||
CSSMediaRule(MediaRule),
|
||||
CSSFontFaceRule(FontFaceRule),
|
||||
Style(StyleRule),
|
||||
Media(MediaRule),
|
||||
FontFace(FontFaceRule),
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,11 +82,11 @@ impl Stylesheet {
|
|||
for rule in ErrorLoggerIterator(parse_stylesheet_rules(tokenize(css))) {
|
||||
let next_state; // Unitialized to force each branch to set it.
|
||||
match rule {
|
||||
QualifiedRule_(rule) => {
|
||||
Rule::QualifiedRule(rule) => {
|
||||
next_state = STATE_BODY;
|
||||
parse_style_rule(&parser_context, rule, &mut rules, &namespaces, &base_url)
|
||||
},
|
||||
AtRule_(rule) => {
|
||||
Rule::AtRule(rule) => {
|
||||
let lower_name = rule.name.as_slice().to_ascii_lower();
|
||||
match lower_name.as_slice() {
|
||||
"charset" => {
|
||||
|
@ -170,7 +170,7 @@ pub fn parse_style_rule(context: &ParserContext,
|
|||
// FIXME: avoid doing this for valid selectors
|
||||
let serialized = prelude.iter().to_css();
|
||||
match selectors::parse_selector_list(context, prelude.into_iter(), namespaces) {
|
||||
Ok(selectors) => parent_rules.push(CSSStyleRule(StyleRule{
|
||||
Ok(selectors) => parent_rules.push(CSSRule::Style(StyleRule{
|
||||
selectors: selectors,
|
||||
declarations: properties::parse_property_declaration_list(block.into_iter(), base_url)
|
||||
})),
|
||||
|
@ -183,11 +183,11 @@ pub fn iter_style_rules<'a>(rules: &[CSSRule], device: &media_queries::Device,
|
|||
callback: |&StyleRule|) {
|
||||
for rule in rules.iter() {
|
||||
match *rule {
|
||||
CSSStyleRule(ref rule) => callback(rule),
|
||||
CSSMediaRule(ref rule) => if rule.media_queries.evaluate(device) {
|
||||
CSSRule::Style(ref rule) => callback(rule),
|
||||
CSSRule::Media(ref rule) => if rule.media_queries.evaluate(device) {
|
||||
iter_style_rules(rule.rules.as_slice(), device, |s| callback(s))
|
||||
},
|
||||
CSSFontFaceRule(_) => {},
|
||||
CSSRule::FontFace(_) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ pub fn iter_style_rules<'a>(rules: &[CSSRule], device: &media_queries::Device,
|
|||
pub fn iter_stylesheet_media_rules(stylesheet: &Stylesheet, callback: |&MediaRule|) {
|
||||
for rule in stylesheet.rules.iter() {
|
||||
match *rule {
|
||||
CSSMediaRule(ref rule) => callback(rule),
|
||||
CSSRule::Media(ref rule) => callback(rule),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue