use super::dom::{Row, attr_value, columns, elements, rows, strip_text, tags_where};
pub fn widgets(html: &str) -> Vec<String> {
tags_where(html, |_, attrs| attr_value(attrs, "data-widget").is_some())
.into_iter()
.filter_map(|(_, attrs, _)| attr_value(&attrs, "data-widget"))
.collect()
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StatTile {
pub label: String,
pub value: String,
pub href: Option<String>,
}
pub fn stats(html: &str) -> Vec<StatTile> {
tags_where(html, |_, attrs| {
attrs.iter().any(|(name, _)| name == "data-stat")
})
.into_iter()
.map(|(tag, attrs, inner)| {
let mut paragraphs = elements(&inner, "p")
.into_iter()
.map(|(_, _, p)| strip_text(&p));
StatTile {
label: paragraphs.next().unwrap_or_default(),
value: paragraphs.next().unwrap_or_default(),
href: (tag == "a").then(|| attr_value(&attrs, "href")).flatten(),
}
})
.collect()
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChartData {
pub kind: String,
pub heading: Option<String>,
pub labels: Vec<String>,
pub series: Vec<ChartSeries>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChartSeries {
pub label: String,
pub values: Vec<String>,
}
pub fn charts(html: &str) -> Vec<ChartData> {
tags_where(html, |_, attrs| attr_value(attrs, "data-chart").is_some())
.into_iter()
.map(|(_, attrs, inner)| {
let table = tags_where(&inner, |tag, attrs| {
tag == "table" && attrs.iter().any(|(name, _)| name == "data-chart-data")
})
.into_iter()
.next()
.map(|(_, _, table)| table)
.unwrap_or_default();
let text = |element: &str| -> Vec<String> {
elements(&table, element)
.into_iter()
.map(|(_, _, inner)| strip_text(&inner))
.collect()
};
let head = elements(&table, "thead")
.into_iter()
.next()
.map(|(_, _, head)| head)
.unwrap_or_default();
let series = elements(&table, "tbody")
.into_iter()
.next()
.map(|(_, _, body)| elements(&body, "tr"))
.unwrap_or_default()
.into_iter()
.map(|(_, _, row)| ChartSeries {
label: elements(&row, "th")
.into_iter()
.next()
.map(|(_, _, th)| strip_text(&th))
.unwrap_or_default(),
values: elements(&row, "td")
.into_iter()
.map(|(_, _, td)| strip_text(&td))
.collect(),
})
.collect();
ChartData {
kind: attr_value(&attrs, "data-chart").unwrap_or_default(),
heading: text("caption").into_iter().next(),
labels: elements(&head, "th")
.into_iter()
.map(|(_, _, th)| strip_text(&th))
.collect(),
series,
}
})
.collect()
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RecordTableData {
pub resource: String,
pub heading: String,
pub columns: Vec<String>,
pub rows: Vec<Row>,
pub list: Option<String>,
}
pub fn record_tables(html: &str) -> Vec<RecordTableData> {
tags_where(html, |_, attrs| {
attr_value(attrs, "data-record-table").is_some()
})
.into_iter()
.map(|(_, attrs, inner)| RecordTableData {
resource: attr_value(&attrs, "data-record-table").unwrap_or_default(),
heading: elements(&inner, "h2")
.into_iter()
.next()
.map(|(_, _, h2)| strip_text(&h2))
.unwrap_or_default(),
columns: columns(&inner),
rows: rows(&inner),
list: tags_where(&inner, |tag, attrs| {
tag == "a"
&& attrs
.iter()
.any(|(name, _)| name == "data-record-table-list")
})
.into_iter()
.next()
.and_then(|(_, attrs, _)| attr_value(&attrs, "href")),
})
.collect()
}