mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Fix broken inline CSS parsing and add a iterator for children.
If '\r' appears in an inline <style> element, libhubbub splits the text nodes there, creating multiple text children. The inline style logic assumed that each <style> element had only one child. The logic was moved to trigger when the style element is finished parsing completely (including the children), and then the children are concatenated before sending it to the parser.
This commit is contained in:
parent
09acdcc4ec
commit
34106d7e45
3 changed files with 45 additions and 22 deletions
|
@ -46,6 +46,10 @@ pub struct AbstractNode<View> {
|
|||
priv obj: *mut Node<View>,
|
||||
}
|
||||
|
||||
pub struct AbstractNodeChildrenIterator<View> {
|
||||
priv current_node: Option<AbstractNode<View>>,
|
||||
}
|
||||
|
||||
/// An HTML node.
|
||||
///
|
||||
/// `View` describes extra data associated with this node that this task has access to. For
|
||||
|
@ -200,7 +204,7 @@ impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<View> AbstractNode<View> {
|
||||
impl<'self, View> AbstractNode<View> {
|
||||
// Unsafe accessors
|
||||
|
||||
/// Returns the layout data, unsafely cast to whatever type layout wishes. Only layout is
|
||||
|
@ -396,6 +400,22 @@ impl<View> AbstractNode<View> {
|
|||
pub fn debug_str(&self) -> ~str {
|
||||
fmt!("%?", self.type_id())
|
||||
}
|
||||
|
||||
pub fn children(&self) -> AbstractNodeChildrenIterator<View> {
|
||||
AbstractNodeChildrenIterator {
|
||||
current_node: self.first_child(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
|
||||
pub fn next(&mut self) -> Option<AbstractNode<View>> {
|
||||
self.current_node = match self.current_node {
|
||||
None => None,
|
||||
Some(node) => node.next_sibling(),
|
||||
};
|
||||
self.current_node
|
||||
}
|
||||
}
|
||||
|
||||
impl Node<ScriptView> {
|
||||
|
|
|
@ -275,24 +275,7 @@ pub fn parse_html(url: Url,
|
|||
parser.set_document_node(unsafe { root.to_hubbub_node() });
|
||||
parser.enable_scripting(true);
|
||||
|
||||
// Performs various actions necessary after appending has taken place. Currently, this
|
||||
// consists of processing inline stylesheets, but in the future it might perform
|
||||
// prefetching, etc.
|
||||
let css_chan2 = css_chan.clone();
|
||||
let append_hook: ~fn(AbstractNode<ScriptView>, AbstractNode<ScriptView>) = |parent_node, child_node| {
|
||||
if parent_node.is_style_element() && child_node.is_text() {
|
||||
debug!("found inline CSS stylesheet");
|
||||
let url = url::from_str("http://example.com/"); // FIXME
|
||||
let url_cell = Cell::new(url);
|
||||
do child_node.with_imm_text |text_node| {
|
||||
let data = text_node.parent.data.to_str(); // FIXME: Bad copy.
|
||||
let provenance = InlineProvenance(result::unwrap(url_cell.take()), data);
|
||||
css_chan2.send(CSSTaskNewFile(provenance));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone());
|
||||
let (css_chan2, css_chan3, js_chan2) = (css_chan.clone(), css_chan.clone(), js_chan.clone());
|
||||
parser.set_tree_handler(~hubbub::TreeHandler {
|
||||
create_comment: |data: ~str| {
|
||||
debug!("create comment");
|
||||
|
@ -393,15 +376,34 @@ pub fn parse_html(url: Url,
|
|||
Node::as_abstract_node(~Text::new(data)).to_hubbub_node()
|
||||
}
|
||||
},
|
||||
ref_node: |_| {},
|
||||
unref_node: |_| {},
|
||||
ref_node: |_| { debug!("ref node"); },
|
||||
unref_node: |node| {
|
||||
// check for the end of a <style> so we can submit all the text to the parser.
|
||||
unsafe {
|
||||
let node: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(node);
|
||||
if node.is_style_element() {
|
||||
let url = url::from_str("http://example.com/"); // FIXME
|
||||
let url_cell = Cell::new(url);
|
||||
|
||||
let mut data = ~[];
|
||||
for node.children().advance |child| {
|
||||
do child.with_imm_text() |text| {
|
||||
data.push(text.parent.data.to_str()); // FIXME: Bad copy.
|
||||
}
|
||||
}
|
||||
let provenance = InlineProvenance(result::unwrap(url_cell.take()), data.concat());
|
||||
css_chan3.send(CSSTaskNewFile(provenance));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| {
|
||||
unsafe {
|
||||
debug!("append child %x %x", cast::transmute(parent), cast::transmute(child));
|
||||
let parent: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(parent);
|
||||
let child: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(child);
|
||||
parent.add_child(child);
|
||||
append_hook(parent, child);
|
||||
}
|
||||
child
|
||||
},
|
||||
|
|
1
src/test/html/bad-line-ends.html
Normal file
1
src/test/html/bad-line-ends.html
Normal file
|
@ -0,0 +1 @@
|
|||
<html>
<head>
<style>
p {
color: white;
}
p.blue {
background-color: blue;
}
p.red {
background-color: red;
}
</style>
</head>
<body>
<p class="blue">
I am a paragraph. My background color is blue.
</p>
<p class="red">
I am a paragraph. My background color is red.
</p>
</body>
</html>
|
Loading…
Add table
Add a link
Reference in a new issue