mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Add a struct to represent import rules, and parse them correctly.
This commit is contained in:
parent
e5d783c454
commit
444fef164e
3 changed files with 103 additions and 7 deletions
|
@ -26,6 +26,7 @@ use std::sync::Arc;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use style_traits::ToCss;
|
||||
use stylist::FnvHashMap;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
use viewport::ViewportRule;
|
||||
|
||||
|
||||
|
@ -79,7 +80,8 @@ impl CssRules {
|
|||
fn only_ns_or_import(&self) -> bool {
|
||||
self.0.iter().all(|r| {
|
||||
match *r {
|
||||
CssRule::Namespace(..) /* | CssRule::Import(..) */ => true,
|
||||
CssRule::Namespace(..) |
|
||||
CssRule::Import(..) => true,
|
||||
_ => false
|
||||
}
|
||||
})
|
||||
|
@ -180,6 +182,7 @@ pub enum CssRule {
|
|||
// https://drafts.csswg.org/cssom/#changes-from-5-december-2013
|
||||
|
||||
Namespace(Arc<RwLock<NamespaceRule>>),
|
||||
Import(Arc<RwLock<ImportRule>>),
|
||||
Style(Arc<RwLock<StyleRule>>),
|
||||
Media(Arc<RwLock<MediaRule>>),
|
||||
FontFace(Arc<RwLock<FontFaceRule>>),
|
||||
|
@ -235,6 +238,7 @@ impl CssRule {
|
|||
pub fn rule_type(&self) -> CssRuleType {
|
||||
match *self {
|
||||
CssRule::Style(_) => CssRuleType::Style,
|
||||
CssRule::Import(_) => CssRuleType::Import,
|
||||
CssRule::Media(_) => CssRuleType::Media,
|
||||
CssRule::FontFace(_) => CssRuleType::FontFace,
|
||||
CssRule::Keyframes(_) => CssRuleType::Keyframes,
|
||||
|
@ -246,7 +250,7 @@ impl CssRule {
|
|||
fn rule_state(&self) -> State {
|
||||
match *self {
|
||||
// CssRule::Charset(..) => State::Start,
|
||||
// CssRule::Import(..) => State::Imports,
|
||||
CssRule::Import(..) => State::Imports,
|
||||
CssRule::Namespace(..) => State::Namespaces,
|
||||
_ => State::Body,
|
||||
}
|
||||
|
@ -254,10 +258,19 @@ impl CssRule {
|
|||
|
||||
/// Call `f` with the slice of rules directly contained inside this rule.
|
||||
///
|
||||
/// Note that only some types of rules can contain rules. An empty slice is used for others.
|
||||
/// Note that only some types of rules can contain rules. An empty slice is
|
||||
/// used for others.
|
||||
pub fn with_nested_rules_and_mq<F, R>(&self, mut f: F) -> R
|
||||
where F: FnMut(&[CssRule], Option<&MediaList>) -> R {
|
||||
match *self {
|
||||
CssRule::Import(ref lock) => {
|
||||
let rule = lock.read();
|
||||
let media = rule.stylesheet.media.read();
|
||||
let rules = rule.stylesheet.rules.read();
|
||||
// FIXME(emilio): Include the nested rules if the stylesheet is
|
||||
// loaded.
|
||||
f(&rules.0, Some(&media))
|
||||
}
|
||||
CssRule::Namespace(_) |
|
||||
CssRule::Style(_) |
|
||||
CssRule::FontFace(_) |
|
||||
|
@ -315,6 +328,7 @@ impl ToCss for CssRule {
|
|||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
CssRule::Namespace(ref lock) => lock.read().to_css(dest),
|
||||
CssRule::Import(ref lock) => lock.read().to_css(dest),
|
||||
CssRule::Style(ref lock) => lock.read().to_css(dest),
|
||||
CssRule::FontFace(ref lock) => lock.read().to_css(dest),
|
||||
CssRule::Viewport(ref lock) => lock.read().to_css(dest),
|
||||
|
@ -346,6 +360,34 @@ impl ToCss for NamespaceRule {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// The [`@import`][import] at-rule.
|
||||
///
|
||||
/// [import]: https://drafts.csswg.org/css-cascade-3/#at-import
|
||||
#[derive(Debug)]
|
||||
pub struct ImportRule {
|
||||
pub url: SpecifiedUrl,
|
||||
|
||||
/// The stylesheet is always present.
|
||||
///
|
||||
/// It contains an empty list of rules and namespace set that is updated
|
||||
/// when it loads.
|
||||
pub stylesheet: Arc<Stylesheet>,
|
||||
}
|
||||
|
||||
impl ToCss for ImportRule {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
try!(dest.write_str("@import "));
|
||||
try!(self.url.to_css(dest));
|
||||
let media = self.stylesheet.media.read();
|
||||
if !media.is_empty() {
|
||||
try!(dest.write_str(" "));
|
||||
try!(media.to_css(dest));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KeyframesRule {
|
||||
pub name: Atom,
|
||||
|
@ -612,8 +654,32 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
"import" => {
|
||||
if self.state.get() <= State::Imports {
|
||||
self.state.set(State::Imports);
|
||||
// TODO: support @import
|
||||
return Err(()) // "@import is not supported yet"
|
||||
let url = try!(input.expect_url_or_string());
|
||||
let url =
|
||||
try!(SpecifiedUrl::parse_from_string(url,
|
||||
&self.context));
|
||||
|
||||
let media =
|
||||
Arc::new(RwLock::new(parse_media_query_list(input)));
|
||||
|
||||
let is_valid_url = url.url().is_some();
|
||||
|
||||
let import_rule = Arc::new(RwLock::new(
|
||||
ImportRule {
|
||||
url: url,
|
||||
stylesheet: Arc::new(Stylesheet {
|
||||
rules: Arc::new(RwLock::new(CssRules(vec![]))),
|
||||
media: media,
|
||||
origin: self.context.stylesheet_origin,
|
||||
base_url: self.context.base_url.clone(),
|
||||
namespaces: RwLock::new(Namespaces::default()),
|
||||
dirty_on_viewport_size_change: AtomicBool::new(false),
|
||||
disabled: AtomicBool::new(false),
|
||||
})
|
||||
}
|
||||
));
|
||||
|
||||
return Ok(AtRuleType::WithoutBlock(CssRule::Import(import_rule)))
|
||||
} else {
|
||||
self.state.set(State::Invalid);
|
||||
return Err(()) // "@import must be before any rule but @charset"
|
||||
|
|
|
@ -165,6 +165,25 @@ impl Stylist {
|
|||
self.add_stylesheet(stylesheet);
|
||||
}
|
||||
|
||||
debug!("Stylist stats:");
|
||||
debug!(" - Got {} sibling-affecting selectors",
|
||||
self.sibling_affecting_selectors.len());
|
||||
debug!(" - Got {} non-common-style-attribute-affecting selectors",
|
||||
self.non_common_style_affecting_attributes_selectors.len());
|
||||
debug!(" - Got {} deps for style-hint calculation",
|
||||
self.state_deps.len());
|
||||
|
||||
SelectorImpl::each_precomputed_pseudo_element(|pseudo| {
|
||||
// TODO: Consider not doing this and just getting the rules on the
|
||||
// fly. It should be a bit slower, but we'd take rid of the
|
||||
// extra field, and avoid this precomputation entirely.
|
||||
if let Some(map) = self.pseudos_map.remove(&pseudo) {
|
||||
let mut declarations = vec![];
|
||||
map.user_agent.get_universal_rules(&mut declarations);
|
||||
self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
|
||||
}
|
||||
});
|
||||
|
||||
self.is_device_dirty = false;
|
||||
true
|
||||
}
|
||||
|
@ -211,6 +230,10 @@ impl Stylist {
|
|||
}
|
||||
}
|
||||
}
|
||||
CssRule::Import(ref import) => {
|
||||
let import = import.read();
|
||||
self.add_stylesheet(&import.stylesheet)
|
||||
}
|
||||
CssRule::Keyframes(ref keyframes_rule) => {
|
||||
let keyframes_rule = keyframes_rule.read();
|
||||
debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
|
||||
|
@ -250,6 +273,7 @@ impl Stylist {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/// Computes the style for a given "precomputed" pseudo-element, taking the
|
||||
/// universal rules and applying them.
|
||||
///
|
||||
|
|
|
@ -11,6 +11,7 @@ use parser::{Parse, ParserContext};
|
|||
#[cfg(feature = "gecko")]
|
||||
use parser::ParserContextExtraData;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Write};
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
@ -76,7 +77,14 @@ pub struct SpecifiedUrl {
|
|||
impl Parse for SpecifiedUrl {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
let url = try!(input.expect_url());
|
||||
Self::parse_from_string(url, context)
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedUrl {
|
||||
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
||||
context: &ParserContext)
|
||||
-> Result<Self, ()> {
|
||||
let extra_data = match UrlExtraData::make_from(context) {
|
||||
Some(extra_data) => extra_data,
|
||||
None => {
|
||||
|
@ -96,9 +104,7 @@ impl Parse for SpecifiedUrl {
|
|||
extra_data: extra_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedUrl {
|
||||
pub fn extra_data(&self) -> &UrlExtraData {
|
||||
&self.extra_data
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue