use crate::tcss::property::Declaration;
use crate::tcss::selector::SelectorList;
use crate::tcss::value::CssValue;
#[derive(Clone, Debug, PartialEq)]
pub struct VariableDefinition {
pub name: String,
pub value: CssValue,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Rule {
pub selectors: SelectorList,
pub declarations: Vec<Declaration>,
pub variables: Vec<VariableDefinition>,
}
impl Rule {
pub fn new(selectors: SelectorList, declarations: Vec<Declaration>) -> Self {
Self {
selectors,
declarations,
variables: Vec::new(),
}
}
pub fn with_variables(
selectors: SelectorList,
declarations: Vec<Declaration>,
variables: Vec<VariableDefinition>,
) -> Self {
Self {
selectors,
declarations,
variables,
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Stylesheet {
rules: Vec<Rule>,
}
impl Stylesheet {
pub fn new() -> Self {
Self::default()
}
pub fn add_rule(&mut self, rule: Rule) {
self.rules.push(rule);
}
pub fn rules(&self) -> &[Rule] {
&self.rules
}
pub fn len(&self) -> usize {
self.rules.len()
}
pub fn is_empty(&self) -> bool {
self.rules.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tcss::property::PropertyName;
use crate::tcss::selector::{CompoundSelector, Selector};
use crate::tcss::value::CssValue;
fn label_rule() -> Rule {
Rule::new(
SelectorList::new(vec![Selector::simple(CompoundSelector::type_selector(
"Label",
))]),
vec![Declaration::new(
PropertyName::Color,
CssValue::Keyword("red".into()),
)],
)
}
#[test]
fn empty_stylesheet() {
let sheet = Stylesheet::new();
assert!(sheet.is_empty());
assert_eq!(sheet.len(), 0);
assert!(sheet.rules().is_empty());
}
#[test]
fn add_rule() {
let mut sheet = Stylesheet::new();
sheet.add_rule(label_rule());
assert_eq!(sheet.len(), 1);
assert!(!sheet.is_empty());
}
#[test]
fn multiple_rules() {
let mut sheet = Stylesheet::new();
sheet.add_rule(label_rule());
sheet.add_rule(label_rule());
assert_eq!(sheet.len(), 2);
}
#[test]
fn rule_with_multiple_selectors() {
let rule = Rule::new(
SelectorList::new(vec![
Selector::simple(CompoundSelector::type_selector("Label")),
Selector::simple(CompoundSelector::type_selector("Container")),
]),
vec![Declaration::new(
PropertyName::Color,
CssValue::Keyword("blue".into()),
)],
);
assert_eq!(rule.selectors.selectors.len(), 2);
}
#[test]
fn rule_with_multiple_declarations() {
let rule = Rule::new(
SelectorList::new(vec![Selector::simple(CompoundSelector::type_selector(
"Label",
))]),
vec![
Declaration::new(PropertyName::Color, CssValue::Keyword("red".into())),
Declaration::new(PropertyName::Background, CssValue::Keyword("blue".into())),
Declaration::new(PropertyName::TextStyle, CssValue::Keyword("bold".into())),
],
);
assert_eq!(rule.declarations.len(), 3);
}
}