#[macro_use]
extern crate cfg_if;
use std::collections::BTreeMap;
use maplit::*;
use wasm_bindgen::prelude::*;
use web_sys::{Document, Node};
cfg_if! {
if #[cfg(feature = "console_error_panic_hook")] {
extern crate console_error_panic_hook;
use console_error_panic_hook::set_once as set_panic_hook;
}
}
cfg_if! {
if #[cfg(feature = "wee_alloc")] {
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}
}
#[wasm_bindgen]
pub fn run() {
use std::borrow::Borrow;
let document: Document = web_sys::window().unwrap().document().unwrap();
let body = document.borrow().body().unwrap();
let body: &web_sys::Node = body.as_ref();
let element = Element {
ty: "div".to_string(),
inner: Inner::Children(vec![
Element {
ty: "input".to_string(),
props: Properties {
attrs: btreemap! {
"value".to_string() => "foo".to_string(),
"type".to_string() => "text".to_string(),
},
},
..Default::default()
},
Element {
ty: "a".to_string(),
props: Properties {
attrs: btreemap! {
"href".to_string() => "/bar".to_string(),
},
},
..Default::default()
},
Element {
ty: "span".to_string(),
inner: Inner::Text("hello world now".to_string()),
..Default::default()
},
]),
props: Properties {
attrs: btreemap! {
"id".to_string() => "container".to_string(),
},
},
..Default::default()
};
render(element, &body);
}
fn render(element: Element, container: &Node) {
let instance: Instance = element.into();
instance.reconcile(container);
}
#[derive(Default)]
pub struct Element {
ty: String,
props: Properties,
inner: Inner<Element, String>,
}
enum Inner<SELF, TEXT> {
Children(Vec<SELF>),
Text(TEXT),
}
impl<S, T> Default for Inner<S, T> {
fn default() -> Self {
Inner::Children(vec![])
}
}
#[derive(Default)]
struct Properties {
attrs: BTreeMap<String, String>,
}
use web_sys::Element as DomElement;
impl Properties {
fn set(&self, elem: &DomElement) {
for (key, value) in &self.attrs {
elem.set_attribute(key, value).unwrap();
}
}
fn remove(&self, elem: &DomElement) {
for key in self.attrs.keys() {
elem.remove_attribute(key).unwrap();
}
}
}
pub struct Instance {
ty: String,
props: Properties,
dom: web_sys::Element,
inner: Inner<Instance, web_sys::Text>,
}
impl Instance {
fn reconcile(&self, parent_dom: &Node) {
}
}
impl From<Element> for Instance {
fn from(elem: Element) -> Self {
let Element { ty, props, inner } = elem;
let document: Document = web_sys::window().unwrap().document().unwrap();
let dom: web_sys::Element = document.create_element(&ty).unwrap().into();
let dom_node: &Node = dom.as_ref();
props.set(&dom);
let inner = match inner {
Inner::Children(children) => Inner::Children(
children
.into_iter()
.map(|child| {
let instance: Instance = child.into();
dom_node.append_child(instance.dom.as_ref()).unwrap();
instance
})
.collect::<Vec<Instance>>(),
),
Inner::Text(text) => {
let text: web_sys::Text = document.create_text_node(&text);
let text_node: &Node = text.as_ref();
let dom_node: &Node = dom.as_ref();
dom_node.append_child(&text_node).unwrap();
Inner::Text(text)
}
};
Instance {
ty,
props,
dom,
inner,
}
}
}