|
| 1 | +use super::error::RendererError; |
| 2 | +use crate::custom_component_renderer::error::Result; |
| 3 | +use ego_tree::{NodeId, NodeMut, NodeRef, Tree}; |
| 4 | +use markup5ever::namespace_url; |
| 5 | +use markup5ever::{ns, Attribute, LocalName, QualName}; |
| 6 | +use scraper::node::{Element, Text}; |
| 7 | +use scraper::Node; |
| 8 | + |
| 9 | +pub struct NodeManipulator<'a> { |
| 10 | + tree: &'a mut Tree<Node>, |
| 11 | + node_id: NodeId, |
| 12 | + append_children_builder: Option<AppendChildrenBuilder>, |
| 13 | +} |
| 14 | + |
| 15 | +impl<'a> NodeManipulator<'a> { |
| 16 | + pub fn new(tree: &'a mut Tree<Node>, node_id: NodeId) -> NodeManipulator<'a> { |
| 17 | + NodeManipulator { |
| 18 | + tree, |
| 19 | + node_id, |
| 20 | + append_children_builder: None, |
| 21 | + } |
| 22 | + } |
| 23 | + |
| 24 | + fn get_node(&'a self) -> Result<NodeRef<'a, Node>> { |
| 25 | + Ok(self.tree.get(self.node_id).ok_or_else(|| { |
| 26 | + RendererError::InternalError(format!("Node with id {:?} does not exist", self.node_id)) |
| 27 | + })?) |
| 28 | + } |
| 29 | + |
| 30 | + fn get_node_mut(&mut self) -> Result<NodeMut<'_, Node>> { |
| 31 | + Ok(self.tree.get_mut(self.node_id).ok_or_else(|| { |
| 32 | + RendererError::InternalError(format!("Node with id {:?} does not exist", self.node_id)) |
| 33 | + })?) |
| 34 | + } |
| 35 | + |
| 36 | + pub fn get_attribute(&self, attr: &str) -> Result<Option<&str>> { |
| 37 | + let node = self.get_node()?; |
| 38 | + match node.value() { |
| 39 | + Node::Element(element) => { |
| 40 | + let attr = element.attr(attr); |
| 41 | + Ok(attr) |
| 42 | + } |
| 43 | + _ => Err(RendererError::InternalError(format!( |
| 44 | + "Node with id {:?} is not an element", |
| 45 | + self.node_id |
| 46 | + ))), |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + /// Appends a child node and returns the id of the inserted node id. |
| 51 | + pub fn append_child(&'a mut self, new_node: Node) -> Result<Self> { |
| 52 | + let mut node = self.get_node_mut()?; |
| 53 | + let inserted_id = node.append(new_node).id(); |
| 54 | + Ok(Self::new(self.tree, inserted_id)) |
| 55 | + } |
| 56 | + |
| 57 | + pub fn append_children(&mut self) -> &mut AppendChildrenBuilder { |
| 58 | + let builder = AppendChildrenBuilder::new(None); |
| 59 | + self.append_children_builder = Some(builder); |
| 60 | + self.append_children_builder.as_mut().unwrap() |
| 61 | + } |
| 62 | + |
| 63 | + fn build_children_impl(&mut self, builder: AppendChildrenBuilder) -> Result<()> { |
| 64 | + let mut node = self.get_node_mut()?; |
| 65 | + let mut builder_to_nodeid = Vec::new(); |
| 66 | + for mut child in builder.children { |
| 67 | + let inserted_id = node.append(child.value.take().unwrap()).id(); |
| 68 | + builder_to_nodeid.push((child, inserted_id)); |
| 69 | + } |
| 70 | + let original_node_id = self.node_id; |
| 71 | + for (child, inserted_id) in builder_to_nodeid { |
| 72 | + self.node_id = inserted_id; |
| 73 | + self.build_children_impl(child)?; |
| 74 | + } |
| 75 | + self.node_id = original_node_id; |
| 76 | + Ok(()) |
| 77 | + } |
| 78 | + |
| 79 | + pub fn build_children(&'a mut self) -> Result<()> { |
| 80 | + let builder = self.append_children_builder.take().ok_or_else(|| { |
| 81 | + RendererError::InternalError(format!("Missing children builder in build_children call")) |
| 82 | + })?; |
| 83 | + self.build_children_impl(builder) |
| 84 | + } |
| 85 | + |
| 86 | + pub fn replace_with(mut self, new_node: Node) -> Result<Self> { |
| 87 | + let mut node = self.get_node_mut()?; |
| 88 | + let inserted_id = node.insert_after(new_node).id(); |
| 89 | + node.detach(); |
| 90 | + let Self { tree, .. } = self; |
| 91 | + Ok(Self::new(tree, inserted_id)) |
| 92 | + } |
| 93 | +} |
| 94 | + |
| 95 | +pub struct AppendChildrenBuilder { |
| 96 | + children: Vec<AppendChildrenBuilder>, |
| 97 | + value: Option<Node>, |
| 98 | +} |
| 99 | + |
| 100 | +impl AppendChildrenBuilder { |
| 101 | + fn new(value: Option<Node>) -> Self { |
| 102 | + Self { |
| 103 | + value, |
| 104 | + children: Vec::new(), |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + pub fn append_child(&mut self, new_node: Node) -> &mut AppendChildrenBuilder { |
| 109 | + let new_builder = Self::new(Some(new_node)); |
| 110 | + self.children.push(new_builder); |
| 111 | + self.children.last_mut().unwrap() |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +pub struct NodeAttribute { |
| 116 | + pub name: String, |
| 117 | + pub value: String, |
| 118 | +} |
| 119 | + |
| 120 | +impl NodeAttribute { |
| 121 | + pub fn new(name: &str, value: &str) -> Self { |
| 122 | + Self { |
| 123 | + name: String::from(name), |
| 124 | + value: String::from(value), |
| 125 | + } |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +impl From<NodeAttribute> for Attribute { |
| 130 | + fn from(value: NodeAttribute) -> Self { |
| 131 | + Attribute { |
| 132 | + name: QualName::new(None, ns!(), LocalName::from(value.name)), |
| 133 | + value: value.value.into(), |
| 134 | + } |
| 135 | + } |
| 136 | +} |
| 137 | + |
| 138 | +pub fn create_node(name: &str, attributes: Vec<NodeAttribute>) -> Node { |
| 139 | + Node::Element(Element::new( |
| 140 | + QualName::new(None, ns!(), LocalName::from(name)), |
| 141 | + attributes.into_iter().map(Into::into).collect(), |
| 142 | + )) |
| 143 | +} |
| 144 | + |
| 145 | +pub fn create_text_node(text: &str) -> Node { |
| 146 | + Node::Text(Text { text: text.into() }) |
| 147 | +} |
0 commit comments