use rdom_style::ContentContext;
use crate::style::{ComputedStyle, Content, ImportantMask, Rule, RuleOrigin, TuiStyle, Value};
pub(super) struct ElementContext<'a> {
pub vars: &'a std::collections::HashMap<String, String>,
pub attr: &'a dyn Fn(&str) -> Option<String>,
pub counter: &'a dyn Fn(&str) -> i32,
}
impl ContentContext for ElementContext<'_> {
fn var(&self, name: &str) -> Option<String> {
self.vars.get(name).cloned()
}
fn attr(&self, name: &str) -> Option<String> {
(self.attr)(name)
}
fn counter(&self, name: &str) -> i32 {
(self.counter)(name)
}
}
pub(super) fn resolve_content_on(
working: &ComputedStyle,
sorted_by_spec: &[&Rule],
inline: Option<&TuiStyle>,
attr_lookup: &dyn Fn(&str) -> Option<String>,
counter_lookup: &dyn Fn(&str) -> i32,
) -> Option<Option<String>> {
let mut declared: Option<Content> = None;
let mut apply_from = |style: &TuiStyle, important_prop_match: bool| {
if let Some(v) = &style.content {
let is_imp = style.important.contains(ImportantMask::CONTENT);
if is_imp == important_prop_match {
declared = match v {
Value::Specified(c) => Some(c.clone()),
Value::Inherit => declared.clone(),
Value::Initial => Some(Content::None),
};
}
}
};
for r in sorted_by_spec {
if r.origin == RuleOrigin::UserAgent {
apply_from(&r.style, false);
}
}
for r in sorted_by_spec {
if r.origin == RuleOrigin::Author {
apply_from(&r.style, false);
}
}
if let Some(s) = inline {
apply_from(s, false);
}
if let Some(s) = inline {
apply_from(s, true);
}
for r in sorted_by_spec {
if r.origin == RuleOrigin::Author {
apply_from(&r.style, true);
}
}
for r in sorted_by_spec {
if r.origin == RuleOrigin::UserAgent {
apply_from(&r.style, true);
}
}
let ctx = ElementContext {
vars: &working.vars,
attr: attr_lookup,
counter: counter_lookup,
};
declared.map(|c| c.resolve(&ctx))
}