mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
html: Handle inline stylesheets. purple.com works now.
This commit is contained in:
parent
f249396712
commit
7917da2f8c
2 changed files with 86 additions and 22 deletions
|
@ -2,28 +2,53 @@
|
||||||
Some little helpers for hooking up the HTML parser with the CSS parser
|
Some little helpers for hooking up the HTML parser with the CSS parser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::net::url::Url;
|
|
||||||
use std::cell::Cell;
|
|
||||||
use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
||||||
|
|
||||||
|
use core::str;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::util::DataStream;
|
use newcss::util::DataStream;
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::net::url::Url;
|
||||||
|
use std::net::url;
|
||||||
|
|
||||||
pub fn spawn_css_parser(url: Url, resource_task: ResourceTask) -> comm::Port<Stylesheet> {
|
/// Where a style sheet comes from.
|
||||||
|
enum StylesheetProvenance {
|
||||||
|
UrlProvenance(Url),
|
||||||
|
InlineProvenance(Url, ~str),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_css_parser(provenance: StylesheetProvenance,
|
||||||
|
resource_task: ResourceTask) -> comm::Port<Stylesheet> {
|
||||||
let result_port = comm::Port();
|
let result_port = comm::Port();
|
||||||
let result_chan = comm::Chan(&result_port);
|
let result_chan = comm::Chan(&result_port);
|
||||||
do task::spawn |move url, copy resource_task| {
|
|
||||||
|
let provenance_cell = Cell(move provenance);
|
||||||
let sheet = Stylesheet::new(copy url, data_stream(copy url, resource_task));
|
do task::spawn |move provenance_cell, copy resource_task| {
|
||||||
|
let url = do provenance_cell.with_ref |p| {
|
||||||
|
match *p {
|
||||||
|
UrlProvenance(copy the_url) => move the_url,
|
||||||
|
InlineProvenance(copy the_url, _) => move the_url
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let sheet = Stylesheet::new(move url, data_stream(provenance_cell.take(), resource_task));
|
||||||
result_chan.send(move sheet);
|
result_chan.send(move sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result_port;
|
return result_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_stream(url: Url, resource_task: ResourceTask) -> DataStream {
|
fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) -> DataStream {
|
||||||
let input_port = Port();
|
match move provenance {
|
||||||
resource_task.send(Load(move url, input_port.chan()));
|
UrlProvenance(move url) => {
|
||||||
resource_port_to_data_stream(input_port)
|
let input_port = Port();
|
||||||
|
resource_task.send(Load(move url, input_port.chan()));
|
||||||
|
resource_port_to_data_stream(input_port)
|
||||||
|
}
|
||||||
|
InlineProvenance(_, move data) => {
|
||||||
|
data_to_data_stream(move data)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resource_port_to_data_stream(input_port: comm::Port<ProgressMsg>) -> DataStream {
|
fn resource_port_to_data_stream(input_port: comm::Port<ProgressMsg>) -> DataStream {
|
||||||
|
@ -34,3 +59,16 @@ fn resource_port_to_data_stream(input_port: comm::Port<ProgressMsg>) -> DataStre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn data_to_data_stream(data: ~str) -> DataStream {
|
||||||
|
let data_cell = Cell(move data);
|
||||||
|
return |move data_cell| {
|
||||||
|
if data_cell.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
// FIXME: Blech, a copy.
|
||||||
|
Some(str::to_bytes(data_cell.take()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use content::content_task::ContentTask;
|
use content::content_task::ContentTask;
|
||||||
use newcss::stylesheet::Stylesheet;
|
|
||||||
use dom::cow;
|
use dom::cow;
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use dom::event::{Event, ReflowEvent};
|
use dom::event::{Event, ReflowEvent};
|
||||||
use dom::node::{Comment, Doctype, DoctypeData, Text,
|
use dom::node::{Comment, Doctype, DoctypeData, Element, Node, NodeScope, Text};
|
||||||
Element, Node, NodeScope};
|
|
||||||
use resource::image_cache_task::ImageCacheTask;
|
use resource::image_cache_task::ImageCacheTask;
|
||||||
use resource::image_cache_task;
|
use resource::image_cache_task;
|
||||||
use resource::resource_task::{Done, Load, Payload, ResourceTask};
|
use resource::resource_task::{Done, Load, Payload, ResourceTask};
|
||||||
|
|
||||||
|
use core::comm::{Chan, Port};
|
||||||
|
use cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
||||||
use hubbub::Attribute;
|
use hubbub::Attribute;
|
||||||
|
use newcss::stylesheet::Stylesheet;
|
||||||
use comm::{Chan, Port};
|
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use cssparse::spawn_css_parser;
|
use std::net::url;
|
||||||
|
|
||||||
type JSResult = ~[~[u8]];
|
type JSResult = ~[~[u8]];
|
||||||
|
|
||||||
enum CSSMessage {
|
enum CSSMessage {
|
||||||
CSSTaskNewFile(Url),
|
CSSTaskNewFile(StylesheetProvenance),
|
||||||
CSSTaskExit
|
CSSTaskExit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,14 +48,15 @@ spawned, collates them, and sends them to the given result channel.
|
||||||
* `from_parent` - A port on which to receive new links.
|
* `from_parent` - A port on which to receive new links.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
fn css_link_listener(to_parent : comm::Chan<Option<Stylesheet>>, from_parent : comm::Port<CSSMessage>,
|
fn css_link_listener(to_parent : comm::Chan<Option<Stylesheet>>,
|
||||||
|
from_parent : comm::Port<CSSMessage>,
|
||||||
resource_task: ResourceTask) {
|
resource_task: ResourceTask) {
|
||||||
let mut result_vec = ~[];
|
let mut result_vec = ~[];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match from_parent.recv() {
|
match from_parent.recv() {
|
||||||
CSSTaskNewFile(move url) => {
|
CSSTaskNewFile(move provenance) => {
|
||||||
result_vec.push(spawn_css_parser(move url, copy resource_task));
|
result_vec.push(spawn_css_parser(move provenance, copy resource_task));
|
||||||
}
|
}
|
||||||
CSSTaskExit => {
|
CSSTaskExit => {
|
||||||
break;
|
break;
|
||||||
|
@ -184,6 +184,31 @@ pub fn parse_html(scope: NodeScope,
|
||||||
debug!("created parser");
|
debug!("created parser");
|
||||||
parser.set_document_node(cast::transmute(cow::unwrap(root)));
|
parser.set_document_node(cast::transmute(cow::unwrap(root)));
|
||||||
parser.enable_scripting(true);
|
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 append_hook: @fn(Node, Node) = |parent_node, child_node| {
|
||||||
|
do scope.read(&parent_node) |parent_node_contents| {
|
||||||
|
do scope.read(&child_node) |child_node_contents| {
|
||||||
|
match (parent_node_contents.kind, child_node_contents.kind) {
|
||||||
|
(~Element(ref element), ~Text(ref data)) => {
|
||||||
|
match element.kind {
|
||||||
|
~HTMLStyleElement => {
|
||||||
|
debug!("found inline CSS stylesheet");
|
||||||
|
let url = url::from_str("http://example.com/"); // FIXME
|
||||||
|
let provenance = InlineProvenance(result::unwrap(move url),
|
||||||
|
copy *data);
|
||||||
|
css_chan.send(CSSTaskNewFile(provenance));
|
||||||
|
}
|
||||||
|
_ => {} // Nothing to do.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {} // Nothing to do.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
parser.set_tree_handler(@hubbub::TreeHandler {
|
parser.set_tree_handler(@hubbub::TreeHandler {
|
||||||
create_comment: |data: ~str| {
|
create_comment: |data: ~str| {
|
||||||
debug!("create comment");
|
debug!("create comment");
|
||||||
|
@ -227,8 +252,8 @@ pub fn parse_html(scope: NodeScope,
|
||||||
(Some(move rel), Some(move href)) => {
|
(Some(move rel), Some(move href)) => {
|
||||||
if rel == ~"stylesheet" {
|
if rel == ~"stylesheet" {
|
||||||
debug!("found CSS stylesheet: %s", href);
|
debug!("found CSS stylesheet: %s", href);
|
||||||
css_chan.send(CSSTaskNewFile(make_url(move href,
|
css_chan.send(CSSTaskNewFile(UrlProvenance(make_url(move href,
|
||||||
Some(copy *url))));
|
Some(copy *url)))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -262,6 +287,7 @@ pub fn parse_html(scope: NodeScope,
|
||||||
let p: Node = cow::wrap(cast::transmute(parent));
|
let p: Node = cow::wrap(cast::transmute(parent));
|
||||||
let c: Node = cow::wrap(cast::transmute(child));
|
let c: Node = cow::wrap(cast::transmute(child));
|
||||||
scope.add_child(p, c);
|
scope.add_child(p, c);
|
||||||
|
append_hook(p, c);
|
||||||
}
|
}
|
||||||
child
|
child
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue