tablo_test/protocol/
sidebar.rs1use super::dom::{Attrs, attr_value, open_tags, strip_text, tags_where};
5
6pub fn nav_badge(html: &str, href: &str) -> Option<String> {
9 let menu = |name: &'static str| {
10 move |_: &str, attrs: &Attrs| attr_value(attrs, "data-sidebar").as_deref() == Some(name)
11 };
12 let (_, _, entry) = tags_where(html, menu("menu-item"))
13 .into_iter()
14 .find(|(_, _, inner)| {
15 open_tags(inner).iter().any(|(tag, attrs, _)| {
16 tag == "a" && attr_value(attrs, "href").as_deref() == Some(href)
17 })
18 })?;
19 let (_, _, badge) = tags_where(&entry, menu("menu-badge")).into_iter().next()?;
20 Some(strip_text(&badge))
21}
22
23pub fn nav_links(html: &str) -> Vec<String> {
25 open_tags(html)
26 .into_iter()
27 .filter(|(tag, attrs, _)| {
28 tag == "a" && attr_value(attrs, "data-sidebar").as_deref() == Some("menu-button")
29 })
30 .filter_map(|(_, attrs, _)| attr_value(&attrs, "href"))
31 .collect()
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct NavGroup {
37 pub label: String,
38 pub links: Vec<String>,
39}
40
41pub fn nav_groups(html: &str) -> Vec<NavGroup> {
43 tags_where(html, |_, attrs| {
44 attr_value(attrs, "data-sidebar").as_deref() == Some("group")
45 })
46 .into_iter()
47 .filter_map(|(_, _, group)| {
48 let (_, _, label) = tags_where(&group, |_, attrs| {
49 attr_value(attrs, "data-sidebar").as_deref() == Some("group-label")
50 })
51 .into_iter()
52 .next()?;
53 Some(NavGroup {
54 label: strip_text(&label),
55 links: nav_links(&group),
56 })
57 })
58 .collect()
59}
60
61pub fn area_back_link(html: &str) -> Option<String> {
63 open_tags(html)
64 .into_iter()
65 .find(|(tag, attrs, _)| tag == "a" && attr_value(attrs, "data-area-back").is_some())
66 .and_then(|(_, attrs, _)| attr_value(&attrs, "href"))
67}
68
69pub fn trail(html: &str) -> Vec<(String, Option<String>)> {
71 let Some((_, _, nav)) = tags_where(html, |tag, attrs| {
72 tag == "nav" && attr_value(attrs, "aria-label").as_deref() == Some("breadcrumb")
73 })
74 .into_iter()
75 .next() else {
76 return Vec::new();
77 };
78 tags_where(&nav, |tag, _| tag == "li")
79 .into_iter()
80 .filter_map(|(_, _, item)| {
81 let text = strip_text(&item);
82 if text.is_empty() {
83 return None;
84 }
85 let href = open_tags(&item)
86 .into_iter()
87 .find(|(tag, _, _)| tag == "a")
88 .and_then(|(_, attrs, _)| attr_value(&attrs, "href"));
89 Some((text, href))
90 })
91 .collect()
92}
93
94pub fn tenant_page_link(html: &str, page: &str) -> Option<String> {
97 open_tags(html)
98 .into_iter()
99 .find(|(tag, attrs, _)| {
100 tag == "a" && attr_value(attrs, "data-tenant-page").as_deref() == Some(page)
101 })
102 .and_then(|(_, attrs, _)| attr_value(&attrs, "href"))
103}