mirror of
https://github.com/servo/servo.git
synced 2025-08-09 07:25:35 +01:00
Upgrade to rust-cssparser master.
* Use associated types * Avoid mutation to gather parsing results.
This commit is contained in:
parent
7359f99f20
commit
966af0030a
11 changed files with 183 additions and 165 deletions
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::iter::Iterator;
|
||||
use std::ascii::AsciiExt;
|
||||
use url::Url;
|
||||
|
@ -10,11 +11,10 @@ use encoding::EncodingRef;
|
|||
|
||||
use cssparser::{Parser, decode_stylesheet_bytes,
|
||||
QualifiedRuleParser, AtRuleParser, RuleListParser, AtRuleType};
|
||||
use string_cache::Namespace;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use selectors::{Selector, parse_selector_list};
|
||||
use parser::ParserContext;
|
||||
use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
|
||||
use namespaces::{NamespaceMap, parse_namespace_rule};
|
||||
use media_queries::{self, Device, MediaQueryList, parse_media_query_list};
|
||||
use font_face::{FontFaceRule, Source, parse_font_face_block, iter_font_face_rules_inner};
|
||||
|
||||
|
@ -85,18 +85,26 @@ impl Stylesheet {
|
|||
}
|
||||
|
||||
pub fn from_str<'i>(css: &'i str, base_url: Url, origin: Origin) -> Stylesheet {
|
||||
let mut context = ParserContext {
|
||||
stylesheet_origin: origin,
|
||||
base_url: &base_url,
|
||||
namespaces: NamespaceMap::new()
|
||||
let rule_parser = TopLevelRuleParser {
|
||||
context: ParserContext::new(origin, &base_url),
|
||||
state: Cell::new(State::Start),
|
||||
};
|
||||
let rule_parser = MainRuleParser {
|
||||
context: &mut context,
|
||||
state: State::Start,
|
||||
};
|
||||
let rules = RuleListParser::new_for_stylesheet(&mut Parser::new(css), rule_parser)
|
||||
.filter_map(|result| result.ok())
|
||||
.collect();
|
||||
let mut input = Parser::new(css);
|
||||
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
|
||||
let mut rules = Vec::new();
|
||||
while let Some(result) = iter.next() {
|
||||
if let Ok(rule) = result {
|
||||
if let CSSRule::Namespace(ref prefix, ref namespace) = rule {
|
||||
if let Some(prefix) = prefix.as_ref() {
|
||||
iter.parser.context.namespaces.prefix_map.insert(
|
||||
prefix.clone(), namespace.clone());
|
||||
} else {
|
||||
iter.parser.context.namespaces.default = Some(namespace.clone());
|
||||
}
|
||||
}
|
||||
rules.push(rule);
|
||||
}
|
||||
}
|
||||
Stylesheet {
|
||||
origin: origin,
|
||||
rules: rules,
|
||||
|
@ -105,24 +113,19 @@ impl Stylesheet {
|
|||
}
|
||||
|
||||
|
||||
fn parse_nested_rules(context: &mut ParserContext, input: &mut Parser) -> Vec<CSSRule> {
|
||||
let parser = MainRuleParser {
|
||||
context: context,
|
||||
state: State::Body,
|
||||
};
|
||||
RuleListParser::new_for_nested_rule(input, parser)
|
||||
fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> Vec<CSSRule> {
|
||||
RuleListParser::new_for_nested_rule(input, NestedRuleParser { context: context })
|
||||
.filter_map(|result| result.ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
struct MainRuleParser<'a, 'b: 'a> {
|
||||
context: &'a mut ParserContext<'b>,
|
||||
state: State,
|
||||
struct TopLevelRuleParser<'a> {
|
||||
context: ParserContext<'a>,
|
||||
state: Cell<State>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd)]
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy)]
|
||||
enum State {
|
||||
Start = 1,
|
||||
Imports = 2,
|
||||
|
@ -137,14 +140,17 @@ enum AtRulePrelude {
|
|||
}
|
||||
|
||||
|
||||
impl<'a, 'b> AtRuleParser<AtRulePrelude, CSSRule> for MainRuleParser<'a, 'b> {
|
||||
fn parse_prelude(&mut self, name: &str, input: &mut Parser)
|
||||
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||
type Prelude = AtRulePrelude;
|
||||
type AtRule = CSSRule;
|
||||
|
||||
fn parse_prelude(&self, name: &str, input: &mut Parser)
|
||||
-> Result<AtRuleType<AtRulePrelude, CSSRule>, ()> {
|
||||
match_ignore_ascii_case! { name,
|
||||
"charset" => {
|
||||
if self.state <= State::Start {
|
||||
if self.state.get() <= State::Start {
|
||||
// Valid @charset rules are just ignored
|
||||
self.state = State::Imports;
|
||||
self.state.set(State::Imports);
|
||||
let charset = try!(input.expect_string()).into_owned();
|
||||
return Ok(AtRuleType::WithoutBlock(CSSRule::Charset(charset)))
|
||||
} else {
|
||||
|
@ -152,8 +158,8 @@ impl<'a, 'b> AtRuleParser<AtRulePrelude, CSSRule> for MainRuleParser<'a, 'b> {
|
|||
}
|
||||
},
|
||||
"import" => {
|
||||
if self.state <= State::Imports {
|
||||
self.state = State::Imports;
|
||||
if self.state.get() <= State::Imports {
|
||||
self.state.set(State::Imports);
|
||||
// TODO: support @import
|
||||
return Err(()) // "@import is not supported yet"
|
||||
} else {
|
||||
|
@ -161,10 +167,12 @@ impl<'a, 'b> AtRuleParser<AtRulePrelude, CSSRule> for MainRuleParser<'a, 'b> {
|
|||
}
|
||||
},
|
||||
"namespace" => {
|
||||
if self.state <= State::Namespaces {
|
||||
self.state = State::Namespaces;
|
||||
let (prefix, namespace) = try!(parse_namespace_rule(self.context, input));
|
||||
return Ok(AtRuleType::WithoutBlock(CSSRule::Namespace(prefix, namespace)))
|
||||
if self.state.get() <= State::Namespaces {
|
||||
self.state.set(State::Namespaces);
|
||||
|
||||
let prefix = input.try(|input| input.expect_ident()).ok().map(|p| p.into_owned());
|
||||
let url = Namespace(Atom::from_slice(try!(input.expect_url_or_string()).as_slice()));
|
||||
return Ok(AtRuleType::WithoutBlock(CSSRule::Namespace(prefix, url)))
|
||||
} else {
|
||||
return Err(()) // "@namespace must be before any rule but @charset and @import"
|
||||
}
|
||||
|
@ -172,8 +180,46 @@ impl<'a, 'b> AtRuleParser<AtRulePrelude, CSSRule> for MainRuleParser<'a, 'b> {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
self.state = State::Body;
|
||||
self.state.set(State::Body);
|
||||
AtRuleParser::parse_prelude(&NestedRuleParser { context: &self.context }, name, input)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
|
||||
AtRuleParser::parse_block(&NestedRuleParser { context: &self.context }, prelude, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
|
||||
type Prelude = Vec<Selector>;
|
||||
type QualifiedRule = CSSRule;
|
||||
|
||||
#[inline]
|
||||
fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector>, ()> {
|
||||
self.state.set(State::Body);
|
||||
QualifiedRuleParser::parse_prelude(&NestedRuleParser { context: &self.context }, input)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_block(&self, prelude: Vec<Selector>, input: &mut Parser) -> Result<CSSRule, ()> {
|
||||
QualifiedRuleParser::parse_block(&NestedRuleParser { context: &self.context },
|
||||
prelude, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct NestedRuleParser<'a, 'b: 'a> {
|
||||
context: &'a ParserContext<'b>,
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = AtRulePrelude;
|
||||
type AtRule = CSSRule;
|
||||
|
||||
fn parse_prelude(&self, name: &str, input: &mut Parser)
|
||||
-> Result<AtRuleType<AtRulePrelude, CSSRule>, ()> {
|
||||
match_ignore_ascii_case! { name,
|
||||
"media" => {
|
||||
let media_queries = parse_media_query_list(input);
|
||||
|
@ -186,7 +232,7 @@ impl<'a, 'b> AtRuleParser<AtRulePrelude, CSSRule> for MainRuleParser<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_block(&mut self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
|
||||
fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
|
||||
match prelude {
|
||||
AtRulePrelude::FontFace => {
|
||||
parse_font_face_block(self.context, input).map(CSSRule::FontFace)
|
||||
|
@ -202,13 +248,15 @@ impl<'a, 'b> AtRuleParser<AtRulePrelude, CSSRule> for MainRuleParser<'a, 'b> {
|
|||
}
|
||||
|
||||
|
||||
impl<'a, 'b> QualifiedRuleParser<Vec<Selector>, CSSRule> for MainRuleParser<'a, 'b> {
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<Vec<Selector>, ()> {
|
||||
self.state = State::Body;
|
||||
impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = Vec<Selector>;
|
||||
type QualifiedRule = CSSRule;
|
||||
|
||||
fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector>, ()> {
|
||||
parse_selector_list(self.context, input)
|
||||
}
|
||||
|
||||
fn parse_block(&mut self, prelude: Vec<Selector>, input: &mut Parser) -> Result<CSSRule, ()> {
|
||||
fn parse_block(&self, prelude: Vec<Selector>, input: &mut Parser) -> Result<CSSRule, ()> {
|
||||
Ok(CSSRule::Style(StyleRule {
|
||||
selectors: prelude,
|
||||
declarations: parse_property_declaration_list(self.context, input)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue