pub mod component;
pub mod html;
pub mod renderer;
use crate::event;
use std::collections::HashMap;
use std::collections::HashSet;
pub use renderer::Renderer;
pub enum Node {
Element(Element),
Text(String),
}
pub struct Element {
pub tag_name: String,
pub attributes: Attributes,
pub events: Events,
pub children: Vec<Node>,
pub need_rerendering: bool,
}
pub struct Attributes {
pub attributes: HashMap<String, HashSet<Value>>,
pub delimiters: HashMap<String, String>,
}
#[derive(Clone, Eq, PartialEq, Hash)]
pub enum Value {
Str(String),
Nut(u64),
Int(i64),
}
pub struct Events {
pub handlers: HashMap<String, event::HandlerId>,
}
impl Node {
pub fn element(
tag_name: impl Into<String>,
attributes: Attributes,
events: Events,
children: Vec<Node>,
need_rerendering: bool,
) -> Self {
Node::Element(Element {
tag_name: tag_name.into(),
attributes,
events,
children,
need_rerendering,
})
}
pub fn text(t: impl Into<String>) -> Self {
Node::Text(t.into())
}
}
impl PartialEq for Element {
fn eq(&self, other: &Self) -> bool {
self.attributes == other.attributes && self.tag_name == other.tag_name
}
}
impl Attributes {
pub fn new() -> Self {
let mut attr = Self {
attributes: HashMap::new(),
delimiters: HashMap::new(),
};
attr.delimit("style", ";");
attr.delimit("class", " ");
attr.delimit("id", " ");
attr
}
pub fn add(&mut self, name: impl Into<String>, value: Value) {
let name: String = name.into();
if let Some(attr) = self.attributes.get_mut(&name) {
attr.insert(value);
} else {
let mut attr: HashSet<Value> = HashSet::new();
attr.insert(value);
self.attributes.insert(name, attr);
}
}
pub fn set(&mut self, name: impl Into<String>) {
let name: String = name.into();
if self.attributes.get(&name).is_none() {
self.attributes.insert(name, HashSet::new());
}
}
pub fn delimit(&mut self, name: impl Into<String>, dlm: impl Into<String>) {
self.delimiters.insert(name.into(), dlm.into());
}
}
impl PartialEq for Attributes {
fn eq(&self, other: &Self) -> bool {
self.attributes.iter().fold(true, |r, (k, v)| {
if let Some(a) = other.attributes.get(k) {
r && (a == v)
} else {
false
}
}) && other.attributes.iter().fold(true, |r, (k, v)| {
if let Some(a) = self.attributes.get(k) {
r && (a == v)
} else {
false
}
})
}
}
impl Into<String> for &Value {
fn into(self) -> String {
match self {
Value::Int(v) => v.to_string(),
Value::Nut(v) => v.to_string(),
Value::Str(v) => v.clone(),
}
}
}
impl Events {
pub fn new() -> Self {
Self {
handlers: HashMap::new(),
}
}
pub fn add(&mut self, name: impl Into<String>, handler: impl FnOnce(web_sys::Event) + 'static) {
let handler_id = event::add(handler);
self.handlers.insert(name.into(), handler_id);
}
}