use std::collections::HashMap;
use super::constants::COLORS;
pub type Specificity = (usize, usize, usize);
#[derive(Debug, Clone, PartialEq)]
pub enum CssRule {
Normal(NormalRule),
Comment(String),
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct NormalRule {
pub selectors: Vec<Selector>,
pub declarations: HashMap<String, Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Selector {
Simple(SimpleSelector),
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct SimpleSelector {
pub id: Option<String>,
pub class: Vec<String>,
pub tag_name: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Keyword(String),
Length(f32, Unit),
Color(Color),
StringLiteral(String),
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Unit {
Cm,
Mm,
In,
Px,
Pt,
Pc,
Em,
Ex,
Ch,
Rem,
Vw,
Vh,
VMin,
VMax,
Percent,
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl Selector {
pub fn specificity(&self) -> Option<Specificity> {
match self {
Selector::Simple(simple) => {
let a = simple.id.iter().count();
let b = simple.class.len();
let c = simple.tag_name.iter().count();
Some((a, b, c))
}
}
}
}
impl From<&str> for Unit {
fn from(value: &str) -> Self {
match value {
"cm" => Unit::Cm,
"mm" => Unit::Mm,
"in" => Unit::In,
"px" => Unit::Px,
"pt" => Unit::Pt,
"pc" => Unit::Pc,
"em" => Unit::Em,
"ex" => Unit::Ex,
"ch" => Unit::Ch,
"rem" => Unit::Rem,
"vw" => Unit::Vw,
"vh" => Unit::Vh,
"vmin" => Unit::VMin,
"vmax" => Unit::VMax,
"%" => Unit::Percent,
_ => Unit::Px,
}
}
}
impl Value {
pub fn to_px(&self) -> f32 {
match *self {
Value::Length(f, _) => f,
_ => 0.0,
}
}
}
impl Color {
pub fn from_hex(hex: &str) -> Self {
let hex = hex.trim_start_matches('#');
let num = i32::from_str_radix(&hex[0..], 16).unwrap();
let r = (num >> 16) as u8;
let g = (num >> 8) as u8;
let b = num as u8;
Self {
r,
g,
b,
a: 255
}
}
pub fn from_keyword(name: &str) -> Self {
let unlocked = COLORS.lock().unwrap();
*unlocked.get(&name.to_lowercase()).unwrap()
}
}