mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Add parsing a stylesheet form an iterator, a style attr form a string.
This commit is contained in:
parent
a4c2e9dcf1
commit
6ddc2c37d1
4 changed files with 87 additions and 67 deletions
|
@ -815,10 +815,15 @@ pub struct PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_property_declaration_list(input: ~[Node]) -> PropertyDeclarationBlock {
|
pub fn parse_style_attribute(input: &str) -> PropertyDeclarationBlock {
|
||||||
|
parse_property_declaration_list(tokenize(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I) -> PropertyDeclarationBlock {
|
||||||
let mut important = ~[];
|
let mut important = ~[];
|
||||||
let mut normal = ~[];
|
let mut normal = ~[];
|
||||||
for item in ErrorLoggerIterator(parse_declaration_list(input.move_iter())) {
|
for item in ErrorLoggerIterator(parse_declaration_list(input)) {
|
||||||
match item {
|
match item {
|
||||||
Decl_AtRule(rule) => log_css_error(
|
Decl_AtRule(rule) => log_css_error(
|
||||||
rule.location, fmt!("Unsupported at-rule in declaration list: @%s", rule.name)),
|
rule.location, fmt!("Unsupported at-rule in declaration list: @%s", rule.name)),
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::ascii::StrAsciiExt;
|
||||||
use extra::sort::tim_sort;
|
use extra::sort::tim_sort;
|
||||||
|
|
||||||
use selectors::*;
|
use selectors::*;
|
||||||
use stylesheets::parse_stylesheet;
|
use stylesheets::Stylesheet;
|
||||||
use media_queries::{Device, Screen};
|
use media_queries::{Device, Screen};
|
||||||
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use servo_util::tree::{TreeNodeRefAsElement, TreeNode, ElementLike};
|
use servo_util::tree::{TreeNodeRefAsElement, TreeNode, ElementLike};
|
||||||
|
@ -36,8 +36,7 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_stylesheet(&mut self, css_source: &str, origin: StylesheetOrigin) {
|
pub fn add_stylesheet(&mut self, stylesheet: Stylesheet, origin: StylesheetOrigin) {
|
||||||
let stylesheet = parse_stylesheet(css_source);
|
|
||||||
let rules = match origin {
|
let rules = match origin {
|
||||||
UserAgentOrigin => &mut self.ua_rules,
|
UserAgentOrigin => &mut self.ua_rules,
|
||||||
AuthorOrigin => &mut self.author_rules,
|
AuthorOrigin => &mut self.author_rules,
|
||||||
|
|
|
@ -18,10 +18,10 @@ extern mod servo_util (name = "util");
|
||||||
|
|
||||||
|
|
||||||
// The "real" public API
|
// The "real" public API
|
||||||
|
pub use stylesheets::Stylesheet;
|
||||||
pub use selector_matching::{Stylist, StylesheetOrigin};
|
pub use selector_matching::{Stylist, StylesheetOrigin};
|
||||||
pub use properties::{cascade, computed_values};
|
pub use properties::{cascade, ComputedValues, computed_values};
|
||||||
pub use properties::{PropertyDeclarationBlock,
|
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
||||||
parse_property_declaration_list}; // Style attributes
|
|
||||||
|
|
||||||
// Things that need to be public to make the compiler happy
|
// Things that need to be public to make the compiler happy
|
||||||
pub mod stylesheets;
|
pub mod stylesheets;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::str;
|
||||||
use std::iterator::Iterator;
|
use std::iterator::Iterator;
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
use cssparser::*;
|
use cssparser::*;
|
||||||
|
@ -31,65 +32,80 @@ pub struct StyleRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_stylesheet(css: &str) -> Stylesheet {
|
impl Stylesheet {
|
||||||
static STATE_CHARSET: uint = 1;
|
pub fn from_iter<I: Iterator<~[u8]>>(input: I) -> Stylesheet {
|
||||||
static STATE_IMPORTS: uint = 2;
|
let mut string = ~"";
|
||||||
static STATE_NAMESPACES: uint = 3;
|
let mut input = input;
|
||||||
static STATE_BODY: uint = 4;
|
// TODO: incremental tokinization/parsing
|
||||||
let mut state: uint = STATE_CHARSET;
|
for chunk in input {
|
||||||
|
// Assume UTF-8. This fails on invalid UTF-8
|
||||||
let mut rules = ~[];
|
// TODO: support character encodings (use rust-encodings in rust-cssparser)
|
||||||
let mut namespaces = NamespaceMap::new();
|
string.push_str(str::from_utf8_owned(chunk))
|
||||||
|
|
||||||
for rule in ErrorLoggerIterator(parse_stylesheet_rules(tokenize(css))) {
|
|
||||||
let next_state; // Unitialized to force each branch to set it.
|
|
||||||
match rule {
|
|
||||||
QualifiedRule(rule) => {
|
|
||||||
next_state = STATE_BODY;
|
|
||||||
parse_style_rule(rule, &mut rules, &namespaces)
|
|
||||||
},
|
|
||||||
AtRule(rule) => {
|
|
||||||
let lower_name = rule.name.to_ascii_lower();
|
|
||||||
match lower_name.as_slice() {
|
|
||||||
"charset" => {
|
|
||||||
if state > STATE_CHARSET {
|
|
||||||
log_css_error(rule.location, "@charset must be the first rule")
|
|
||||||
}
|
|
||||||
// Valid @charset rules are just ignored
|
|
||||||
next_state = STATE_IMPORTS;
|
|
||||||
},
|
|
||||||
"import" => {
|
|
||||||
if state > STATE_IMPORTS {
|
|
||||||
next_state = state;
|
|
||||||
log_css_error(rule.location,
|
|
||||||
"@import must be before any rule but @charset")
|
|
||||||
} else {
|
|
||||||
next_state = STATE_IMPORTS;
|
|
||||||
log_css_error(rule.location, "@import is not supported yet") // TODO
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"namespace" => {
|
|
||||||
if state > STATE_NAMESPACES {
|
|
||||||
next_state = state;
|
|
||||||
log_css_error(
|
|
||||||
rule.location,
|
|
||||||
"@namespace must be before any rule but @charset and @import"
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
next_state = STATE_NAMESPACES;
|
|
||||||
parse_namespace_rule(rule, &mut namespaces)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
next_state = STATE_BODY;
|
|
||||||
parse_nested_at_rule(lower_name, rule, &mut rules, &namespaces)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
state = next_state;
|
Stylesheet::from_str(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_str(css: &str) -> Stylesheet {
|
||||||
|
static STATE_CHARSET: uint = 1;
|
||||||
|
static STATE_IMPORTS: uint = 2;
|
||||||
|
static STATE_NAMESPACES: uint = 3;
|
||||||
|
static STATE_BODY: uint = 4;
|
||||||
|
let mut state: uint = STATE_CHARSET;
|
||||||
|
|
||||||
|
let mut rules = ~[];
|
||||||
|
let mut namespaces = NamespaceMap::new();
|
||||||
|
|
||||||
|
for rule in ErrorLoggerIterator(parse_stylesheet_rules(tokenize(css))) {
|
||||||
|
let next_state; // Unitialized to force each branch to set it.
|
||||||
|
match rule {
|
||||||
|
QualifiedRule(rule) => {
|
||||||
|
next_state = STATE_BODY;
|
||||||
|
parse_style_rule(rule, &mut rules, &namespaces)
|
||||||
|
},
|
||||||
|
AtRule(rule) => {
|
||||||
|
let lower_name = rule.name.to_ascii_lower();
|
||||||
|
match lower_name.as_slice() {
|
||||||
|
"charset" => {
|
||||||
|
if state > STATE_CHARSET {
|
||||||
|
log_css_error(rule.location, "@charset must be the first rule")
|
||||||
|
}
|
||||||
|
// Valid @charset rules are just ignored
|
||||||
|
next_state = STATE_IMPORTS;
|
||||||
|
},
|
||||||
|
"import" => {
|
||||||
|
if state > STATE_IMPORTS {
|
||||||
|
next_state = state;
|
||||||
|
log_css_error(rule.location,
|
||||||
|
"@import must be before any rule but @charset")
|
||||||
|
} else {
|
||||||
|
next_state = STATE_IMPORTS;
|
||||||
|
// TODO: support @import
|
||||||
|
log_css_error(rule.location, "@import is not supported yet")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"namespace" => {
|
||||||
|
if state > STATE_NAMESPACES {
|
||||||
|
next_state = state;
|
||||||
|
log_css_error(
|
||||||
|
rule.location,
|
||||||
|
"@namespace must be before any rule but @charset and @import"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
next_state = STATE_NAMESPACES;
|
||||||
|
parse_namespace_rule(rule, &mut namespaces)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
next_state = STATE_BODY;
|
||||||
|
parse_nested_at_rule(lower_name, rule, &mut rules, &namespaces)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
state = next_state;
|
||||||
|
}
|
||||||
|
Stylesheet{ rules: rules, namespaces: namespaces }
|
||||||
}
|
}
|
||||||
Stylesheet{ rules: rules, namespaces: namespaces }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +115,7 @@ pub fn parse_style_rule(rule: QualifiedRule, parent_rules: &mut ~[CSSRule],
|
||||||
match selectors::parse_selector_list(prelude, namespaces) {
|
match selectors::parse_selector_list(prelude, namespaces) {
|
||||||
Some(selectors) => parent_rules.push(CSSStyleRule(StyleRule{
|
Some(selectors) => parent_rules.push(CSSStyleRule(StyleRule{
|
||||||
selectors: selectors,
|
selectors: selectors,
|
||||||
declarations: properties::parse_property_declaration_list(block)
|
declarations: properties::parse_property_declaration_list(block.move_iter())
|
||||||
})),
|
})),
|
||||||
None => log_css_error(location, "Unsupported CSS selector."),
|
None => log_css_error(location, "Unsupported CSS selector."),
|
||||||
}
|
}
|
||||||
|
@ -125,7 +141,7 @@ impl Stylesheet {
|
||||||
|
|
||||||
struct StyleRuleIterator<'self> {
|
struct StyleRuleIterator<'self> {
|
||||||
device: &'self media_queries::Device,
|
device: &'self media_queries::Device,
|
||||||
// FIXME: I couldn’t get this to borrow-check with a stack of VecIterator
|
// FIXME: I couldn't get this to borrow-check with a stack of VecIterator
|
||||||
stack: ~[(&'self [CSSRule], uint)],
|
stack: ~[(&'self [CSSRule], uint)],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue