pub trait RangedFeature<'a>: Sized {
type Value: Parse<'a>;
type FeatureName: Peek<'a> + Parse<'a> + RangedFeatureKeyword;
// Required methods
fn new_legacy(
open: LeftParen,
name: Self::FeatureName,
colon: Colon,
value: Self::Value,
close: RightParen,
) -> Result<Self>;
fn new_left(
open: LeftParen,
name: Self::FeatureName,
comparison: Comparison,
value: Self::Value,
close: RightParen,
) -> Result<Self>;
fn new_right(
open: LeftParen,
value: Self::Value,
comparison: Comparison,
name: Self::FeatureName,
close: RightParen,
) -> Result<Self>;
fn new_ranged(
open: LeftParen,
left: Self::Value,
left_comparison: Comparison,
name: Self::FeatureName,
right_comparison: Comparison,
value: Self::Value,
close: RightParen,
) -> Result<Self>;
// Provided method
fn parse_ranged_feature(p: &mut Parser<'a>) -> Result<Self> { ... }
}
Expand description
This trait provides an implementation for parsing a “Media Feature” in the “Range” context.
Rather than implementing this trait on an enum, use the ranged_feature! macro which expands to define the enum and necessary traits (Parse, this trait, and ToCursors) in a single macro call.
It does not implement Parse, but provides parse_ranged_feature(&mut Parser<'a>) -> Result<Self>
, which can make
for a trivial Parse implementation. The type Self::FeatureName must be defined, and represents the
<feature-name>
token(s), while Self::Value represents the <value>
token(s). The grammar of both <value>
and
<feature-name>
aren’t mandated by this spec but are very likely be an Ident
for the <feature-name>
and either
a Dimension
or Number
for the <value>
portion. Self::FeatureName must also implement the
crate::RangedFeatureKeyword trait which provides RangedFeatureKeyword::is_legacy to determine if the
<feature-name>
is unambiguously a legacy “min-” or “max-” prefixed name, for “legacy” ranged media conditions.
CSS defines the Media Feature in Ranged context as:
╭─ "=" ─╮
├─ "<" ─┤
├─ "<=" ─┤
├─ ">" ─┤
│├─ "(" ─╮─ [<feature-name> or <value>] ─╯─ ">=" ─╰─ [<feature-name> or <value>] ─╭─ ")" ─┤│
├────── <value> ─╮─ "<" ─╭── <feature-name> ─╮─ "<" ─╭── <value> ──────┤
│ ╰─ "<=" ─╯ ╰─ "<=" ─╯ │
╰────── <value> ─╮─ ">" ─╭── <feature-name> ─╮─ ">" ─╭── <value> ──────╯
╰─ ">=" ─╯ ╰─ ">=" ─╯
This trait deviates slightly from the CSS spec ever so slightly for a few reasons:
- It uses a
<comparison>
token to represent each of the comparison operators, implemented as Comparison. This makes for much more convenient parsing and subsequent analyses. - The CSS defined railroad diagram doesn’t quite fully convey that
<value> <comparison> <value>
and<feature-name> <comparison> <feature-name>
are not valid productions. This trait will fail to parse such productions, as do all existing implementations of CSS (i.e browsers). - It does not do the extra validation to ensure a left/right comparison are “directionally equivalent” - in other
words
<value> "<=" <feature-name> "=>" <value>
is a valid production in this trait - this allows for ASTs to factor in error tolerance. If an AST node wishes to be strict, it can check the comparators inside of RangedFeature::new_ranged and return an Err there. - It supports the “Legacy” modes which are defined for certain ranged media features. These legacy productions use
a colon token and typically have
min
andmax
variants of the RangedFeature::FeatureName. For examplewidth: 1024px
is equivalent towidth >= 1024px
, whilemax-width: 1024px
is equivalent tomax-width <= 1024px
. If an AST node wishes to not support legacy feature-names, it can return an Err in RangedFeature::new_legacy.
Given the above differences, the trait RangedFeature
parses a grammar defined as:
<comparison>
│├──╮─ "=" ─╭──┤│
├─ "<" ─┤
├─ "<=" ─┤
├─ ">" ─┤
╰─ ">=" ─╯
<ranged-feature-trait>
│├─ "(" ─╮─ <feature-name> ─ <comparison> ─ <value> ─────────────────────────────────╭─ ")" ─┤│
├─ <value> ─ <comparison> ─ <ranged-feautre-name> ──────────────────────────┤
├─ <value> ─ <comparison> ─ <ranged-feature-name> ─ <comparison> ─ <value> ─┤
╰─ <feature-name> ─ ":" ─ <value> ──────────────────────────────────────────╯
Required Associated Types§
type Value: Parse<'a>
type FeatureName: Peek<'a> + Parse<'a> + RangedFeatureKeyword
Required Methods§
Sourcefn new_legacy(
open: LeftParen,
name: Self::FeatureName,
colon: Colon,
value: Self::Value,
close: RightParen,
) -> Result<Self>
fn new_legacy( open: LeftParen, name: Self::FeatureName, colon: Colon, value: Self::Value, close: RightParen, ) -> Result<Self>
Method for constructing a “legacy” media feature. Legacy features always include a colon token.
Sourcefn new_left(
open: LeftParen,
name: Self::FeatureName,
comparison: Comparison,
value: Self::Value,
close: RightParen,
) -> Result<Self>
fn new_left( open: LeftParen, name: Self::FeatureName, comparison: Comparison, value: Self::Value, close: RightParen, ) -> Result<Self>
Method for constructing a “left” media feature. This method is called when the parsed tokens encountered
the <value>
token before the <feature-name>
.
Sourcefn new_right(
open: LeftParen,
value: Self::Value,
comparison: Comparison,
name: Self::FeatureName,
close: RightParen,
) -> Result<Self>
fn new_right( open: LeftParen, value: Self::Value, comparison: Comparison, name: Self::FeatureName, close: RightParen, ) -> Result<Self>
Method for constructing a “right” media feature. This method is called when the parsed tokens
encountered the <feature-name>
token before the <value>
.
Sourcefn new_ranged(
open: LeftParen,
left: Self::Value,
left_comparison: Comparison,
name: Self::FeatureName,
right_comparison: Comparison,
value: Self::Value,
close: RightParen,
) -> Result<Self>
fn new_ranged( open: LeftParen, left: Self::Value, left_comparison: Comparison, name: Self::FeatureName, right_comparison: Comparison, value: Self::Value, close: RightParen, ) -> Result<Self>
Method for constructing a “ranged” media feature. This method is called when the parsed tokens
encountered the <value>
token, followed by a <comparison>
, followed by a <feature-name>
, followed by a
<comparison>
followed lastly by a <value>
.
Provided Methods§
fn parse_ranged_feature(p: &mut Parser<'a>) -> Result<Self>
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.