60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use html5ever::QualName;
|
|
use kuchiki::{traits::*, NodeRef};
|
|
|
|
pub fn rewrite_tags(html: &str, selector: &str, mapping: impl Fn(&NodeRef) -> String) -> String {
|
|
let document = kuchiki::parse_html().one(html);
|
|
|
|
for elem in document
|
|
.select(selector)
|
|
.expect("Failed to select document with given selector")
|
|
.collect::<Vec<_>>()
|
|
{
|
|
let node = elem.as_node();
|
|
let new_contents = kuchiki::parse_fragment(
|
|
elem.name.clone(),
|
|
elem.attributes
|
|
.borrow()
|
|
.map
|
|
.clone()
|
|
.into_iter()
|
|
.map(|(name, value)| html5ever::Attribute {
|
|
name: QualName::new(value.prefix, name.ns, name.local),
|
|
value: value.value.into(),
|
|
})
|
|
.collect(),
|
|
)
|
|
.one(mapping(node))
|
|
.first_child()
|
|
.expect("Root element somehow missing");
|
|
|
|
for child in node.children() {
|
|
child.detach();
|
|
}
|
|
|
|
for child in new_contents.children() {
|
|
node.append(child);
|
|
}
|
|
}
|
|
|
|
let mut out = Vec::new();
|
|
document
|
|
.serialize(&mut out)
|
|
.expect("Failed to serialize document");
|
|
String::from_utf8_lossy(&out).into_owned()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::rewrite_tags;
|
|
|
|
#[test]
|
|
fn remap_block() {
|
|
let html = r#"<p>hello, world! <span class="replace-me">REPLACE ME</span> <span class="replace-me me-too">me too!</span></p>"#;
|
|
let rewritten_html = rewrite_tags(html, ".replace-me", |_| {
|
|
"<strong>it's a me!</strong>".to_string()
|
|
});
|
|
|
|
println!("{}", rewritten_html)
|
|
}
|
|
}
|