diff --git a/src/html5/parser/document.rs b/src/html5/parser/document.rs
index 9f8e24cae..41859a062 100755
--- a/src/html5/parser/document.rs
+++ b/src/html5/parser/document.rs
@@ -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};
@@ -629,21 +630,16 @@ 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));
@@ -651,6 +647,51 @@ impl DocumentHandle {
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 {
@@ -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),
}
}
}
@@ -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"));
+ }
}