Skip to content

Commit

Permalink
Resolved merge conflict in src/html5/tokenizer/token.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
chamber909 committed Nov 7, 2023
2 parents 4f53661 + fec1688 commit 3c65a9b
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 32 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
#
# Please keep this list sorted alphabetically by last name.

Ahmed Ibrahim <[email protected]>
Joshua Thijssen <[email protected]>
Zach Weaver <[email protected]>
14 changes: 8 additions & 6 deletions src/html5/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,13 +513,12 @@ impl<'chars> Html5Parser<'chars> {
}
Token::StartTag {
name, attributes, ..
} if name == "font" => {
if attributes.contains_key("color")
} if name == "font"
&& (attributes.contains_key("color")
|| attributes.contains_key("face")
|| attributes.contains_key("size")
{
self.process_unexpected_html_tag();
}
|| attributes.contains_key("size")) =>
{
self.process_unexpected_html_tag();
}
Token::EndTag { name, .. } if name == "br" || name == "p" => {
self.process_unexpected_html_tag();
Expand Down Expand Up @@ -3830,6 +3829,9 @@ impl<'chars> Html5Parser<'chars> {

/// Find the correct tokenizer state when we are about to parse a fragment case
fn find_initial_state_for_context(&self, context_node: &Node) -> State {
if !context_node.is_namespace(HTML_NAMESPACE) {
return State::Data;
}
match context_node.name.as_str() {
"title" | "textarea" => State::RCDATA,
"style" | "xmp" | "iframe" | "noembed" | "noframes" => State::RAWTEXT,
Expand Down
126 changes: 112 additions & 14 deletions src/html5/parser/document.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::html5::element_class::ElementClass;
use crate::html5::node::arena::NodeArena;
use crate::html5::node::data::doctype::DocTypeData;
use crate::html5::node::data::{comment::CommentData, text::TextData};
Expand Down Expand Up @@ -629,28 +630,68 @@ impl DocumentHandle {
)))?
.data;

if let NodeData::Element(_) = data {
} else {
return Err(Error::DocumentTask(format!(
"Node ID {} is not an element",
element_id
)));
}

let old_id = if let NodeData::Element(element) = data {
let attributes = &mut element.attributes;
let old_id = attributes.get("id").map(|v| v.to_owned());
attributes.insert("id".into(), value.into());
old_id
} else {
None
return Err(Error::DocumentTask(format!(
"Node ID {} is not an element",
element_id
)));
};

old_id.map(|id| doc.named_id_elements.remove(&id));
doc.named_id_elements.insert(value.to_owned(), element_id);

Ok(())
}

fn insert_class_attribute(&mut self, value: &str, element_id: NodeId) -> Result<()> {
let mut doc = self.get_mut();
let node = doc
.get_node_by_id_mut(element_id)
.ok_or(Error::DocumentTask(format!(
"Node ID {} not found",
element_id
)))?;
if let NodeData::Element(element) = &mut node.data {
element.classes = ElementClass::from_string(value);
} else {
return Err(Error::DocumentTask(format!(
"Node ID {} is not an element",
element_id
)));
}

Ok(())
}

fn insert_generic_attribute(
&mut self,
key: &str,
value: &str,
element_id: NodeId,
) -> Result<()> {
let mut doc = self.get_mut();
let node = doc
.get_node_by_id_mut(element_id)
.ok_or(Error::DocumentTask(format!(
"Node ID {} not found",
element_id
)))?;
if let NodeData::Element(element) = &mut node.data {
element.attributes.insert(key.to_owned(), value.to_owned());
} else {
return Err(Error::DocumentTask(format!(
"Node ID {} is not an element",
element_id
)));
}

Ok(())
}
}

impl TreeBuilder for DocumentHandle {
Expand Down Expand Up @@ -683,11 +724,8 @@ impl TreeBuilder for DocumentHandle {
fn insert_attribute(&mut self, key: &str, value: &str, element_id: NodeId) -> Result<()> {
match key {
"id" => self.insert_id_attribute(value, element_id),
"class" => todo!(),
_ => {
// TODO: generic element insert here
Ok(())
}
"class" => self.insert_class_attribute(value, element_id),
_ => self.insert_generic_attribute(key, value, element_id),
}
}
}
Expand Down Expand Up @@ -1094,4 +1132,64 @@ mod tests {
};
assert_eq!(p_element.attributes.get("id").unwrap(), "myid");
}

#[test]
fn insert_generic_attribute() {
let mut doc = DocumentBuilder::new_document();
let div_id = doc.create_element("div", NodeId::root(), None, HTML_NAMESPACE);
let res = doc.insert_attribute("key", "value", div_id);
assert!(res.is_ok());
let doc_read = doc.get();
let NodeData::Element(element) = &doc_read.get_node_by_id(div_id).unwrap().data else {
panic!()
};
assert_eq!(element.attributes.get("key").unwrap(), "value");
}

#[test]
fn task_queue_insert_generic_attribute() {
let doc = DocumentBuilder::new_document();
let mut task_queue = DocumentTaskQueue::new(&doc);
let div_id = task_queue.create_element("div", NodeId::root(), None, HTML_NAMESPACE);
let _ = task_queue.insert_attribute("key", "value", div_id);
let errors = task_queue.flush();
assert!(errors.is_empty());
let doc_read = doc.get();
let NodeData::Element(element) = &doc_read.get_node_by_id(div_id).unwrap().data else {
panic!()
};
assert_eq!(element.attributes.get("key").unwrap(), "value");
}

