Skip to content

Commit

Permalink
src/node/node_ref.rs: implemented NodeRef::insert_after
Browse files Browse the repository at this point in the history
  • Loading branch information
niklak committed Nov 14, 2024
1 parent 6991bea commit 96db062
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 46 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This allows querying into the `noscript` element.

## Added
- Implemented `Ord` trait for `NodeId`

- Implemented `NodeRef::insert_after` method, which allows to insert a node after the selected node.

## [0.9.1] - 2024-11-10

Expand Down
85 changes: 58 additions & 27 deletions src/dom_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ impl Tree {
}
}

#[deprecated(since="0.9.1", note="please use `insert_before_of` instead")]
#[deprecated(since = "0.9.1", note = "please use `insert_before_of` instead")]
/// Append a sibling node in the tree before the given node.
pub fn append_prev_sibling_of(&self, id: &NodeId, new_sibling_id: &NodeId) {
self.insert_before_of(id, new_sibling_id);
Expand Down Expand Up @@ -448,6 +448,37 @@ impl Tree {
}
}

/// Append a sibling node in the tree after the given node.
pub fn insert_after_of(&self, id: &NodeId, new_sibling_id: &NodeId) {
self.remove_from_parent(new_sibling_id);
let mut nodes = self.nodes.borrow_mut();
let node = match nodes.get_mut(id.value) {
Some(node) => node,
None => return,

Check warning on line 457 in src/dom_tree.rs

View check run for this annotation

Codecov / codecov/patch

src/dom_tree.rs#L457

Added line #L457 was not covered by tests
};

let parent_id = node.parent;
let next_sibling_id = node.next_sibling;

node.next_sibling = Some(*new_sibling_id);

if let Some(new_sibling) = nodes.get_mut(new_sibling_id.value) {
new_sibling.parent = parent_id;
new_sibling.prev_sibling = Some(*id);
new_sibling.next_sibling = next_sibling_id;
};

if let Some(parent) = parent_id.and_then(|id| nodes.get_mut(id.value)) {
if parent.last_child == Some(*id) {
parent.last_child = Some(*new_sibling_id);

Check warning on line 473 in src/dom_tree.rs

View check run for this annotation

Codecov / codecov/patch

src/dom_tree.rs#L473

Added line #L473 was not covered by tests
}
}

Check warning on line 475 in src/dom_tree.rs

View check run for this annotation

Codecov / codecov/patch

src/dom_tree.rs#L475

Added line #L475 was not covered by tests

if let Some(next_sibling) = next_sibling_id.and_then(|id| nodes.get_mut(id.value)) {
next_sibling.prev_sibling = Some(*new_sibling_id);
}
}

