use rdom_core::{NodeId, NodeType};
use rdom_css::{Warning, parse, parse_inline};
use rdom_style::Stylesheet;
use crate::{TuiDom, TuiNodeMutExt};
pub fn extend_from_style_tags(dom: &TuiDom, sheet: &mut Stylesheet) -> Vec<Warning> {
let mut warnings = Vec::new();
let style_ids = collect_style_elements(dom);
for id in style_ids {
let css = collect_text_content(dom, id);
let result = parse(&css);
for rule in result.stylesheet.rules() {
let _ = sheet.add_rule(&rule.source_text, rule.style.clone());
}
for (k, v) in result.stylesheet.vars() {
let owned = std::mem::take(sheet);
*sheet = owned.define_var(k, v);
}
warnings.extend(result.warnings);
}
warnings
}
fn collect_style_elements(dom: &TuiDom) -> Vec<NodeId> {
let mut out = Vec::new();
walk(dom, dom.root(), &mut out);
out
}
fn walk(dom: &TuiDom, id: NodeId, out: &mut Vec<NodeId>) {
let node = dom.node(id);
if node.tag_name() == Some("style") {
out.push(id);
return;
}
for child in node.child_nodes() {
walk(dom, child.id(), out);
}
}
fn collect_text_content(dom: &TuiDom, id: NodeId) -> String {
let mut out = String::new();
for child in dom.node(id).child_nodes() {
if child.node_type() == NodeType::Text
&& let Some(s) = child.node_value()
{
out.push_str(s);
}
}
out
}
pub fn seed_inline_styles(dom: &mut TuiDom) -> Vec<Warning> {
let mut warnings = Vec::new();
let candidates = collect_styled_elements(dom);
for id in candidates {
let Some(text) = dom.node(id).get_attribute("style").map(|s| s.to_string()) else {
continue;
};
let result = parse_inline(&text);
warnings.extend(result.warnings);
dom.node_mut(id).set_inline_style(result.style);
}
warnings
}
fn collect_styled_elements(dom: &TuiDom) -> Vec<NodeId> {
let mut out = Vec::new();
walk_styled(dom, dom.root(), &mut out);
out
}
fn walk_styled(dom: &TuiDom, id: NodeId, out: &mut Vec<NodeId>) {
if dom.node(id).has_attribute("style") {
out.push(id);
}
for child in dom.node(id).child_nodes() {
walk_styled(dom, child.id(), out);
}
}