Format style component.

This commit is contained in:
chansuke 2018-09-09 16:24:45 +02:00 committed by Emilio Cobos Álvarez
parent 31fc6cd565
commit 8dab4d659a
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
120 changed files with 2207 additions and 1417 deletions

View file

@ -53,12 +53,12 @@ impl ToCss for MediaCondition {
MediaCondition::Not(ref c) => {
dest.write_str("not ")?;
c.to_css(dest)
}
},
MediaCondition::InParens(ref c) => {
dest.write_char('(')?;
c.to_css(dest)?;
dest.write_char(')')
}
},
MediaCondition::Operation(ref list, op) => {
let mut iter = list.iter();
iter.next().unwrap().to_css(dest)?;
@ -69,7 +69,7 @@ impl ToCss for MediaCondition {
item.to_css(dest)?;
}
Ok(())
}
},
}
}
}
@ -104,14 +104,12 @@ impl MediaCondition {
let is_negation = match *input.next()? {
Token::ParenthesisBlock => false,
Token::Ident(ref ident) if ident.eq_ignore_ascii_case("not") => true,
ref t => {
return Err(location.new_unexpected_token_error(t.clone()))
}
ref t => return Err(location.new_unexpected_token_error(t.clone())),
};
if is_negation {
let inner_condition = Self::parse_in_parens(context, input)?;
return Ok(MediaCondition::Not(Box::new(inner_condition)))
return Ok(MediaCondition::Not(Box::new(inner_condition)));
}
// ParenthesisBlock.
@ -162,7 +160,7 @@ impl MediaCondition {
input.parse_nested_block(|input| {
// Base case.
if let Ok(inner) = input.try(|i| Self::parse(context, i)) {
return Ok(MediaCondition::InParens(Box::new(inner)))
return Ok(MediaCondition::InParens(Box::new(inner)));
}
let expr = MediaFeatureExpression::parse_in_parenthesis_block(context, input)?;
Ok(MediaCondition::Feature(expr))
@ -178,14 +176,10 @@ impl MediaCondition {
MediaCondition::Operation(ref conditions, op) => {
let mut iter = conditions.iter();
match op {
Operator::And => {
iter.all(|c| c.matches(device, quirks_mode))
}
Operator::Or => {
iter.any(|c| c.matches(device, quirks_mode))
}
Operator::And => iter.all(|c| c.matches(device, quirks_mode)),
Operator::Or => iter.any(|c| c.matches(device, quirks_mode)),
}
}
},
}
}
}

View file

@ -30,10 +30,9 @@ type MediaFeatureEvaluator<T> = fn(
pub type KeywordSerializer = fn(KeywordDiscriminant) -> String;
/// Parses a given identifier.
pub type KeywordParser = for <'a, 'i, 't> fn(
context: &'a ParserContext,
input: &'a mut Parser<'i, 't>,
) -> Result<KeywordDiscriminant, ParseError<'i>>;
pub type KeywordParser =
for<'a, 'i, 't> fn(context: &'a ParserContext, input: &'a mut Parser<'i, 't>)
-> Result<KeywordDiscriminant, ParseError<'i>>;
/// An evaluator for a given media feature.
///
@ -70,50 +69,49 @@ pub enum Evaluator {
/// asserts if that's not true. As of today there's nothing like that (does that
/// even make sense?).
macro_rules! keyword_evaluator {
($actual_evaluator:ident, $keyword_type:ty) => {
{
fn __parse<'i, 't>(
context: &$crate::parser::ParserContext,
input: &mut $crate::cssparser::Parser<'i, 't>,
) -> Result<
$crate::media_queries::media_feature::KeywordDiscriminant,
::style_traits::ParseError<'i>,
> {
let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?;
Ok(kw as $crate::media_queries::media_feature::KeywordDiscriminant)
}
fn __serialize(kw: $crate::media_queries::media_feature::KeywordDiscriminant) -> String {
// This unwrap is ok because the only discriminants that get
// back to us is the ones that `parse` produces.
let value: $keyword_type =
::num_traits::cast::FromPrimitive::from_u8(kw).unwrap();
<$keyword_type as ::style_traits::ToCss>::to_css_string(&value)
}
fn __evaluate(
device: &$crate::media_queries::Device,
value: Option<$crate::media_queries::media_feature::KeywordDiscriminant>,
range_or_operator: Option<$crate::media_queries::media_feature_expression::RangeOrOperator>,
) -> bool {
debug_assert!(
range_or_operator.is_none(),
"Since when do keywords accept ranges?"
);
// This unwrap is ok because the only discriminants that get
// back to us is the ones that `parse` produces.
let value: Option<$keyword_type> =
value.map(|kw| ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap());
$actual_evaluator(device, value)
}
$crate::media_queries::media_feature::Evaluator::Enumerated {
parser: __parse,
serializer: __serialize,
evaluator: __evaluate,
}
($actual_evaluator:ident, $keyword_type:ty) => {{
fn __parse<'i, 't>(
context: &$crate::parser::ParserContext,
input: &mut $crate::cssparser::Parser<'i, 't>,
) -> Result<
$crate::media_queries::media_feature::KeywordDiscriminant,
::style_traits::ParseError<'i>,
> {
let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?;
Ok(kw as $crate::media_queries::media_feature::KeywordDiscriminant)
}
}
fn __serialize(kw: $crate::media_queries::media_feature::KeywordDiscriminant) -> String {
// This unwrap is ok because the only discriminants that get
// back to us is the ones that `parse` produces.
let value: $keyword_type = ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap();
<$keyword_type as ::style_traits::ToCss>::to_css_string(&value)
}
fn __evaluate(
device: &$crate::media_queries::Device,
value: Option<$crate::media_queries::media_feature::KeywordDiscriminant>,
range_or_operator: Option<
$crate::media_queries::media_feature_expression::RangeOrOperator,
>,
) -> bool {
debug_assert!(
range_or_operator.is_none(),
"Since when do keywords accept ranges?"
);
// This unwrap is ok because the only discriminants that get
// back to us is the ones that `parse` produces.
let value: Option<$keyword_type> =
value.map(|kw| ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap());
$actual_evaluator(device, value)
}
$crate::media_queries::media_feature::Evaluator::Enumerated {
parser: __parse,
serializer: __serialize,
evaluator: __evaluate,
}
}};
}
bitflags! {
@ -169,7 +167,7 @@ macro_rules! feature {
evaluator: $evaluator,
requirements: $reqs,
}
}
};
}
impl fmt::Debug for MediaFeatureDescription {

View file

@ -102,13 +102,9 @@ pub enum RangeOrOperator {
impl RangeOrOperator {
/// Evaluate a given range given an optional query value and a value from
/// the browser.
pub fn evaluate<T>(
range_or_op: Option<Self>,
query_value: Option<T>,
value: T,
) -> bool
pub fn evaluate<T>(range_or_op: Option<Self>, query_value: Option<T>, value: T) -> bool
where
T: PartialOrd + Zero
T: PartialOrd + Zero,
{
match query_value {
Some(v) => Self::evaluate_with_query_value(range_or_op, v, value),
@ -118,11 +114,7 @@ impl RangeOrOperator {
/// Evaluate a given range given a non-optional query value and a value from
/// the browser.
pub fn evaluate_with_query_value<T>(
range_or_op: Option<Self>,
query_value: T,
value: T,
) -> bool
pub fn evaluate_with_query_value<T>(range_or_op: Option<Self>, query_value: T, value: T) -> bool
where
T: PartialOrd,
{
@ -142,20 +134,14 @@ impl RangeOrOperator {
Range::Min => cmp == Ordering::Greater,
Range::Max => cmp == Ordering::Less,
}
}
RangeOrOperator::Operator(op) => {
match op {
Operator::Equal => cmp == Ordering::Equal,
Operator::GreaterThan => cmp == Ordering::Greater,
Operator::GreaterThanEqual => {
cmp == Ordering::Equal || cmp == Ordering::Greater
}
Operator::LessThan => cmp == Ordering::Less,
Operator::LessThanEqual => {
cmp == Ordering::Equal || cmp == Ordering::Less
}
}
}
},
RangeOrOperator::Operator(op) => match op {
Operator::Equal => cmp == Ordering::Equal,
Operator::GreaterThan => cmp == Ordering::Greater,
Operator::GreaterThanEqual => cmp == Ordering::Equal || cmp == Ordering::Greater,
Operator::LessThan => cmp == Ordering::Less,
Operator::LessThanEqual => cmp == Ordering::Equal || cmp == Ordering::Less,
},
}
}
}
@ -172,8 +158,8 @@ pub struct MediaFeatureExpression {
impl PartialEq for MediaFeatureExpression {
fn eq(&self, other: &Self) -> bool {
self.feature as *const _ == other.feature as *const _ &&
self.value == other.value &&
self.range_or_operator == other.range_or_operator
self.value == other.value &&
self.range_or_operator == other.range_or_operator
}
}
@ -184,7 +170,11 @@ impl ToCss for MediaFeatureExpression {
{
dest.write_str("(")?;
if self.feature.requirements.contains(ParsingRequirements::WEBKIT_PREFIX) {
if self
.feature
.requirements
.contains(ParsingRequirements::WEBKIT_PREFIX)
{
dest.write_str("-webkit-")?;
}
@ -215,9 +205,7 @@ impl ToCss for MediaFeatureExpression {
}
/// Consumes an operation or a colon, or returns an error.
fn consume_operation_or_colon(
input: &mut Parser,
) -> Result<Option<Operator>, ()> {
fn consume_operation_or_colon(input: &mut Parser) -> Result<Option<Operator>, ()> {
let first_delim = {
let next_token = match input.next() {
Ok(t) => t,
@ -238,14 +226,14 @@ fn consume_operation_or_colon(
} else {
Operator::GreaterThan
}
}
},
'<' => {
if input.try(|i| i.expect_delim('=')).is_ok() {
Operator::LessThanEqual
} else {
Operator::LessThan
}
}
},
_ => return Err(()),
}))
}
@ -256,7 +244,11 @@ impl MediaFeatureExpression {
value: Option<MediaExpressionValue>,
range_or_operator: Option<RangeOrOperator>,
) -> Self {
Self { feature, value, range_or_operator }
Self {
feature,
value,
range_or_operator,
}
}
/// Parse a media expression of the form:
@ -269,9 +261,7 @@ impl MediaFeatureExpression {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
input.expect_parenthesis_block()?;
input.parse_nested_block(|input| {
Self::parse_in_parenthesis_block(context, input)
})
input.parse_nested_block(|input| Self::parse_in_parenthesis_block(context, input))
}
/// Parse a media feature expression where we've already consumed the
@ -294,9 +284,7 @@ impl MediaFeatureExpression {
let mut requirements = ParsingRequirements::empty();
if context.chrome_rules_enabled() ||
context.stylesheet_origin == Origin::UserAgent
{
if context.chrome_rules_enabled() || context.stylesheet_origin == Origin::UserAgent {
requirements.insert(ParsingRequirements::CHROME_AND_UA_ONLY);
}
@ -313,7 +301,9 @@ impl MediaFeatureExpression {
if unsafe {
structs::StaticPrefs_sVarCache_layout_css_prefixes_device_pixel_ratio_webkit
} {
requirements.insert(ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED);
requirements.insert(
ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED,
);
}
}
}
@ -370,45 +360,41 @@ impl MediaFeatureExpression {
// Gecko doesn't allow ranged expressions without a
// value, so just reject them here too.
if range.is_some() {
return Err(input.new_custom_error(
StyleParseErrorKind::RangedExpressionWithNoValue
));
return Err(
input.new_custom_error(StyleParseErrorKind::RangedExpressionWithNoValue)
);
}
return Ok(Self::new(feature, None, None));
}
},
Ok(operator) => operator,
};
let range_or_operator = match range {
Some(range) => {
if operator.is_some() {
return Err(input.new_custom_error(
StyleParseErrorKind::MediaQueryUnexpectedOperator
));
return Err(
input.new_custom_error(StyleParseErrorKind::MediaQueryUnexpectedOperator)
);
}
Some(RangeOrOperator::Range(range))
}
None => {
match operator {
Some(operator) => {
if !feature.allows_ranges() {
return Err(input.new_custom_error(
StyleParseErrorKind::MediaQueryUnexpectedOperator
));
}
Some(RangeOrOperator::Operator(operator))
},
None => match operator {
Some(operator) => {
if !feature.allows_ranges() {
return Err(input
.new_custom_error(StyleParseErrorKind::MediaQueryUnexpectedOperator));
}
None => None,
}
}
Some(RangeOrOperator::Operator(operator))
},
None => None,
},
};
let value =
MediaExpressionValue::parse(feature, context, input).map_err(|err| {
err.location
.new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue)
})?;
let value = MediaExpressionValue::parse(feature, context, input).map_err(|err| {
err.location
.new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue)
})?;
Ok(Self::new(feature, Some(value), range_or_operator))
}
@ -419,13 +405,11 @@ impl MediaFeatureExpression {
macro_rules! expect {
($variant:ident) => {
value.map(|value| {
match *value {
MediaExpressionValue::$variant(ref v) => v,
_ => unreachable!("Unexpected MediaExpressionValue"),
}
value.map(|value| match *value {
MediaExpressionValue::$variant(ref v) => v,
_ => unreachable!("Unexpected MediaExpressionValue"),
})
}
};
}
match self.feature.evaluator {
@ -436,13 +420,11 @@ impl MediaFeatureExpression {
})
});
eval(device, computed, self.range_or_operator)
}
},
Evaluator::Integer(eval) => {
eval(device, expect!(Integer).cloned(), self.range_or_operator)
}
Evaluator::Float(eval) => {
eval(device, expect!(Float).cloned(), self.range_or_operator)
}
},
Evaluator::Float(eval) => eval(device, expect!(Float).cloned(), self.range_or_operator),
Evaluator::IntRatio(eval) => {
eval(device, expect!(IntRatio).cloned(), self.range_or_operator)
},
@ -453,20 +435,16 @@ impl MediaFeatureExpression {
})
});
eval(device, computed, self.range_or_operator)
}
},
Evaluator::Enumerated { evaluator, .. } => {
evaluator(
device,
expect!(Enumerated).cloned(),
self.range_or_operator,
)
}
Evaluator::Ident(eval) => {
eval(device, expect!(Ident).cloned(), self.range_or_operator)
}
Evaluator::BoolInteger(eval) => {
eval(device, expect!(BoolInteger).cloned(), self.range_or_operator)
}
evaluator(device, expect!(Enumerated).cloned(), self.range_or_operator)
},
Evaluator::Ident(eval) => eval(device, expect!(Ident).cloned(), self.range_or_operator),
Evaluator::BoolInteger(eval) => eval(
device,
expect!(BoolInteger).cloned(),
self.range_or_operator,
),
}
}
}
@ -502,11 +480,7 @@ pub enum MediaExpressionValue {
}
impl MediaExpressionValue {
fn to_css<W>(
&self,
dest: &mut CssWriter<W>,
for_expr: &MediaFeatureExpression,
) -> fmt::Result
fn to_css<W>(&self, dest: &mut CssWriter<W>, for_expr: &MediaFeatureExpression) -> fmt::Result
where
W: fmt::Write,
{
@ -515,18 +489,12 @@ impl MediaExpressionValue {
MediaExpressionValue::Integer(v) => v.to_css(dest),
MediaExpressionValue::Float(v) => v.to_css(dest),
MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }),
MediaExpressionValue::IntRatio(ratio) => {
ratio.to_css(dest)
},
MediaExpressionValue::IntRatio(ratio) => ratio.to_css(dest),
MediaExpressionValue::Resolution(ref r) => r.to_css(dest),
MediaExpressionValue::Ident(ref ident) => serialize_atom_identifier(ident, dest),
MediaExpressionValue::Enumerated(value) => {
match for_expr.feature.evaluator {
Evaluator::Enumerated { serializer, .. } => {
dest.write_str(&*serializer(value))
}
_ => unreachable!(),
}
MediaExpressionValue::Enumerated(value) => match for_expr.feature.evaluator {
Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)),
_ => unreachable!(),
},
}
}
@ -540,11 +508,11 @@ impl MediaExpressionValue {
Evaluator::Length(..) => {
let length = Length::parse_non_negative(context, input)?;
MediaExpressionValue::Length(length)
}
},
Evaluator::Integer(..) => {
let integer = Integer::parse_non_negative(context, input)?;
MediaExpressionValue::Integer(integer.value() as u32)
}
},
Evaluator::BoolInteger(..) => {
let integer = Integer::parse_non_negative(context, input)?;
let value = integer.value();
@ -552,29 +520,26 @@ impl MediaExpressionValue {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
MediaExpressionValue::BoolInteger(value == 1)
}
},
Evaluator::Float(..) => {
let number = Number::parse(context, input)?;
MediaExpressionValue::Float(number.get())
}
},
Evaluator::IntRatio(..) => {
let a = Integer::parse_positive(context, input)?;
input.expect_delim('/')?;
let b = Integer::parse_positive(context, input)?;
MediaExpressionValue::IntRatio(AspectRatio(
a.value() as u32,
b.value() as u32
))
}
MediaExpressionValue::IntRatio(AspectRatio(a.value() as u32, b.value() as u32))
},
Evaluator::Resolution(..) => {
MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
}
},
Evaluator::Enumerated { parser, .. } => {
MediaExpressionValue::Enumerated(parser(context, input)?)
}
},
Evaluator::Ident(..) => {
MediaExpressionValue::Ident(Atom::from(input.expect_ident()?.as_ref()))
}
},
})
}
}

View file

@ -30,10 +30,7 @@ impl MediaList {
/// "not all", see:
///
/// <https://drafts.csswg.org/mediaqueries/#error-handling>
pub fn parse(
context: &ParserContext,
input: &mut Parser,
) -> Self {
pub fn parse(context: &ParserContext, input: &mut Parser) -> Self {
if input.is_exhausted() {
return Self::empty();
}
@ -48,8 +45,10 @@ impl MediaList {
Err(err) => {
media_queries.push(MediaQuery::never_matching());
let location = err.location;
let error =
ContextualParseError::InvalidMediaRule(input.slice_from(start_position), err);
let error = ContextualParseError::InvalidMediaRule(
input.slice_from(start_position),
err,
);
context.log_css_error(location, error);
},
}
@ -79,8 +78,10 @@ impl MediaList {
let media_match = mq.media_type.matches(device.media_type());
// Check if the media condition match.
let query_match = media_match &&
mq.condition.as_ref().map_or(true, |c| c.matches(device, quirks_mode));
let query_match = media_match && mq
.condition
.as_ref()
.map_or(true, |c| c.matches(device, quirks_mode));
// Apply the logical NOT qualifier to the result
match mq.qualifier {

View file

@ -15,7 +15,6 @@ use style_traits::{CssWriter, ParseError, ToCss};
use super::media_condition::MediaCondition;
use values::CustomIdent;
/// <https://drafts.csswg.org/mediaqueries/#mq-prefix>
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
pub enum Qualifier {
@ -125,12 +124,13 @@ impl MediaQuery {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let (qualifier, explicit_media_type) = input.try(|input| -> Result<_, ()> {
let qualifier = input.try(Qualifier::parse).ok();
let ident = input.expect_ident().map_err(|_| ())?;
let media_type = MediaQueryType::parse(&ident)?;
Ok((qualifier, Some(media_type)))
}).unwrap_or_default();
let (qualifier, explicit_media_type) = input
.try(|input| -> Result<_, ()> {
let qualifier = input.try(Qualifier::parse).ok();
let ident = input.expect_ident().map_err(|_| ())?;
let media_type = MediaQueryType::parse(&ident)?;
Ok((qualifier, Some(media_type)))
}).unwrap_or_default();
let condition = if explicit_media_type.is_none() {
Some(MediaCondition::parse(context, input)?)
@ -141,7 +141,11 @@ impl MediaQuery {
};
let media_type = explicit_media_type.unwrap_or(MediaQueryType::All);
Ok(Self { qualifier, media_type, condition })
Ok(Self {
qualifier,
media_type,
condition,
})
}
}