feat: reactivityl; vdom; rhei; styles; fs; image element
This commit is contained in:
183
src/interpreter/style.rs
Normal file
183
src/interpreter/style.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct StyleSheet {
|
||||
index: HashMap<String, HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl StyleSheet {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn add_rule(&mut self, selector: String, properties: HashMap<String, String>) {
|
||||
self.index
|
||||
.entry(selector.trim().to_string())
|
||||
.or_default()
|
||||
.extend(properties);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn resolve(&self, element_type: &str) -> Option<&HashMap<String, String>> {
|
||||
self.index.get(element_type.trim())
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.index.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct ComputedStyle {
|
||||
pub font_size: Option<f32>,
|
||||
pub color: Option<iced::Color>,
|
||||
pub padding: Option<f32>,
|
||||
pub background: Option<iced::Color>,
|
||||
pub spacing: Option<f32>,
|
||||
pub border_radius: Option<f32>,
|
||||
pub border_width: Option<f32>,
|
||||
pub border_color: Option<iced::Color>,
|
||||
pub width: Option<f32>,
|
||||
pub direction: Option<LayoutDirection>,
|
||||
pub align_items: Option<iced::Alignment>,
|
||||
pub content_align: Option<ContentAlign>,
|
||||
}
|
||||
|
||||
impl ComputedStyle {
|
||||
pub fn compute(
|
||||
inline: &HashMap<String, String>,
|
||||
sheet: Option<&HashMap<String, String>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
font_size: lookup("font-size", inline, sheet).and_then(parse_size),
|
||||
color: lookup("color", inline, sheet).and_then(parse_color),
|
||||
padding: lookup("padding", inline, sheet).and_then(parse_size),
|
||||
background: lookup("background", inline, sheet)
|
||||
.or_else(|| lookup("background-color", inline, sheet))
|
||||
.and_then(parse_color),
|
||||
spacing: lookup("spacing", inline, sheet)
|
||||
.or_else(|| lookup("gap", inline, sheet))
|
||||
.and_then(parse_size),
|
||||
border_radius: lookup("border-radius", inline, sheet).and_then(parse_size),
|
||||
border_width: lookup("border-width", inline, sheet).and_then(parse_size),
|
||||
border_color: lookup("border-color", inline, sheet).and_then(parse_color),
|
||||
width: lookup("width", inline, sheet).and_then(parse_size),
|
||||
|
||||
direction: lookup("direction", inline, sheet).and_then(parse_direction),
|
||||
align_items: lookup("align-items", inline, sheet).and_then(parse_alignment),
|
||||
content_align: lookup("content-align", inline, sheet).and_then(parse_content_align),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lookup<'a>(
|
||||
key: &str,
|
||||
inline: &'a HashMap<String, String>,
|
||||
sheet: Option<&'a HashMap<String, String>>,
|
||||
) -> Option<&'a str> {
|
||||
if let Some(v) = inline.get(key) {
|
||||
return Some(v.as_str());
|
||||
}
|
||||
if let Some(v) = inline.get(&format!("style:{key}")) {
|
||||
return Some(v.as_str());
|
||||
}
|
||||
sheet.and_then(|s| s.get(key)).map(String::as_str)
|
||||
}
|
||||
|
||||
pub fn parse_color(s: &str) -> Option<iced::Color> {
|
||||
let s = s.trim();
|
||||
|
||||
if let Some(hex) = s.strip_prefix('#') {
|
||||
return match hex.len() {
|
||||
3 => {
|
||||
let r = u8::from_str_radix(&hex[0..1].repeat(2), 16).ok()?;
|
||||
let g = u8::from_str_radix(&hex[1..2].repeat(2), 16).ok()?;
|
||||
let b = u8::from_str_radix(&hex[2..3].repeat(2), 16).ok()?;
|
||||
Some(iced::Color::from_rgb(
|
||||
r as f32 / 255.0,
|
||||
g as f32 / 255.0,
|
||||
b as f32 / 255.0,
|
||||
))
|
||||
}
|
||||
6 => {
|
||||
let r = u8::from_str_radix(&hex[0..2], 16).ok()?;
|
||||
let g = u8::from_str_radix(&hex[2..4], 16).ok()?;
|
||||
let b = u8::from_str_radix(&hex[4..6], 16).ok()?;
|
||||
Some(iced::Color::from_rgb(
|
||||
r as f32 / 255.0,
|
||||
g as f32 / 255.0,
|
||||
b as f32 / 255.0,
|
||||
))
|
||||
}
|
||||
8 => {
|
||||
let r = u8::from_str_radix(&hex[0..2], 16).ok()?;
|
||||
let g = u8::from_str_radix(&hex[2..4], 16).ok()?;
|
||||
let b = u8::from_str_radix(&hex[4..6], 16).ok()?;
|
||||
let a = u8::from_str_radix(&hex[6..8], 16).ok()?;
|
||||
Some(iced::Color::from_rgba(
|
||||
r as f32 / 255.0,
|
||||
g as f32 / 255.0,
|
||||
b as f32 / 255.0,
|
||||
a as f32 / 255.0,
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
match s {
|
||||
"white" => Some(iced::Color::WHITE),
|
||||
"black" => Some(iced::Color::BLACK),
|
||||
"transparent" => Some(iced::Color::TRANSPARENT),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum LayoutDirection {
|
||||
Column,
|
||||
Row,
|
||||
Grid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ContentAlign {
|
||||
Start,
|
||||
Center,
|
||||
End,
|
||||
}
|
||||
|
||||
pub fn parse_direction(s: &str) -> Option<LayoutDirection> {
|
||||
match s.trim().to_lowercase().as_str() {
|
||||
"horizontal" | "row" => Some(LayoutDirection::Row),
|
||||
"vertical" | "column" => Some(LayoutDirection::Column),
|
||||
"grid" => Some(LayoutDirection::Grid),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_alignment(s: &str) -> Option<iced::Alignment> {
|
||||
match s.trim().to_lowercase().as_str() {
|
||||
"start" => Some(iced::Alignment::Start),
|
||||
"center" => Some(iced::Alignment::Center),
|
||||
"end" => Some(iced::Alignment::End),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_content_align(s: &str) -> Option<ContentAlign> {
|
||||
match s.trim().to_lowercase().as_str() {
|
||||
"start" | "left" | "top" => Some(ContentAlign::Start),
|
||||
"center" => Some(ContentAlign::Center),
|
||||
"end" | "right" | "bottom" => Some(ContentAlign::End),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_size(s: &str) -> Option<f32> {
|
||||
s.trim()
|
||||
.trim_end_matches(|c: char| c.is_alphabetic() || c == '%')
|
||||
.parse::<f32>()
|
||||
.ok()
|
||||
}
|
||||
Reference in New Issue
Block a user