mirror of
https://github.com/servo/servo.git
synced 2025-08-14 18:05:36 +01:00
style: Evaluate MediaConditions, and glue it all together.
Bug: 1422225 Reviewed-by: xidorn MozReview-Commit-ID: 3MThE2FvfDf
This commit is contained in:
parent
d2a1895752
commit
3a92fd1cfc
4 changed files with 96 additions and 58 deletions
|
@ -7,11 +7,12 @@
|
|||
//! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use context::QuirksMode;
|
||||
use parser::ParserContext;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||
|
||||
use super::MediaFeatureExpression;
|
||||
use super::{Device, MediaFeatureExpression};
|
||||
|
||||
|
||||
/// A binary `and` or `or` operator.
|
||||
|
@ -22,7 +23,15 @@ pub enum Operator {
|
|||
Or,
|
||||
}
|
||||
|
||||
/// Whether to allow an `or` condition or not during parsing.
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Parse, ToCss)]
|
||||
enum AllowOr {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
/// Represents a media condition.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||
pub enum MediaCondition {
|
||||
/// A simple media feature expression, implicitly parenthesized.
|
||||
Feature(MediaFeatureExpression),
|
||||
|
@ -72,6 +81,24 @@ impl MediaCondition {
|
|||
pub fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowOr::Yes)
|
||||
}
|
||||
|
||||
/// Parse a single media condition, disallowing `or` expressions.
|
||||
///
|
||||
/// To be used from the legacy media query syntax.
|
||||
pub fn parse_disallow_or<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowOr::No)
|
||||
}
|
||||
|
||||
fn parse_internal<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_or: AllowOr,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let location = input.current_source_location();
|
||||
|
||||
|
@ -96,6 +123,10 @@ impl MediaCondition {
|
|||
Err(..) => return Ok(first_condition),
|
||||
};
|
||||
|
||||
if allow_or == AllowOr::No && operator == Operator::Or {
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
|
||||
let mut conditions = vec![];
|
||||
conditions.push(first_condition);
|
||||
conditions.push(Self::parse_in_parens(context, input)?);
|
||||
|
@ -140,4 +171,24 @@ impl MediaCondition {
|
|||
Ok(MediaCondition::InParens(Box::new(inner)))
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether this condition matches the device and quirks mode.
|
||||
pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool {
|
||||
match *self {
|
||||
MediaCondition::Feature(ref f) => f.matches(device, quirks_mode),
|
||||
MediaCondition::InParens(ref c) => c.matches(device, quirks_mode),
|
||||
MediaCondition::Not(ref c) => !c.matches(device, quirks_mode),
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue