/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
usesuper::{FeatureFlags, FeatureType, QueryFeatureExpression}; usecrate::values::computed; usecrate::{error_reporting::ContextualParseError, parser::ParserContext}; use cssparser::{Parser, Token}; use selectors::kleene_value::KleeneValue; use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// Whether to allow an `or` condition or not during parsing. #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)] enum AllowOr {
Yes,
No,
}
/// Represents a condition. #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] pubenum QueryCondition { /// A simple feature expression, implicitly parenthesized.
Feature(QueryFeatureExpression), /// A negation of a condition.
Not(Box<QueryCondition>), /// A set of joint operations.
Operation(Box<[QueryCondition]>, Operator), /// A condition wrapped in parenthesis.
InParens(Box<QueryCondition>), /// [ <function-token> <any-value>? ) ] | [ ( <any-value>? ) ]
GeneralEnclosed(String),
}
impl ToCss for QueryCondition { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where
W: fmt::Write,
{ match *self { // NOTE(emilio): QueryFeatureExpression already includes the // parenthesis.
QueryCondition::Feature(ref f) => f.to_css(dest),
QueryCondition::Not(ref c) => {
dest.write_str("not ")?;
c.to_css(dest)
},
QueryCondition::InParens(ref c) => {
dest.write_char('(')?;
c.to_css(dest)?;
dest.write_char(')')
},
QueryCondition::Operation(ref list, op) => { letmut iter = list.iter();
iter.next().unwrap().to_css(dest)?; for item in iter {
dest.write_char(' ')?;
op.to_css(dest)?;
dest.write_char(' ')?;
item.to_css(dest)?;
}
Ok(())
},
QueryCondition::GeneralEnclosed(ref s) => dest.write_str(&s),
}
}
}
/// Returns the union of all flags in the expression. This is useful for /// container queries. pubfn cumulative_flags(&self) -> FeatureFlags { letmut result = FeatureFlags::empty(); self.visit(&mut |condition| { ifletSelf::Feature(ref f) = condition {
result.insert(f.feature_flags())
}
});
result
}
/// Parse a single condition, disallowing `or` expressions. /// /// To be used from the legacy query syntax. pubfn parse_disallow_or<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
feature_type: FeatureType,
) -> Result<Self, ParseError<'i>> { Self::parse_internal(context, input, feature_type, AllowOr::No)
}
/// https://drafts.csswg.org/mediaqueries-5/#typedef-media-condition or /// https://drafts.csswg.org/mediaqueries-5/#typedef-media-condition-without-or /// (depending on `allow_or`). fn parse_internal<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
feature_type: FeatureType,
allow_or: AllowOr,
) -> Result<Self, ParseError<'i>> { let location = input.current_source_location(); if input.try_parse(|i| i.expect_ident_matching("not")).is_ok() { let inner_condition = Self::parse_in_parens(context, input, feature_type)?; return Ok(QueryCondition::Not(Box::new(inner_condition)));
}
let first_condition = Self::parse_in_parens(context, input, feature_type)?; let operator = match input.try_parse(Operator::parse) {
Ok(op) => op,
Err(..) => return Ok(first_condition),
};
fn parse_in_parenthesis_block<'i>(
context: &ParserContext,
input: &mut Parser<'i, '_>,
feature_type: FeatureType,
) -> Result<Self, ParseError<'i>> { // Base case. Make sure to preserve this error as it's more generally // relevant. let feature_error = match input.try_parse(|input| {
QueryFeatureExpression::parse_in_parenthesis_block(context, input, feature_type)
}) {
Ok(expr) => return Ok(Self::Feature(expr)),
Err(e) => e,
}; iflet Ok(inner) = Self::parse(context, input, feature_type) { return Ok(Self::InParens(Box::new(inner)));
}
Err(feature_error)
}
/// Parse a condition in parentheses, or `<general-enclosed>`. /// /// https://drafts.csswg.org/mediaqueries/#typedef-media-in-parens pubfn parse_in_parens<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
feature_type: FeatureType,
) -> Result<Self, ParseError<'i>> {
input.skip_whitespace(); let start = input.position(); let start_location = input.current_source_location(); match *input.next()? {
Token::ParenthesisBlock => { let nested = input.try_parse(|input| {
input.parse_nested_block(|input| { Self::parse_in_parenthesis_block(context, input, feature_type)
})
}); match nested {
Ok(nested) => return Ok(nested),
Err(e) => { // We're about to swallow the error in a `<general-enclosed>` // condition, so report it while we can. let loc = e.location; let error =
ContextualParseError::InvalidMediaRule(input.slice_from(start), e);
context.log_css_error(loc, error);
},
}
},
Token::Function(..) => { // TODO: handle `style()` queries, etc.
}, ref t => return Err(start_location.new_unexpected_token_error(t.clone())),
}
input.parse_nested_block(consume_any_value)?;
Ok(Self::GeneralEnclosed(input.slice_from(start).to_owned()))
}
/// Whether this condition matches the device and quirks mode. /// https://drafts.csswg.org/mediaqueries/#evaluating /// https://drafts.csswg.org/mediaqueries/#typedef-general-enclosed /// Kleene 3-valued logic is adopted here due to the introduction of /// <general-enclosed>. pubfn matches(&self, context: &computed::Context) -> KleeneValue { match *self {
QueryCondition::Feature(ref f) => f.matches(context),
QueryCondition::GeneralEnclosed(_) => KleeneValue::Unknown,
QueryCondition::InParens(ref c) => c.matches(context),
QueryCondition::Not(ref c) => !c.matches(context),
QueryCondition::Operation(ref conditions, op) => {
debug_assert!(!conditions.is_empty(), "We never create an empty op"); match op {
Operator::And => { letmut result = KleeneValue::True; for c in conditions.iter() {
result &= c.matches(context); if result == KleeneValue::False { break;
}
}
result
},
Operator::Or => { letmut result = KleeneValue::False; for c in conditions.iter() {
result |= c.matches(context); if result == KleeneValue::True { break;
}
}
result
},
}
},
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.