use super::dom::{Attrs, attr_value, open_tags, strip_text, tags_where};
pub fn nav_badge(html: &str, href: &str) -> Option<String> {
let menu = |name: &'static str| {
move |_: &str, attrs: &Attrs| attr_value(attrs, "data-sidebar").as_deref() == Some(name)
};
let (_, _, entry) = tags_where(html, menu("menu-item"))
.into_iter()
.find(|(_, _, inner)| {
open_tags(inner).iter().any(|(tag, attrs, _)| {
tag == "a" && attr_value(attrs, "href").as_deref() == Some(href)
})
})?;
let (_, _, badge) = tags_where(&entry, menu("menu-badge")).into_iter().next()?;
Some(strip_text(&badge))
}
pub fn nav_links(html: &str) -> Vec<String> {
open_tags(html)
.into_iter()
.filter(|(tag, attrs, _)| {
tag == "a" && attr_value(attrs, "data-sidebar").as_deref() == Some("menu-button")
})
.filter_map(|(_, attrs, _)| attr_value(&attrs, "href"))
.collect()
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NavGroup {
pub label: String,
pub links: Vec<String>,
}
pub fn nav_groups(html: &str) -> Vec<NavGroup> {
tags_where(html, |_, attrs| {
attr_value(attrs, "data-sidebar").as_deref() == Some("group")
})
.into_iter()
.filter_map(|(_, _, group)| {
let (_, _, label) = tags_where(&group, |_, attrs| {
attr_value(attrs, "data-sidebar").as_deref() == Some("group-label")
})
.into_iter()
.next()?;
Some(NavGroup {
label: strip_text(&label),
links: nav_links(&group),
})
})
.collect()
}
pub fn area_back_link(html: &str) -> Option<String> {
open_tags(html)
.into_iter()
.find(|(tag, attrs, _)| tag == "a" && attr_value(attrs, "data-area-back").is_some())
.and_then(|(_, attrs, _)| attr_value(&attrs, "href"))
}
pub fn trail(html: &str) -> Vec<(String, Option<String>)> {
let Some((_, _, nav)) = tags_where(html, |tag, attrs| {
tag == "nav" && attr_value(attrs, "aria-label").as_deref() == Some("breadcrumb")
})
.into_iter()
.next() else {
return Vec::new();
};
tags_where(&nav, |tag, _| tag == "li")
.into_iter()
.filter_map(|(_, _, item)| {
let text = strip_text(&item);
if text.is_empty() {
return None;
}
let href = open_tags(&item)
.into_iter()
.find(|(tag, _, _)| tag == "a")
.and_then(|(_, attrs, _)| attr_value(&attrs, "href"));
Some((text, href))
})
.collect()
}
pub fn tenant_page_link(html: &str, page: &str) -> Option<String> {
open_tags(html)
.into_iter()
.find(|(tag, attrs, _)| {
tag == "a" && attr_value(attrs, "data-tenant-page").as_deref() == Some(page)
})
.and_then(|(_, attrs, _)| attr_value(&attrs, "href"))
}