Skip to content

Commit

Permalink
Support base_url in stylesheet
Browse files Browse the repository at this point in the history
  • Loading branch information
recrack committed Feb 19, 2014
1 parent a12608d commit 7b56e75
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 26 deletions.
4 changes: 3 additions & 1 deletion src/components/script/dom/element.rs
Expand Up @@ -221,7 +221,9 @@ impl Element {

match local_name.as_slice() {
"style" => {
self.style_attribute = Some(style::parse_style_attribute(value))
let doc = self.node.owner_doc();
let base_url = doc.document().url.clone();
self.style_attribute = Some(style::parse_style_attribute(value, &base_url))
}
"id" if abstract_self.is_in_doc() => {
// XXX: this dual declaration are workaround to avoid the compile error:
Expand Down
7 changes: 3 additions & 4 deletions src/components/script/html/hubbub_html_parser.rs
Expand Up @@ -26,7 +26,6 @@ use servo_util::url::parse_url;
use std::cast;
use std::cell::RefCell;
use std::comm::{Port, SharedChan};
use std::from_str::FromStr;
use std::str;
use style::Stylesheet;

Expand Down Expand Up @@ -277,7 +276,8 @@ pub fn parse_html(cx: *JSContext,

debug!("Fetched page; metadata is {:?}", load_response.metadata);

let url2 = load_response.metadata.final_url.clone();
let base_url = load_response.metadata.final_url.clone();
let url2 = base_url.clone();
let url3 = url2.clone();

// Store the final URL before we start parsing, so that DOM routines
Expand Down Expand Up @@ -485,7 +485,6 @@ pub fn parse_html(cx: *JSContext,
// We've reached the end of a <style> so we can submit all the text to the parser.
unsafe {
let style: AbstractNode = NodeWrapping::from_hubbub_node(style);
let url = FromStr::from_str("http://example.com/"); // FIXME
let mut data = ~[];
debug!("iterating over children {:?}", style.first_child());
for child in style.children() {
Expand All @@ -496,7 +495,7 @@ pub fn parse_html(cx: *JSContext,
}

debug!("style data = {:?}", data);
let provenance = InlineProvenance(url.unwrap(), data.concat());
let provenance = InlineProvenance(base_url.clone(), data.concat());
css_chan3.send(CSSTaskNewFile(provenance));
}
},
Expand Down
7 changes: 4 additions & 3 deletions src/components/style/media_queries.rs
Expand Up @@ -9,6 +9,7 @@ use cssparser::ast::*;
use errors::{ErrorLoggerIterator, log_css_error};
use stylesheets::{CSSRule, CSSMediaRule, parse_style_rule, parse_nested_at_rule};
use namespaces::NamespaceMap;
use extra::url::Url;


pub struct MediaRule {
Expand Down Expand Up @@ -48,7 +49,7 @@ pub struct Device {


pub fn parse_media_rule(rule: AtRule, parent_rules: &mut ~[CSSRule],
namespaces: &NamespaceMap) {
namespaces: &NamespaceMap, base_url: &Url) {
let media_queries = parse_media_query_list(rule.prelude);
let block = match rule.block {
Some(block) => block,
Expand All @@ -60,9 +61,9 @@ pub fn parse_media_rule(rule: AtRule, parent_rules: &mut ~[CSSRule],
let mut rules = ~[];
for rule in ErrorLoggerIterator(parse_rule_list(block.move_iter())) {
match rule {
QualifiedRule(rule) => parse_style_rule(rule, &mut rules, namespaces),
QualifiedRule(rule) => parse_style_rule(rule, &mut rules, namespaces, base_url),
AtRule(rule) => parse_nested_at_rule(
rule.name.to_ascii_lower(), rule, &mut rules, namespaces),
rule.name.to_ascii_lower(), rule, &mut rules, namespaces, base_url),
}
}
parent_rules.push(CSSMediaRule(MediaRule {
Expand Down
129 changes: 117 additions & 12 deletions src/components/style/properties.rs.mako
Expand Up @@ -7,6 +7,7 @@
use std::ascii::StrAsciiExt;
pub use servo_util::url::parse_url;
pub use extra::arc::Arc;
pub use extra::url::Url;
use servo_util::cowarc::CowArc;

pub use cssparser::*;
Expand Down Expand Up @@ -50,7 +51,9 @@ STYLE_STRUCTS = []
THIS_STYLE_STRUCT = None
LONGHANDS = []
LONGHANDS_BY_NAME = {}
LONGHANDS_WITH_URL = []
SHORTHANDS = []
SHORTHANDS_WITH_URL = []
def new_style_struct(name, is_inherited):
global THIS_STYLE_STRUCT
Expand Down Expand Up @@ -103,6 +106,32 @@ pub mod longhands {
}
</%def>

<%def name="url_longhand(name, no_super=False)">
<%
property = Longhand(name)
THIS_STYLE_STRUCT.longhands.append(property)
LONGHANDS_WITH_URL.append(property)
LONGHANDS_BY_NAME[name] = property
%>
pub mod ${property.ident} {
% if not no_super:
use super::*;
% endif
pub use self::computed_value::*;
${caller.body()}
pub fn parse_declared(input: &[ComponentValue], base_url: &Url)
-> Option<DeclaredValue<SpecifiedValue>> {
match CSSWideKeyword::parse(input) {
Some(Some(keyword)) => Some(CSSWideKeyword(keyword)),
Some(None) => Some(CSSWideKeyword(${
"Inherit" if THIS_STYLE_STRUCT.inherited else "Initial"})),
None => parse_specified(input, base_url),
}
}
}
</%def>

<%def name="longhand(name, no_super=False)">
<%self:raw_longhand name="${name}">
${caller.body()}
Expand Down Expand Up @@ -475,7 +504,7 @@ pub mod longhands {
${predefined_type("background-color", "CSSColor",
"RGBA(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}

<%self:single_component_value name="background-image">
<%self:url_longhand name="background-image">
// The computed value is the same as the specified value.
pub use to_computed_value = super::computed_as_specified;
pub mod computed_value {
Expand All @@ -486,16 +515,29 @@ pub mod longhands {
#[inline] pub fn get_initial_value() -> SpecifiedValue {
None
}
pub fn from_component_value(component_value: &ComponentValue) -> Option<SpecifiedValue> {
pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option<SpecifiedValue> {
from_iter(input.skip_whitespace(), base_url)
}
pub fn from_iter<'a>(mut iter: SkipWhitespaceIterator<'a>, base_url: &Url) -> Option<SpecifiedValue> {
match iter.next() {
Some(v) => from_component_value_with_url(v, base_url),
_ => None
}
}
pub fn from_component_value_with_url(component_value: &ComponentValue, base_url: &Url) -> Option<SpecifiedValue> {
match component_value {
&ast::URL(ref url) => {
let image_url = parse_url(url.as_slice(), None);
let image_url = parse_url(url.as_slice(), Some(base_url.clone()));
Some(Some(image_url))
},
_ => None,
}
}
</%self:single_component_value>
pub fn parse_specified(input: &[ComponentValue], base_url: &Url)
-> Option<DeclaredValue<SpecifiedValue>> {
parse(input, base_url).map(super::SpecifiedValue)
}
</%self:url_longhand>


${new_style_struct("Color", is_inherited=True)}
Expand Down Expand Up @@ -805,6 +847,24 @@ pub mod shorthands {
}
</%def>

<%def name="url_shorthand(name, sub_properties)">
<%
shorthand = Shorthand(name, sub_properties.split())
SHORTHANDS_WITH_URL.append(shorthand)
%>
pub mod ${shorthand.ident} {
use super::*;
struct Longhands {
% for sub_property in shorthand.sub_properties:
${sub_property.ident}: Option<${sub_property.ident}::SpecifiedValue>,
% endfor
}
pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option<Longhands> {
${caller.body()}
}
}
</%def>
<%def name="four_sides_shorthand(name, sub_property_pattern, parser_function)">
<%self:shorthand name="${name}" sub_properties="${
' '.join(sub_property_pattern % side
Expand Down Expand Up @@ -833,7 +893,7 @@ pub mod shorthands {
</%def>

// TODO: other background-* properties
<%self:shorthand name="background" sub_properties="background-color background-image">
<%self:url_shorthand name="background" sub_properties="background-color background-image">
let mut color = None;
let mut image = None;
let mut any = false;
Expand All @@ -847,7 +907,7 @@ pub mod shorthands {
}
if image.is_none() {
match background_image::from_component_value(component_value) {
match background_image::from_component_value_with_url(component_value, base_url) {
Some(v) => { image = Some(v); any = true; continue },
None => (),
}
Expand All @@ -856,7 +916,7 @@ pub mod shorthands {
}
if any { Some(Longhands { background_color: color, background_image: image }) }
else { None }
</%self:shorthand>
</%self:url_shorthand>

${four_sides_shorthand("margin", "margin-%s", "margin_top::from_component_value")}
${four_sides_shorthand("padding", "padding-%s", "padding_top::from_component_value")}
Expand Down Expand Up @@ -1014,12 +1074,12 @@ pub struct PropertyDeclarationBlock {
}


pub fn parse_style_attribute(input: &str) -> PropertyDeclarationBlock {
parse_property_declaration_list(tokenize(input))
pub fn parse_style_attribute(input: &str, base_url: &Url) -> PropertyDeclarationBlock {
parse_property_declaration_list(tokenize(input), base_url)
}


pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I) -> PropertyDeclarationBlock {
pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I, base_url: &Url) -> PropertyDeclarationBlock {
let mut important = ~[];
let mut normal = ~[];
for item in ErrorLoggerIterator(parse_declaration_list(input)) {
Expand All @@ -1029,7 +1089,7 @@ pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I) -> PropertyD
Declaration(Declaration{ location: l, name: n, value: v, important: i}) => {
// TODO: only keep the last valid declaration for a given name.
let list = if i { &mut important } else { &mut normal };
match PropertyDeclaration::parse(n, v, list) {
match PropertyDeclaration::parse(n, v, list, base_url) {
UnknownProperty => log_css_error(l, format!(
"Unsupported property: {}:{}", n, v.iter().to_css())),
InvalidValue => log_css_error(l, format!(
Expand Down Expand Up @@ -1077,6 +1137,9 @@ pub enum PropertyDeclaration {
% for property in LONGHANDS:
${property.ident}_declaration(DeclaredValue<longhands::${property.ident}::SpecifiedValue>),
% endfor
% for property in LONGHANDS_WITH_URL:
${property.ident}_declaration(DeclaredValue<longhands::${property.ident}::SpecifiedValue>),
% endfor
}


Expand All @@ -1086,9 +1149,11 @@ enum PropertyDeclarationParseResult {
ValidDeclaration,
}


impl PropertyDeclaration {
pub fn parse(name: &str, value: &[ComponentValue],
result_list: &mut ~[PropertyDeclaration]) -> PropertyDeclarationParseResult {
result_list: &mut ~[PropertyDeclaration],
base_url: &Url) -> PropertyDeclarationParseResult {
// FIXME: local variable to work around Rust #10683
let name_lower = name.to_ascii_lower();
match name_lower.as_slice() {
Expand All @@ -1100,6 +1165,14 @@ impl PropertyDeclaration {
}
)),
% endfor
% for property in LONGHANDS_WITH_URL:
"${property.name}" => result_list.push(${property.ident}_declaration(
match longhands::${property.ident}::parse_declared(value, base_url) {
Some(value) => value,
None => return InvalidValue,
}
)),
% endfor
% for shorthand in SHORTHANDS:
"${shorthand.name}" => match CSSWideKeyword::parse(value) {
Some(Some(keyword)) => {
Expand Down Expand Up @@ -1132,6 +1205,38 @@ impl PropertyDeclaration {
}
},
% endfor
% for shorthand in SHORTHANDS_WITH_URL:
"${shorthand.name}" => match CSSWideKeyword::parse(value) {
Some(Some(keyword)) => {
% for sub_property in shorthand.sub_properties:
result_list.push(${sub_property.ident}_declaration(
CSSWideKeyword(keyword)
));
% endfor
},
Some(None) => {
% for sub_property in shorthand.sub_properties:
result_list.push(${sub_property.ident}_declaration(
CSSWideKeyword(${
"Inherit" if sub_property.style_struct.inherited else "Initial"})
));
% endfor
},
None => match shorthands::${shorthand.ident}::parse(value, base_url) {
Some(result) => {
% for sub_property in shorthand.sub_properties:
result_list.push(${sub_property.ident}_declaration(
match result.${sub_property.ident} {
Some(value) => SpecifiedValue(value),
None => CSSWideKeyword(Initial),
}
));
% endfor
},
None => return InvalidValue,
}
},
% endfor
_ => return UnknownProperty,
}
ValidDeclaration
Expand Down
12 changes: 6 additions & 6 deletions src/components/style/stylesheets.rs
Expand Up @@ -75,7 +75,7 @@ impl Stylesheet {
match rule {
QualifiedRule(rule) => {
next_state = STATE_BODY;
parse_style_rule(rule, &mut rules, &namespaces)
parse_style_rule(rule, &mut rules, &namespaces, &base_url)
},
AtRule(rule) => {
let lower_name = rule.name.to_ascii_lower();
Expand Down Expand Up @@ -112,7 +112,7 @@ impl Stylesheet {
},
_ => {
next_state = STATE_BODY;
parse_nested_at_rule(lower_name, rule, &mut rules, &namespaces)
parse_nested_at_rule(lower_name, rule, &mut rules, &namespaces, &base_url)
},
}
},
Expand All @@ -125,14 +125,14 @@ impl Stylesheet {


pub fn parse_style_rule(rule: QualifiedRule, parent_rules: &mut ~[CSSRule],
namespaces: &NamespaceMap) {
namespaces: &NamespaceMap, base_url: &Url) {
let QualifiedRule{location: location, prelude: prelude, block: block} = rule;
// FIXME: avoid doing this for valid selectors
let serialized = prelude.iter().to_css();
match selectors::parse_selector_list(prelude, namespaces) {
Some(selectors) => parent_rules.push(CSSStyleRule(StyleRule{
selectors: selectors,
declarations: properties::parse_property_declaration_list(block.move_iter())
declarations: properties::parse_property_declaration_list(block.move_iter(), base_url)
})),
None => log_css_error(location, format!(
"Invalid/unsupported selector: {}", serialized)),
Expand All @@ -142,9 +142,9 @@ pub fn parse_style_rule(rule: QualifiedRule, parent_rules: &mut ~[CSSRule],

// lower_name is passed explicitly to avoid computing it twice.
pub fn parse_nested_at_rule(lower_name: &str, rule: AtRule,
parent_rules: &mut ~[CSSRule], namespaces: &NamespaceMap) {
parent_rules: &mut ~[CSSRule], namespaces: &NamespaceMap, base_url: &Url) {
match lower_name {
"media" => parse_media_rule(rule, parent_rules, namespaces),
"media" => parse_media_rule(rule, parent_rules, namespaces, base_url),
_ => log_css_error(rule.location, format!("Unsupported at-rule: @{:s}", lower_name))
}
}
Expand Down

5 comments on commit 7b56e75

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from SimonSapin
at recrack@7b56e75

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging recrack/servo/background-image = 7b56e75 into auto

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recrack/servo/background-image = 7b56e75 merged ok, testing candidate = dedecec

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = dedecec

Please sign in to comment.