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:
Jack Moffitt 2013-07-19 15:18:45 -06:00
parent 09acdcc4ec
commit 34106d7e45
3 changed files with 45 additions and 22 deletions

View file

@ -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
},