style: Add @keyframe rule parsing.

This commit is contained in:
Emilio Cobos Álvarez 2016-06-16 16:14:09 +02:00
parent 7b2080c5b7
commit c1fd7432e9
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
5 changed files with 197 additions and 15 deletions

View file

@ -9,6 +9,7 @@ use cssparser::{AtRuleType, RuleListParser};
use encoding::EncodingRef;
use error_reporting::ParseErrorReporter;
use font_face::{FontFaceRule, parse_font_face_block};
use keyframes::{Keyframe, parse_keyframe_list};
use media_queries::{Device, MediaQueryList, parse_media_query_list};
use parser::{ParserContext, ParserContextExtraData, log_css_error};
use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
@ -62,6 +63,14 @@ pub enum CSSRule<Impl: SelectorImpl> {
Media(MediaRule<Impl>),
FontFace(FontFaceRule),
Viewport(ViewportRule),
Keyframes(KeyframesRule),
}
#[derive(Debug, HeapSizeOf, PartialEq)]
pub struct KeyframesRule {
pub name: String,
pub keyframes: Vec<Keyframe>,
}
#[derive(Debug, PartialEq)]
@ -71,6 +80,7 @@ pub struct MediaRule<Impl: SelectorImpl> {
pub rules: Vec<CSSRule<Impl>>,
}
impl<Impl: SelectorImpl> MediaRule<Impl> {
#[inline]
pub fn evaluate(&self, device: &Device) -> bool {
@ -127,7 +137,7 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
let mut input = Parser::new(css);
input.look_for_viewport_percentages();
let mut rules = Vec::new();
let mut rules = vec![];
{
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
while let Some(result) = iter.next() {
@ -142,6 +152,7 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
Some(namespace.clone());
}
}
rules.push(rule);
}
Err(range) => {
@ -153,6 +164,7 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
}
}
}
Stylesheet {
origin: origin,
rules: rules,
@ -253,7 +265,7 @@ pub mod rule_filter {
use std::marker::PhantomData;
use super::super::font_face::FontFaceRule;
use super::super::viewport::ViewportRule;
use super::{CSSRule, MediaRule, StyleRule};
use super::{CSSRule, KeyframesRule, MediaRule, StyleRule};
macro_rules! rule_filter {
($variant:ident -> $value:ty) => {
@ -266,6 +278,8 @@ pub mod rule_filter {
impl<'a, I, Impl: SelectorImpl + 'a> $variant<'a, I>
where I: Iterator<Item=&'a CSSRule<Impl>> {
#[inline]
pub fn new(iter: I) -> $variant<'a, I> {
$variant {
iter: iter,
@ -300,6 +314,7 @@ pub mod rule_filter {
rule_filter!(Style -> StyleRule<Impl>);
rule_filter!(FontFace -> FontFaceRule);
rule_filter!(Viewport -> ViewportRule);
rule_filter!(Keyframes -> KeyframesRule);
}
/// Extension methods for `CSSRule` iterators.
@ -315,6 +330,9 @@ pub trait CSSRuleIteratorExt<'a, Impl: SelectorImpl + 'a>: Iterator<Item=&'a CSS
/// Yield only @viewport rules.
fn viewport(self) -> rule_filter::Viewport<'a, Self>;
/// Yield only @keyframes rules.
fn keyframes(self) -> rule_filter::Keyframes<'a, Self>;
}
impl<'a, I, Impl: SelectorImpl + 'a> CSSRuleIteratorExt<'a, Impl> for I where I: Iterator<Item=&'a CSSRule<Impl>> {
@ -337,6 +355,11 @@ impl<'a, I, Impl: SelectorImpl + 'a> CSSRuleIteratorExt<'a, Impl> for I where I:
fn viewport(self) -> rule_filter::Viewport<'a, I> {
rule_filter::Viewport::new(self)
}
#[inline]
fn keyframes(self) -> rule_filter::Keyframes<'a, I> {
rule_filter::Keyframes::new(self)
}
}
fn parse_nested_rules<Impl: SelectorImpl>(context: &ParserContext, input: &mut Parser) -> Vec<CSSRule<Impl>> {
@ -376,9 +399,14 @@ enum State {
enum AtRulePrelude {
/// A @font-face rule prelude.
FontFace,
/// A @media rule prelude, with its media queries.
Media(MediaQueryList),
/// A @viewport rule prelude.
Viewport,
/// A @keyframes rule, with its animation name.
Keyframes(String),
}
@ -478,6 +506,10 @@ impl<'a, 'b, Impl: SelectorImpl> AtRuleParser for NestedRuleParser<'a, 'b, Impl>
Err(())
}
},
"keyframes" => {
let name = try!(input.expect_ident());
Ok(AtRuleType::WithBlock(AtRulePrelude::Keyframes(name.into_owned())))
},
_ => Err(())
}
}
@ -496,11 +528,16 @@ impl<'a, 'b, Impl: SelectorImpl> AtRuleParser for NestedRuleParser<'a, 'b, Impl>
AtRulePrelude::Viewport => {
ViewportRule::parse(input, self.context).map(CSSRule::Viewport)
}
AtRulePrelude::Keyframes(name) => {
Ok(CSSRule::Keyframes(KeyframesRule {
name: name,
keyframes: try!(parse_keyframe_list(&self.context, input)),
}))
}
}
}
}
impl<'a, 'b, Impl: SelectorImpl> QualifiedRuleParser for NestedRuleParser<'a, 'b, Impl> {
type Prelude = Vec<Selector<Impl>>;
type QualifiedRule = CSSRule<Impl>;