Repository: jaytaph/gosub-browser
File: src/html5/parser/document.rs (Rust)

Code before:
    pub fn relocate(&mut self, node_id: NodeId, parent_id: NodeId) {
        self.get_mut().relocate(node_id, parent_id)
    }

    /// Returns true when there is a cyclic reference from the given node_id to the parent_id
    pub fn has_cyclic_reference(&self, node_id: NodeId, parent_id: NodeId) -> bool {
        self.get().has_cyclic_reference(node_id, parent_id)
    }
}

impl TreeBuilder for DocumentHandle {
    /// Creates and attaches a new element node to the document
    fn create_element(
        &mut self,
        name: &str,
        parent_id: NodeId,
        position: Option<usize>,
        namespace: &str,
    ) -> NodeId {
        let new_element = Node::new_element(self, name, HashMap::new(), namespace);
        self.add_node(new_element, parent_id, position)
    }

    /// Creates and attaches a new text node to the document
    fn create_text(&mut self, content: &str, parent_id: NodeId) {
        let new_text = Node::new_text(self, content);
        self.add_node(new_text, parent_id, None);
    }

    /// Creates and attaches a new comment node to the document
    fn create_comment(&mut self, content: &str, parent_id: NodeId) {
        let new_comment = Node::new_comment(self, content);
        self.add_node(new_comment, parent_id, None);
    }

    /// Inserts an attribute to an element node.
    /// If node is not an element or if passing an invalid attribute value, returns an Err()
    fn insert_attribute(&mut self, key: &str, value: &str, element_id: NodeId) -> Result<()> {
        if !self.get().validate_id_attribute_value(value) {
            return Err(Error::DocumentTask(format!(
                "Attribute value '{}' did not pass validation",
                value
            )));
        }

        if let Some(node) = self.get_mut().get_node_by_id_mut(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",

Review comment (suggestion):
In a later PR, we can consolidate lines 634-637 with line 646, so that there's a single `if let` statement.

Code after:
        }

        // an ID must be tied to only one element
        if self.get().named_id_elements.contains_key(value) {
            return Err(Error::DocumentTask(format!(
                "ID '{}' already exists in DOM",
                value
            )));
        }

        let mut doc = self.get_mut();
        let data = &mut doc
            .get_node_by_id_mut(element_id)
            .ok_or(Error::DocumentTask(format!(
                "Node ID {} not found",
                element_id
            )))?
            .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
        };

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

        Ok(())
    }
}

impl TreeBuilder for DocumentHandle {
    /// Creates and attaches a new element node to the document
    fn create_element(
        &mut self,
        name: &str,
        parent_id: NodeId,
        position: Option<usize>,
        namespace: &str,