#[test]
fn insert_class_attribute() {
let mut doc = DocumentBuilder::new_document();
let div_id = doc.create_element("div", NodeId::root(), None, HTML_NAMESPACE);
let res = doc.insert_attribute("class", "one two three", div_id);
assert!(res.is_ok());
let doc_read = doc.get();
let NodeData::Element(element) = &doc_read.get_node_by_id(div_id).unwrap().data else {
panic!()
};
assert!(element.classes.contains("one"));
assert!(element.classes.contains("two"));
assert!(element.classes.contains("three"));
}

#[test]
fn task_queue_insert_class_attribute() {
let doc = DocumentBuilder::new_document();
let mut task_queue = DocumentTaskQueue::new(&doc);
let div_id = task_queue.create_element("div", NodeId::root(), None, HTML_NAMESPACE);
let _ = task_queue.insert_attribute("class", "one two three", div_id);
let errors = task_queue.flush();
assert!(errors.is_empty());
let doc_read = doc.get();
let NodeData::Element(element) = &doc_read.get_node_by_id(div_id).unwrap().data else {
panic!()
};
assert!(element.classes.contains("one"));
assert!(element.classes.contains("two"));
assert!(element.classes.contains("three"));
}
}
22 changes: 22 additions & 0 deletions src/html5/tokenizer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,21 +221,35 @@ mod tests {
let token = Token::Eof;
assert_eq!(format!("{}", token), "EOF");
}
<<<<<<< HEAD

#[test]
fn test_is_start_tag() {
let token = Token::StartTag {
=======

#[test]
fn test_is_start_tag() {
let token = Token::StartTag{
>>>>>>> fec1688a7f0e533bae30d1111ec4338a17b1ee61
name: "div".to_string(),
is_self_closing: false,
attributes: HashMap::new(),
};
assert!(token.is_start_tag("div"));
assert!(!token.is_start_tag("span"));
}
<<<<<<< HEAD

#[test]
fn test_is_any_start_tag() {
let start_tag = Token::StartTag {
=======

#[test]
fn test_is_any_start_tag() {
let start_tag = Token::StartTag{
>>>>>>> fec1688a7f0e533bae30d1111ec4338a17b1ee61
name: "div".to_string(),
is_self_closing: false,
attributes: HashMap::new(),
Expand All @@ -244,11 +258,19 @@ mod tests {
assert!(start_tag.is_any_start_tag());
assert!(!other_tag.is_any_start_tag());
}
<<<<<<< HEAD

#[test]
fn test_is_text_token() {
let text_token = Token::Text("TestingText".to_string());
let other_token = Token::StartTag {
=======

#[test]
fn test_is_text_token() {
let text_token = Token::Text("TestingText".to_string());
let other_token = Token::StartTag{
>>>>>>> fec1688a7f0e533bae30d1111ec4338a17b1ee61
name: "div".to_string(),
is_self_closing: false,
attributes: HashMap::new(),
Expand Down
42 changes: 31 additions & 11 deletions src/testing/tree_construction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,23 @@ impl Test {
// First, create a (fake) main document that contains only the fragment as node
let main_document = DocumentBuilder::new_document();
let mut main_document = Document::clone(&main_document);
let (element, namespace) = if fragment.starts_with("svg ") {
(
fragment.strip_prefix("svg ").unwrap().to_string(),
SVG_NAMESPACE,
)
} else if fragment.starts_with("math ") {
(
fragment.strip_prefix("math ").unwrap().to_string(),
MATHML_NAMESPACE,
)
} else {
(fragment, HTML_NAMESPACE)
};

// Add context node
let context_node_id = main_document.create_element(
fragment.as_str(),
NodeId::root(),
None,
HTML_NAMESPACE,
);
let context_node_id =
main_document.create_element(element.as_str(), NodeId::root(), None, namespace);
context_node = Some(
main_document
.get()
Expand Down Expand Up @@ -605,12 +614,23 @@ pub fn fixtures(filenames: Option<&[&str]>) -> Result<Vec<FixtureFile>> {
for entry in fs::read_dir(root)? {
let path = entry?.path();

if !use_fixture(filenames, &path) {
continue;
}
if path.is_file() {
if !use_fixture(filenames, &path) {
continue;
}

let file = fixture_from_path(&path)?;
files.push(file);
let file = fixture_from_path(&path)?;
files.push(file);
} else {
for subentry in fs::read_dir(path)? {
let path = subentry?.path();
if !use_fixture(filenames, &path) {
continue;
}
let file = fixture_from_path(&path)?;
files.push(file);
}
}
}

Ok(files)
Expand Down
2 changes: 1 addition & 1 deletion tests/tree_construction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ lazy_static! {
// #[test_case("domjs-unsafe.dat")]
#[test_case("entities01.dat")]
#[test_case("entities02.dat")]
// #[test_case("foreign-fragment.dat")]
#[test_case("foreign-fragment.dat")]
#[test_case("html5test-com.dat")]
#[test_case("inbody01.dat")]
#[test_case("isindex.dat")]
Expand Down

0 comments on commit 3c65a9b

Please sign in to comment.