/// Changes the parent of children nodes of a node.
pub fn reparent_children_of(&self, id: &NodeId, new_parent_id: Option<NodeId>) {
let mut nodes = self.nodes.borrow_mut();
Expand Down Expand Up @@ -564,33 +595,33 @@ impl Tree {
base_id
}


fn copy_tree_nodes(&self, source_tree: &Tree, id_map: &InnerHashMap<usize, usize>) -> Vec<TreeNode> {
fn copy_tree_nodes(
&self,
source_tree: &Tree,
id_map: &InnerHashMap<usize, usize>,
) -> Vec<TreeNode> {
let mut new_nodes: Vec<TreeNode> = vec![];
let source_nodes = source_tree.nodes.borrow();
let tree_nodes_it = id_map.iter().flat_map(|(old_id, new_id)| {
source_nodes.get(*old_id).map(|sn|
TreeNode {
id: NodeId::new(*new_id),
parent: sn
.parent
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
prev_sibling: sn
.prev_sibling
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
next_sibling: sn
.next_sibling
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
first_child: sn
.first_child
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
last_child: sn
.last_child
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
data: sn.data.clone(),
}
)

source_nodes.get(*old_id).map(|sn| TreeNode {
id: NodeId::new(*new_id),
parent: sn
.parent
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
prev_sibling: sn
.prev_sibling
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
next_sibling: sn
.next_sibling
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
first_child: sn
.first_child
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
last_child: sn
.last_child
.and_then(|old_id| id_map.get(&old_id.value).map(|id| NodeId::new(*id))),
data: sn.data.clone(),
})
});
new_nodes.extend(tree_nodes_it);
new_nodes.sort_by_key(|k| k.id.value);
Expand All @@ -599,9 +630,9 @@ impl Tree {

/// Copies nodes from another tree to the current tree and applies the given function
/// to each copied node. The function is called with the ID of each copied node.
///
///
/// # Arguments
///
///
/// * `other_nodes` - slice of nodes to be copied
/// * `f` - function to be applied to each copied node
pub(crate) fn copy_nodes_with_fn<F>(&self, other_nodes: &[NodeRef], f: F)
Expand Down
18 changes: 10 additions & 8 deletions src/node/node_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,22 @@ impl<'a> NodeRef<'a> {
/// Appends another node by id to the parent node of the selected node.
/// Another node takes place of the selected node.
#[inline]
#[deprecated(since="0.9.1", note="please use `insert_before` instead")]
#[deprecated(since = "0.9.1", note = "please use `insert_before` instead")]
pub fn append_prev_sibling<P: NodeIdProver>(&self, id_provider: P) {
self.insert_before(id_provider);
}
/// Appends another node by id to the parent node of the selected node.
/// Another node takes place of the selected node.
/// Inserts another node by id before the selected node.
/// Another node takes place of the selected node shifting it to right.
#[inline]
pub fn insert_before<P: NodeIdProver>(&self, id_provider: P) {
self.tree
.insert_before_of(&self.id, id_provider.node_id())
self.tree.insert_before_of(&self.id, id_provider.node_id())
}


/// Inserts another node by id after the selected node.
/// Another node takes place of the next sibling of the selected node.
pub fn insert_after<P: NodeIdProver>(&self, id_provider: P) {
self.tree.insert_after_of(&self.id, id_provider.node_id())
}

/// Appends another node by id to the selected node.
#[inline]
Expand Down Expand Up @@ -216,11 +219,10 @@ impl<'a> NodeRef<'a> {
}
}


/// Appends another node and it's siblings to the parent node
/// of the selected node, shifting itself.
#[inline]
#[deprecated(since="0.9.1", note="please use `insert_siblings_before` instead")]
#[deprecated(since = "0.9.1", note = "please use `insert_siblings_before` instead")]
pub fn append_prev_siblings<P: NodeIdProver>(&self, id_provider: P) {
self.insert_siblings_before(id_provider);
}
Expand Down
5 changes: 2 additions & 3 deletions src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,8 @@ impl<'a> Selection<'a> {

let sel_nodes = sel.nodes();
for node in self.nodes() {
node.tree.copy_nodes_with_fn(sel_nodes, |new_node_id| {
node.insert_before(&new_node_id)
});
node.tree
.copy_nodes_with_fn(sel_nodes, |new_node_id| node.insert_before(&new_node_id));
}

self.remove()
Expand Down
41 changes: 38 additions & 3 deletions tests/node-manipulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use wasm_bindgen_test::*;

mod alloc;


#[cfg_attr(not(target_arch = "wasm32"), test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_create_element() {
Expand Down Expand Up @@ -218,8 +217,6 @@ fn test_change_parent_nodes_old() {
assert!(doc.select("#outline > #origin > #inline").exists());
}



#[cfg_attr(not(target_arch = "wasm32"), test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_node_replace_with_by_node_id() {
Expand Down Expand Up @@ -396,3 +393,41 @@ fn test_node_prepend_html() {
.select("#origin > #first + #second + #third + #inline")
.exists());
}


#[cfg_attr(not(target_arch = "wasm32"), test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_node_insert_before() {
let doc = Document::from(REPLACEMENT_CONTENTS);

let sel = doc.select_single("#before-origin");
let node = sel.nodes().first().unwrap();

let new_node = doc.tree.new_element("p");
new_node.set_attr("id", "before-before-origin");

node.insert_before(&new_node);

assert!(doc
.select("#before-before-origin + #before-origin + #origin + #after-origin")
.exists());
}


#[cfg_attr(not(target_arch = "wasm32"), test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_node_insert_after() {
let doc = Document::from(REPLACEMENT_CONTENTS);

let sel = doc.select_single("#before-origin");
let node = sel.nodes().first().unwrap();

let new_node = doc.tree.new_element("p");
new_node.set_attr("id", "also-before-origin");

node.insert_after(&new_node);

assert!(doc
.select("#before-origin + #also-before-origin + #origin + #after-origin")
.exists());
}
11 changes: 7 additions & 4 deletions tests/selection-traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,6 @@ fn test_selection_try_add() {
assert_eq!(children_sel.unwrap().length(), 2);
}


#[cfg_attr(not(target_arch = "wasm32"), test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_select_inside_noscript() {
Expand All @@ -446,8 +445,12 @@ fn test_select_inside_noscript() {
</noscript>
</body>
</html>
"#.into();
"#
.into();

let sel = doc.select("noscript div");
assert_eq!(sel.text(), "Please enable javascript to run this site".into());
}
assert_eq!(
sel.text(),
"Please enable javascript to run this site".into()
);
}

0 comments on commit 96db062

Please sign in to comment.