use crate::ast::style::Style;
use crate::css::engine::{AncestorInfo, CssEngine};
use crate::html::ast::HtmlElement;
pub struct StyleResolver<'a> {
engine: &'a CssEngine,
ancestors: Vec<AncestorInfo>,
}
impl<'a> StyleResolver<'a> {
pub fn new(engine: &'a CssEngine) -> Self {
Self {
engine,
ancestors: Vec::new(),
}
}
pub fn resolve(&self, elem: &HtmlElement, parent_style: &Style) -> Style {
let tag = elem.tag.as_str();
let classes = elem.classes();
let id = elem.id();
let mut style = self
.engine
.resolve_style(tag, &classes, id, &self.ancestors, parent_style);
if let Some(inline_css) = elem.inline_style() {
self.engine.apply_inline_style(&mut style, inline_css);
}
style
}
pub fn resolve_text(&self, parent_style: &Style) -> Style {
self.engine
.resolve_style("span", &[], None, &self.ancestors, parent_style)
}
pub fn with_ancestor<F, R>(&mut self, elem: &HtmlElement, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
let tag = elem.tag.as_str();
let classes = elem.classes();
let id = elem.id();
self.ancestors.push(AncestorInfo {
tag: tag.to_string(),
classes,
id: id.map(|s| s.to_string()),
});
let result = f(self);
self.ancestors.pop();
result
}
pub fn ancestors(&self) -> &[AncestorInfo] {
&self.ancestors
}
pub fn is_hidden(&self, elem: &HtmlElement, parent_style: &Style) -> bool {
self.resolve(elem, parent_style).display == crate::ast::style::Display::None
}
pub fn engine(&self) -> &'a CssEngine {
self.engine
}
}