1use std::fmt;
2use std::any::Any;
3use std::rc::Rc;
4use std::slice::{Iter, IterMut};
5use std::cell::{RefCell, Ref, RefMut};
6use std::collections::{HashMap, HashSet};
7use std::error::Error;
8use std::marker::PhantomData;
9
10use wasm_bindgen::prelude::*;
11use wasm_bindgen::JsCast;
12use wasm_bindgen::closure::Closure;
13use web_sys::{Element, Node, NodeList, Document, Text, Window, Event};
14
15use serde_json::Value;
16use serde::{Serialize, Serializer, ser::SerializeSeq, Deserialize, de::DeserializeOwned};
17use serde::de::{Deserializer, Visitor, SeqAccess};
18
19pub use anansi_macros::*;
20
21extern crate self as anansi_aux;
22
23pub mod prelude {
24 pub use serde_json::Value;
25 pub use serde::{Serialize, Deserialize};
26 pub use anansi_macros::{store, Properties, component, function_component, refchild, release};
27 pub use super::{attributes, element, document, Rsx, Sub, Proxy, Comp, Elem, Attribute, CbCmd, Resource, Rendered, RefVec, RefChild, Signal};
28}
29
30pub mod components;
31
32pub type Mounts = &'static [(&'static str, fn(String), fn())];
33
34thread_local! {
35 pub static WINDOW: Window = web_sys::window().expect("should have a window");
36 pub static DOCUMENT: Document = {
37 let window = web_sys::window().expect("should have a window");
38 window.document().expect("window should have a document")
39 };
40 pub static CALLBACKS: RefCell<HashMap<String, CallbackData>> = RefCell::new(HashMap::new());
41 pub static RECALLS: RefCell<HashMap<String, RecallData>> = RefCell::new(HashMap::new());
42 pub static APP_STATE: RefCell<Option<AppState>> = RefCell::new(None);
43 pub static NODE_ID: RefCell<String> = RefCell::new(String::new());
44 pub static IDS: RefCell<Vec<String>> = RefCell::new(vec![]);
45 pub static RID: RefCell<usize> = RefCell::new(0);
46 pub static CTX: RefCell<HashMap<String, Ctx>> = RefCell::new(HashMap::new());
47 pub static REFS: RefCell<HashMap<usize, Vec<usize>>> = RefCell::new(HashMap::new());
48 pub static COMP_RSX: RefCell<HashMap<CompId, Option<Rsx>>> = RefCell::new(HashMap::new());
49 pub static VNODE_MAP: RefCell<HashMap<String, Node>> = RefCell::new(HashMap::new());
50 pub static MOUNTED: RefCell<HashSet<String>> = RefCell::new(HashSet::new());
51 pub static VIRT_NODES: RefCell<HashMap<String, Rsx>> = RefCell::new(HashMap::new());
52 pub static EVENT_CB: RefCell<HashMap<&'static str, Closure<dyn Fn(Event)>>> = RefCell::new(HashMap::new());
53}
54
55#[derive(PartialEq, Eq, Hash, Debug)]
56pub struct CompId {
57 node_id: String,
58 n: usize,
59}
60
61impl CompId {
62 pub fn new(node_id: String, n: usize) -> Self {
63 Self {node_id, n}
64 }
65 pub fn node_id(&self) -> &String {
66 &self.node_id
67 }
68 pub fn n(&self) -> usize {
69 self.n
70 }
71}
72
73#[macro_export]
74macro_rules! document {
75 ($e:expr) => {
76 anansi_aux::DOCUMENT.with($e)
77 }
78}
79
80#[macro_export]
81macro_rules! comp_statics {
82 ($($name:expr,)*) => {
83 pub static STATICS: &[(&'static str, &'static [u8])] = &[
84 $((concat!("/static/styles/", $name, ".css"), include_bytes!(concat!("static", anansi_aux::main_separator!(), "styles", anansi_aux::main_separator!(), $name, ".css"))),)*
85 ];
86 }
87}
88
89#[macro_export]
90#[cfg(not(target_os = "windows"))]
91macro_rules! main_separator {
92 () => {r"/"}
93}
94
95#[macro_export]
96#[cfg(target_os = "windows")]
97macro_rules! main_separator {
98 () => {r"\"}
99}
100
101pub fn box_closure<F: Fn(Event) + 'static>(closure: F) -> Box<dyn Fn(Event)> {
102 Box::new(closure)
103}
104
105pub fn load_style(url: &'static str) {
106 DOCUMENT.with(|document| {
107 if let Ok(links) = document.query_selector_all("link") {
108 for i in 0..links.length() {
109 if let Some(node) = links.get(i) {
110 let link = node.dyn_ref::<Element>().unwrap();
111 if let Some(href) = link.attributes().get_named_item("href") {
112 if href.value() == url {
113 return;
114 }
115 }
116 }
117 }
118 }
119 if let Ok(head) = document.query_selector("head") {
120 if let Some(head) = head {
121 if let Ok(link) = document.create_element("link") {
122 link.set_attribute("rel", "stylesheet").unwrap();
123 link.set_attribute("href", url).unwrap();
124 head.append_child(&link).unwrap();
125 }
126 }
127 }
128 });
129}
130
131#[derive(Debug)]
132pub enum CbCmd {
133 Callback(u8),
134 Text(u8, Result<String, Box<dyn Error>>),
135}
136
137#[derive(Properties, Serialize, Deserialize)]
138pub struct EmptyProp;
139
140#[derive(Debug)]
141pub enum Resource<D> {
142 Pending,
143 Rejected(Box<dyn Error>),
144 Resolved(D),
145}
146
147pub struct Rendered(Vec<Rsx>);
148
149impl Rendered {
150 pub fn new(rsx: Vec<Rsx>) -> Self {
151 Self(rsx)
152 }
153 pub fn resume(_store: &mut AppState, _n: usize) -> Self {
154 Self(vec![])
155 }
156 pub fn rsx(&self) -> &Vec<Rsx> {
157 &self.0
158 }
159}
160
161pub enum Cmd {
162 Update(Rsx, String),
163 Set(HashMap<String, Ctx>),
164}
165
166pub trait RefChild {
167 type Item;
168 fn new(pos: usize, item: Self::Item) -> Self;
169 fn pos(&self) -> usize;
170 fn pos_mut(&mut self) -> &mut usize;
171}
172
173impl<T: Serialize> Serialize for RefVec<T> {
174 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
175 where
176 S: Serializer,
177 {
178 let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
179 for e in &self.0 {
180 seq.serialize_element(&*e.borrow())?;
181 }
182 seq.end()
183 }
184}
185
186struct RefVecVisitor<T> {
187 t: PhantomData<T>,
188}
189
190impl<'de, T: Deserialize<'de> + RefChild> Visitor<'de> for RefVecVisitor<T> {
191 type Value = RefVec<T>;
192
193 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
194 formatter.write_str("struct RefVec")
195 }
196
197 fn visit_seq<V>(self, mut seq: V) -> Result<RefVec<T>, V::Error>
198 where
199 V: SeqAccess<'de>,
200 {
201 let mut new_obj = RefVec::new();
202 while let Some(value) = seq.next_element()? {
203 new_obj.push_ref(value);
204 }
205
206 Ok(new_obj)
207 }
208}
209
210impl<'de, T: Deserialize<'de> + RefChild> Deserialize<'de> for RefVec<T> {
211 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
212 where
213 D: Deserializer<'de>,
214 {
215 deserializer.deserialize_seq(RefVecVisitor {t: PhantomData})
216 }
217}
218
219pub trait Parent {
220 type Item;
221}
222
223#[derive(Debug)]
224pub struct RefVec<T: ?Sized>(Vec<Rc<RefCell<T>>>);
225
226impl<T> Parent for RefVec<T> {
227 type Item = T;
228}
229
230impl<T: ?Sized> RefVec<T> {
231 pub fn new() -> Self {
232 Self(vec![])
233 }
234 pub fn inner(&self) -> &Vec<Rc<RefCell<T>>> {
235 &self.0
236 }
237 pub fn len(&self) -> usize {
238 self.0.len()
239 }
240}
241
242pub trait GetOne {
243 fn get_one(&self, n: usize) -> Rc<dyn Any>;
244}
245
246impl<T: 'static> GetOne for RefVec<T> {
247 fn get_one(&self, n: usize) -> Rc<dyn Any> {
248 self.0[n].clone() as Rc<dyn Any>
249 }
250}
251
252impl<T: RefChild> RefVec<T> {
253 pub fn push(&mut self, t: <T as RefChild>::Item) {
254 self.0.push(Rc::new(RefCell::new(T::new(self.0.len(), t))));
255 }
256 pub fn push_ref(&mut self, t: T) {
257 self.0.push(Rc::new(RefCell::new(t)));
258 }
259 pub fn append(&mut self, t: &mut Vec<<T as RefChild>::Item>) {
260 let v = t.split_off(0);
261 let mut n = self.0.len();
262 for e in v {
263 self.0.push(Rc::new(RefCell::new(T::new(n, e))));
264 n += 1;
265 }
266 }
267 pub fn clear(&mut self) {
268 self.0.clear();
269 }
270 pub fn swap(&mut self, a: usize, b: usize) {
271 {
272 let mut first = self.0[a].borrow_mut();
273 let mut second = self.0[b].borrow_mut();
274 let p = first.pos();
275 *first.pos_mut() = second.pos();
276 *second.pos_mut() = p;
277 }
278 self.0.swap(a, b);
279 }
280 pub fn remove(&mut self, index: usize) -> Rc<RefCell<T>> {
281 let mut rest = self.0.split_off(index + 1);
282 let removed = self.0.pop().unwrap();
283 for c in &mut rest {
284 *c.borrow_mut().pos_mut() -= 1;
285 }
286 self.0.append(&mut rest);
287 removed
288 }
289 pub fn iter(&self) -> RefIter<'_, T> {
290 RefIter {iter: self.0.iter()}
291 }
292 pub fn iter_mut(&mut self) -> RefIterMut<'_, T> {
293 RefIterMut {iter_mut: self.0.iter_mut()}
294 }
295 pub fn with_capacity(capacity: usize) -> Self {
296 Self(Vec::with_capacity(capacity))
297 }
298}
299
300pub struct RefIter<'a, T> {
301 iter: Iter<'a, Rc<RefCell<T>>>,
302}
303
304impl<'a, T> Iterator for RefIter<'a, T> {
305 type Item = Ref<'a, T>;
306 fn next(&mut self) -> Option<Self::Item> {
307 if let Some(r) = self.iter.next() {
308 Some(r.borrow())
309 } else {
310 None
311 }
312 }
313}
314
315pub struct RefIterMut<'a, T> {
316 iter_mut: IterMut<'a, Rc<RefCell<T>>>,
317}
318
319impl<'a, T> Iterator for RefIterMut<'a, T> {
320 type Item = RefMut<'a, T>;
321 fn next(&mut self) -> Option<Self::Item> {
322 if let Some(r) = self.iter_mut.next() {
323 Some(r.borrow_mut())
324 } else {
325 None
326 }
327 }
328}
329
330pub struct Signal<T> {
331 _proxy: SignalProxy,
332 value: T,
333}
334
335impl<T> Parent for Signal<T> {
336 type Item = T;
337}
338
339impl<T: Serialize + DeserializeOwned + 'static + std::fmt::Debug> Signal<T> {
340 pub fn resume(store: &mut AppState, n: usize) -> Self {
341 if let Obj::Js(v) = &store.objs[n] {
342 let t: T = serde_json::from_value(v.clone()).unwrap();
343 let subs = store.subs.pop().expect("problem getting subs");
344 Self {_proxy: SignalProxy::from(subs[0]), value: t}
345 } else {
346 panic!("expected JavaScript value when resuming")
347 }
348 }
349}
350
351impl<T> Signal<T> {
352 pub fn new(t: T) -> Self {
353 Self {_proxy: SignalProxy::new(), value: t}
354 }
355 pub fn value(&mut self) -> &T {
356 self._proxy.set();
357 &self.value
358 }
359 pub fn value_mut(&mut self) -> &mut T {
360 self._proxy._invalid = true;
361 &mut self.value
362 }
363 pub fn get_subs(&self) -> Vec<String> {
364 self._proxy.get_subs()
365 }
366 pub fn into_inner(self) -> T {
367 self.value
368 }
369}
370
371#[derive(Clone)]
372pub struct SignalProxy {
373 pub _learning: bool,
374 pub _invalid: bool,
375 pub _node: u32,
376 pub _dirty: i64,
377 pub _sub: Sub,
378}
379
380impl SignalProxy {
381 pub fn new() -> Self {
382 Self {_learning: false, _invalid: false, _node: 0, _dirty: -1, _sub: (0, 0)}
383 }
384 pub fn from(_sub: (u32, i64)) -> Self {
385 Self {_learning: false, _invalid: false, _node: 0, _dirty: -1, _sub}
386 }
387 pub fn set(&mut self) {
388 if self._learning {
389 self._sub = (self._node, 0);
390 } else {
391 if self._dirty == -1 {
392 self._dirty = 0;
393 }
394 self._dirty |= 1;
395 }
396 }
397 pub fn start_proxy(&mut self) -> Sub {
398 self._learning = true;
399 self._invalid = false;
400 self._dirty = -1;
401 self._sub
402 }
403 pub fn stop_proxy(&mut self, sub: Sub) {
404 self._sub = sub;
405 self._learning = false;
406 }
407 pub fn get_subs(&self) -> Vec<String> {
408 vec![format!("{} {}", self._sub.0, self._sub.1)]
409 }
410}
411
412pub struct Proxy {
413 pub _learning: bool,
414 pub _invalid: bool,
415 pub _node: u32,
416 pub _dirty: i64,
417 pub _subs: Vec<Sub>,
418}
419
420impl Proxy {
421 pub fn new(subs: Vec<Sub>) -> Self {
422 Self {_learning: false, _invalid: false, _node: 0, _dirty: -1, _subs: subs}
423 }
424 pub fn set(&mut self, n: i64) {
425 if self._learning {
426 self._subs.push((self._node, n));
427 } else {
428 if self._dirty == -1 {
429 self._dirty = 0;
430 }
431 self._dirty |= n;
432 }
433 }
434 pub fn start_proxy(&mut self) -> Vec<Sub> {
435 self._learning = true;
436 self._invalid = false;
437 self._dirty = -1;
438 let mut subs = vec![];
439 subs.append(&mut self._subs);
440 subs
441 }
442 pub fn stop_proxy(&mut self, subs: Vec<Sub>) {
443 self._subs = subs;
444 self._learning = false;
445 }
446 pub fn get_subs(&self) -> Vec<String> {
447 let mut v = Vec::with_capacity(self._subs.len());
448 for sub in &self._subs {
449 v.push(format!("{} {}", sub.0, sub.1));
450 }
451 v
452 }
453}
454
455#[derive(Debug, Clone)]
456pub struct Comp {
457 pub children: Vec<Rsx>,
458}
459
460#[derive(Debug, Clone)]
461pub struct Elem {
462 pub name: &'static str,
463 pub attrs: Vec<Attribute>,
464 pub children: Vec<Rsx>,
465 pub el: Option<Element>,
466}
467
468#[derive(Debug, Clone)]
469pub struct Attribute {
470 pub key: String,
471 pub value: String,
472}
473
474#[macro_export]
475macro_rules! attributes {
476 ($(($k:expr, $v:expr)),* $(,)?) => {
477 vec![$(Attribute {key: $k, value: $v},)*]
478 }
479}
480
481impl Elem {
482 fn node(&self) -> Node {
483 self.el.clone().expect("expected element").dyn_into::<Node>().unwrap()
484 }
485 fn to_node(&mut self, document: &Document) -> Node {
486 let el = document.create_element(self.name).unwrap();
487 for attr in &self.attrs {
488 el.set_attribute(&attr.key, &attr.value).unwrap();
489 if attr.key.starts_with("on:") {
490 CALLBACKS.with(|c| {
491 let c = c.borrow();
492 let (v, ids) = attr.value.split_once('[').unwrap();
493 let (ids, _) = ids.rsplit_once(']').unwrap();
494 let cb = c.get(v).unwrap();
495 RID.with(|r| {
496 let mut r = r.borrow_mut();
497 let rs = r.to_string();
498 el.set_attribute("rid", &rs).unwrap();
499 RECALLS.with(|rc| {
500 rc.borrow_mut().insert(rs, RecallData {call: cb.call, ids: ids.to_string()});
501 });
502 *r += 1;
503 });
504 });
505 }
506 }
507 for child in &mut self.children {
508 child.attach_to_element(&el, document);
509 }
510 self.el = Some(el.clone());
511 el.dyn_into::<Node>().unwrap()
512 }
513 fn diff(&mut self, node: &mut Node) {
514 let mut name = node.node_name();
515 if name == "#text" && node.node_value().unwrap() == "" {
516 *node = node.next_sibling().unwrap();
517 name = node.node_name();
518 }
519 if self.name == name {
520 let el = node.dyn_ref::<Element>().unwrap();
521 let attributes = el.attributes();
522 let l = self.attrs.len() as u32;
523 let mut same = true;
524 if l == attributes.length() {
525 for attr in &self.attrs {
526 if let Some(attribute) = attributes.get_named_item(&attr.key) {
527 let val = attribute.value();
528 if val != attr.value {
529 same = false;
530 break;
531 }
532 } else {
533 same = false;
534 break;
535 }
536 }
537 } else if l + 1 == attributes.length() {
538 if attributes.get_named_item("rid").is_some() {
539 for attr in &self.attrs {
540 if let Some(attribute) = attributes.get_named_item(&attr.key) {
541 if attribute.value() != attr.value {
542 same = false;
543 break;
544 }
545 } else {
546 same = false;
547 break;
548 }
549 }
550 } else {
551 same = false;
552 }
553 } else {
554 same = false;
555 }
556 if same {
557 return;
558 }
559 }
560 let parent = node.parent_node().unwrap();
561 DOCUMENT.with(|document| {
562 let new = self.to_node(&document);
563
564 parent.insert_before(&new, Some(&node)).unwrap();
565 *node = new;
566 });
567 }
568 fn vcheck(&mut self, old: &Rsx) -> bool {
569 if let Rsx::Element(el) = old {
570 if self.name == el.name {
571 self.el = el.el.clone();
572 Self::echeck(&el.el.as_ref().unwrap(), &self.attrs, &el.attrs);
573 return true;
574 }
575 }
576 false
577 }
578 fn echeck(node: &Element, attrs: &[Attribute], attrs2: &[Attribute]) {
579 let mut attrs = attrs.iter();
580 let mut attrs2 = attrs2.iter();
581 while let Some(attr) = attrs.next() {
582 if let Some(attr2) = attrs2.next() {
583 if attr.key == attr2.key {
584 if attr.value == attr2.value {
585 continue;
586 }
587 } else {
588 node.remove_attribute(&attr.key).unwrap();
589 }
590 if !check_recall(node, attr) {
591 node.set_attribute(&attr.key, &attr.value).unwrap();
592 }
593 } else {
594 while let Some(attr) = attrs.next() {
595 node.set_attribute(&attr.key, &attr.value).unwrap();
596 }
597 return;
598 }
599 }
600 if let Some(attr2) = attrs2.next() {
601 node.remove_attribute(&attr2.key).unwrap();
602 while let Some(attr) = attrs.next() {
603 node.remove_attribute(&attr.key).unwrap();
604 }
605 }
606 }
607 fn kdiff(&mut self, old: &Elem) {
608 self.el = old.el.clone();
609 Self::echeck(old.el.as_ref().unwrap(), &self.attrs[1..], &old.attrs[1..]);
610 vcheck_both(&mut self.children, &old.children);
611 }
612 fn vdiff(&mut self, old: &Rsx) {
613 if self.vcheck(old) {
614 return;
615 }
616 let parent = old.node().parent_node().unwrap();
617 DOCUMENT.with(|document| {
618 let new = self.to_node(&document);
619
620 parent.replace_child(&new, &old.node()).unwrap();
621 });
622 }
623 fn vlast(&mut self, old: &Rsx) {
624 if self.vcheck(old) {
625 return;
626 }
627 let parent = old.node().parent_node().unwrap();
628 DOCUMENT.with(|document| {
629 let new = self.to_node(&document);
630
631 parent.replace_child(&new, &old.node()).unwrap();
632 });
633 }
634}
635
636fn check_recall(node: &Element, attr: &Attribute) -> bool {
637 let mut b = false;
638 if attr.key.starts_with("on:") {
639 CALLBACKS.with(|c| {
640 let c = c.borrow();
641 let (v, ids) = attr.value.split_once('[').unwrap();
642 let (ids, _) = ids.rsplit_once(']').unwrap();
643 let cb = c.get(v).unwrap();
644 RID.with(|r| {
645 let mut r = r.borrow_mut();
646 let rs = r.to_string();
647 node.set_attribute("rid", &rs).unwrap();
648 RECALLS.with(|rc| {
649 rc.borrow_mut().insert(rs, RecallData {call: cb.call, ids: ids.to_string()});
650 });
651 *r += 1;
652 b = true;
653 });
654 });
655 }
656 b
657}
658
659#[macro_export]
660macro_rules! element {
661 ($n:literal, $a:expr, $c: expr) => {
662 Rsx::Element(Elem {name: $n, attrs: $a, children: $c, el: None})
663 }
664}
665
666#[derive(Debug, Clone)]
667pub struct Txt {
668 text: String,
669 node: Option<Text>,
670}
671
672impl Txt {
673 fn to_node(&mut self, document: &Document) -> Node {
674 let text_node = document.create_text_node(&self.text);
675 self.node = Some(text_node.clone());
676 text_node.dyn_into::<Node>().unwrap()
677 }
678}
679
680#[derive(Debug, Clone)]
681pub struct Keys {
682 parent: Option<Node>,
683 children: Vec<Rsx>,
684}
685
686impl Keys {
687 fn kcheck(&mut self, k: &Self) {
688 self.parent = k.parent.clone();
689 let parent = self.parent.clone().expect("expected parent");
690 let mut children = self.children.iter_mut().map(|c| if let Rsx::Element(e) = c {e} else {unimplemented!()});
691 let mut children2 = k.children.iter().map(|c| if let Rsx::Element(e) = c {e} else {unimplemented!()});
692 let mut c1 = if let Some(c) = children.next() {
693 c
694 } else {
695 while let Some(child) = children2.next() {
696 parent.remove_child(&child.node()).unwrap();
697 }
698 return;
699 };
700 DOCUMENT.with(|doc| {
701 let mut c2 = if let Some(c) = children2.next() {
702 c
703 } else {
704 parent.append_child(&c1.to_node(&doc)).unwrap();
705 while let Some(child) = children.next() {
706 parent.append_child(&child.to_node(&doc)).unwrap();
707 }
708 return;
709 };
710 let mut old: HashMap<String, (&Elem, u32)> = HashMap::new();
711
712 loop {
713 let k2 = &c2.attrs[0].value;
714 if c1.attrs[0].value == c2.attrs[0].value {
715 c1.kdiff(c2);
716 if let Some(c) = children.next() {
717 c1 = c;
718 if let Some(c) = children2.next() {
719 c2 = c;
720 continue;
721 } else {
722 parent.append_child(&c1.to_node(&doc)).unwrap();
723 while let Some(child) = children.next() {
724 parent.append_child(&child.to_node(&doc)).unwrap();
725 }
726 return;
727 }
728 } else {
729 while let Some(child) = children2.next() {
730 parent.remove_child(&child.node()).unwrap();
731 }
732 for (c, _) in old.values() {
733 parent.remove_child(&c.node()).unwrap();
734 }
735 return;
736 }
737 } else {
738 let b;
739 if let Some((child, n)) = old.remove(k2) {
740 c1.kdiff(child);
741 let node = parent.child_nodes().get(n).unwrap();
742 parent.insert_before(&c1.node(), Some(&node)).unwrap();
743 } else {
744 let mut n = 0;
745 for c in k.children.iter().map(|c| c.as_elem()) {
746 let k = &c.attrs[0].value;
747 if &c1.attrs[0].value == k {
748 c1.kdiff(c);
749 old.insert(c1.attrs[0].value.to_string(), (c2, n));
750 let child = c.node();
751 let other = c2.node();
752 parent.replace_child(&child, &other).unwrap();
753 break;
754 }
755 n += 1;
756 }
757 if n == k.children.len() as u32 {
758 parent.replace_child(&c1.to_node(doc), &c2.node()).unwrap();
759 }
760 }
761 if let Some(c) = children.next() {
762 c1 = c;
763 if let Some(c) = children2.next() {
764 c2 = c;
765 b = true;
766 } else {
767 parent.append_child(&c1.to_node(&doc)).unwrap();
768 while let Some(child) = children.next() {
769 parent.append_child(&child.to_node(&doc)).unwrap();
770 }
771 return;
772 }
773 } else {
774 while let Some(child) = children2.next() {
775 if !old.contains_key(&child.attrs[0].value) {
776 parent.remove_child(&child.node()).unwrap();
777 }
778 }
779 return;
780 }
781 if b {
782 continue;
783 }
784 parent.insert_before(&c1.to_node(&doc), Some(&c2.node())).unwrap();
785 if let Some(c) = children.next() {
786 c1 = c;
787 continue;
788 }
789 while let Some(child) = children2.next() {
790 parent.remove_child(&child.node()).unwrap();
791 }
792
793 }
794 }
795 });
796 }
797}
798
799#[derive(Debug, Clone)]
800pub enum Rsx {
801 Component(Comp),
802 Element(Elem),
803 Text(Txt),
804 Keyed(Keys),
805}
806
807impl Rsx {
808 pub fn component() -> Self {
809 Rsx::Component(Comp {children: vec![]})
810 }
811 pub fn as_elem(&self) -> &Elem {
812 if let Rsx::Element(e) = self {
813 e
814 } else {
815 unimplemented!();
816 }
817 }
818 pub fn new_text(text: String) -> Self {
819 Rsx::Text(Txt {text, node: None})
820 }
821 pub fn new_keyed(children: Vec<Rsx>) -> Self {
822 Rsx::Keyed(Keys {parent: None, children})
823 }
824 fn attach_to_element(&mut self, el: &Element, document: &Document) {
825 match self {
826 Self::Element(elem) => {
827 el.append_child(&elem.to_node(document)).unwrap();
828 }
829 Self::Text(text) => {
830 el.append_child(&text.to_node(document)).unwrap();
831 }
832 Self::Component(_) => unimplemented!(),
833 Self::Keyed(keyed) => {
834 for child in &mut keyed.children {
835 el.append_child(&child.to_node(document)).unwrap();
836 }
837 }
838 }
839 }
840 fn edit(&mut self, node: &Node) {
841 DOCUMENT.with(|document| {
842 match self {
843 Self::Element(elem) => {
844 let new = elem.to_node(&document);
845 add_sibling(node, &new);
846 }
847 Self::Text(text) => {
848 let new = text.to_node(&document);
849 add_sibling(node, &new);
850 }
851 Self::Component(_) => unimplemented!(),
852 Self::Keyed(_) => unimplemented!(),
853 }
854 });
855 }
856 fn parent_node(&self) -> Option<Node> {
857 match self {
858 Self::Element(elem) => {
859 elem.el.as_ref().expect("expected element").parent_node()
860 }
861 Self::Text(text) => {
862 if let Some(node) = text.node.clone() {
863 node.parent_node()
864 } else {
865 panic!("expected node for text: {}", text.text)
866 }
867 }
868 Self::Component(_) => unimplemented!(),
869 Self::Keyed(_) => unimplemented!(),
870 }
871 }
872 fn node(&self) -> Node {
873 match self {
874 Self::Element(elem) => {
875 elem.node()
876 }
877 Self::Text(text) => {
878 text.node.clone().expect("expected text node").dyn_into::<Node>().expect("expected node")
879 }
880 Self::Component(_) => unimplemented!(),
881 Self::Keyed(_) => unimplemented!(),
882 }
883 }
884 fn to_node(&mut self, document: &Document) -> Node {
885 match self {
886 Self::Element(elem) => {
887 elem.to_node(document)
888 }
889 Self::Text(text) => {
890 text.to_node(document)
891 }
892 Self::Component(_) => unimplemented!(),
893 Self::Keyed(_) => unimplemented!(),
894 }
895 }
896 fn children(&self) -> Option<&Vec<Self>> {
897 match self {
898 Self::Element(elem) => {
899 if !elem.children.is_empty() {
900 Some(&elem.children)
901 } else {
902 None
903 }
904 }
905 Self::Text(_) => {
906 unimplemented!();
907 }
908 Self::Component(comp) => {
909 Some(&comp.children)
910 }
911 Self::Keyed(keyed) => {
912 Some(&keyed.children)
913 }
914 }
915 }
916}
917
918#[derive(Serialize, Deserialize, Debug)]
919pub enum Ctx {
920 R(String),
921}
922
923pub type Sub = (u32, i64);
924
925pub struct AppState {
926 objs: Vec<Obj>,
927 subs: Vec<Vec<Sub>>,
928}
929
930impl AppState {
931 pub fn objs(&self) -> &Vec<Obj> {
932 &self.objs
933 }
934 pub fn objs_mut(&mut self) -> &mut Vec<Obj> {
935 &mut self.objs
936 }
937 pub fn subs(&self) -> &Vec<Vec<Sub>> {
938 &self.subs
939 }
940 pub fn subs_mut(&mut self) -> &mut Vec<Vec<Sub>> {
941 &mut self.subs
942 }
943}
944
945#[derive(Clone)]
946pub enum Obj {
947 Rs(Rc<RefCell<dyn Any>>),
948 Js(Value),
949}
950
951pub fn html_escape(s: &str) -> String {
952 let mut escaped = String::new();
953 for c in s.chars() {
954 let html = match c {
955 '<' => "<",
956 '>' => ">",
957 '\'' => "'",
958 '"' => """,
959 '&' => "&",
960 _ => {
961 escaped.push(c);
962 continue;
963 }
964 };
965 escaped.push_str(html);
966 }
967 escaped
968}
969
970pub struct RecallData {
971 pub call: fn(),
972 pub ids: String,
973}
974
975pub struct CallbackData {
976 pub new: fn(String),
977 pub call: fn(),
978}
979
980#[macro_export]
981macro_rules! log {
982 ($f:literal $($t:tt)*) => {
983 web_sys::console::log_1(&format!($f $($t)*).into());
984 };
985 ($($t:tt)*) => {
986 web_sys::console::log_1(&$($t)*);
987 };
988}
989
990fn add_sibling(node: &Node, new: &Node) {
991 match node.node_type() {
992 Node::ELEMENT_NODE => node.dyn_ref::<Element>().unwrap().after_with_node_1(new).unwrap(),
993 Node::TEXT_NODE => node.dyn_ref::<Text>().unwrap().after_with_node_1(new).unwrap(),
994 _ => unimplemented!(),
995 }
996}
997
998pub fn get_state(document: &Document, ctx_map: &mut HashMap<String, Ctx>) -> Option<AppState> {
999 let script = document.query_selector_all("script[type='app/json']").unwrap().get(0).unwrap();
1000 let text = script.text_content().unwrap();
1001 let json: Value = serde_json::from_str(&text).unwrap();
1002 let values = json.as_object().unwrap();
1003 let ctx = values.get("ctx").unwrap();
1004 let contexts = ctx.as_object().unwrap();
1005 let mut cmap = HashMap::new();
1006 for (id, n) in contexts {
1007 let c = serde_json::from_value(n.clone()).unwrap();
1008 cmap.insert(id.to_string(), c);
1009 }
1010 let object_array = values.get("objs").unwrap();
1011 let mut objs = vec![];
1012 for object in object_array.as_array().unwrap() {
1013 objs.push(Obj::Js(object.clone()));
1014 }
1015 let sub_array = values.get("subs").unwrap();
1016 let mut subs = vec![];
1017 for arr in sub_array.as_array().unwrap() {
1018 let mut sv = vec![];
1019 for sub in arr.as_array().unwrap() {
1020 let s = sub.as_str().unwrap();
1021 let nums: Vec<&str> = s.split(' ').collect();
1022 sv.push((nums[0].parse().unwrap(), nums[1].parse().unwrap()));
1023 }
1024 subs.push(sv);
1025 }
1026 let parent = script.parent_node().unwrap();
1027 parent.remove_child(&script).unwrap();
1028 *ctx_map = cmap;
1029 Some(AppState {objs, subs})
1030}
1031
1032fn check_vnodes(nodes: &NodeList, vnode_map: &mut HashMap<String, Node>) {
1033 let mut ident;
1034 for i in 0..nodes.length() {
1035 let node = nodes.get(i).unwrap();
1036 if node.node_type() == Node::COMMENT_NODE {
1037 let comment = node.text_content().unwrap();
1038 if comment.starts_with("av ") {
1039 let attrs: Vec<&str> = comment.split(' ').collect();
1040 let mut id = false;
1041 for attr in &attrs[1..] {
1042 let (k, v) = attr.split_once('=').unwrap();
1043 if k == "a:id" {
1044 ident = v.to_string();
1045 vnode_map.insert(ident, node.clone());
1046 id = true;
1047 break;
1048 }
1049 }
1050 if !id {
1051 panic!("expected id for virtual node");
1052 }
1053 }
1054 } else {
1055 check_vnodes(&node.child_nodes(), vnode_map);
1056 }
1057 }
1058}
1059
1060pub fn setup(callbacks: HashMap<String, CallbackData>) {
1061 std::panic::set_hook(Box::new(console_error_panic_hook::hook));
1062 CALLBACKS.with(|c| {
1063 let mut cb = c.borrow_mut();
1064 *cb = callbacks;
1065 });
1066}
1067
1068pub fn rerender(mut rsx: Rsx) {
1069 CTX.with(|contexts| {
1070 let contexts = contexts.borrow();
1071 VNODE_MAP.with(|vnode_map| {
1072 let mut vnode_map = vnode_map.borrow_mut();
1073 NODE_ID.with(|node_id| {
1074 let node_id = node_id.borrow();
1075 let vn_index = match contexts.get(&*node_id).unwrap() {
1076 Ctx::R(s) => s,
1077 };
1078 VIRT_NODES.with(|virt_nodes| {
1079 let mut virt_nodes = virt_nodes.borrow_mut();
1080 if let Some(virt) = virt_nodes.remove(vn_index) {
1081 vupdate(&mut rsx, &virt, false);
1082 } else {
1083 DOCUMENT.with(|document| {
1084 let nodes = document.body().unwrap().child_nodes();
1085 check_vnodes(&nodes, &mut vnode_map);
1086 let mut node = vnode_map.get(vn_index).unwrap().clone().next_sibling().unwrap();
1087 update(&mut rsx, &mut node);
1088 close_vnode(&document, &node);
1089 });
1090 }
1091 virt_nodes.insert(vn_index.to_string(), rsx);
1092 });
1093 });
1094 });
1095 });
1096}
1097
1098#[wasm_bindgen]
1099pub fn recall(rid: &str) -> bool {
1100 let mut b = false;
1101 RECALLS.with(|r| {
1102 let recalls = r.borrow();
1103 if let Some(rc) = recalls.get(rid) {
1104 let r = rc.call;
1105 IDS.with(|id| {
1106 let arr: Vec<String> = rc.ids.split(' ').map(|s| s.to_string()).collect();
1107 *id.borrow_mut() = arr;
1108 });
1109 drop(recalls);
1110 (r)();
1111 b = true;
1112 }
1113 });
1114 b
1115}
1116
1117fn check_mount(node_id: &str) -> bool {
1118 let mut b = true;
1119 CTX.with(|contexts| {
1120 let contexts = contexts.borrow();
1121 MOUNTED.with(|m| {
1122 let mounted = m.borrow();
1123 if let Some(vn_index) = contexts.get(node_id) {
1124 let index = match vn_index {
1125 Ctx::R(s) => s,
1126 };
1127 if mounted.contains(index) {
1128 b = false;
1129 }
1130 }
1131 });
1132 });
1133 b
1134}
1135
1136#[wasm_bindgen]
1137pub fn call(callback: &str, node_id: &str) -> Result<(), JsValue> {
1138 let (name, arr) = callback.split_once('[').unwrap();
1139 let (arr, _) = arr.rsplit_once(']').unwrap();
1140 let arr: Vec<String> = arr.split(' ').map(|s| s.to_string()).collect();
1141
1142 CALLBACKS.with(|c| {
1143 let cbc = {
1144 let mut callbacks = c.borrow_mut();
1145 if let Some(cb) = callbacks.get_mut(name) {
1146 NODE_ID.with(|n| *n.borrow_mut() = node_id.to_string());
1147 IDS.with(|id| {
1148 *id.borrow_mut() = arr;
1149 });
1150
1151 if check_mount(node_id) {
1152 (cb.new)(node_id.to_string());
1153 CTX.with(|contexts| {
1154 let contexts = contexts.borrow();
1155 MOUNTED.with(|m| {
1156 let mut mounted = m.borrow_mut();
1157 if let Some(vn_index) = contexts.get(node_id) {
1158 let index = match vn_index {
1159 Ctx::R(s) => s,
1160 };
1161 mounted.insert(index.to_string());
1162 }
1163 });
1164 });
1165 }
1166 cb.call
1167 } else {
1168 panic!("expected callback");
1169 }
1170 };
1171 cbc();
1172 });
1173
1174 Ok(())
1175}
1176
1177#[derive(Debug)]
1178pub struct ScopeVar {
1179 pub rf: Rc<RefCell<dyn Any>>,
1180 pub index: Option<usize>,
1181}
1182
1183impl ScopeVar {
1184 fn new(rf: Rc<RefCell<dyn Any>>, index: Option<usize>) -> Self {
1185 Self {rf, index}
1186 }
1187}
1188
1189pub fn lexical_scope() -> Vec<ScopeVar> {
1190 let mut v = vec![];
1191 APP_STATE.with(|app| {
1192 let app = app.borrow();
1193 IDS.with(|ids| {
1194 for id in ids.borrow().iter() {
1195 if let Some((f, s)) = id.split_once('-') {
1196 let f: usize = f.parse().expect("problem parsing id for lexical scope");
1197 let s: usize = s.parse().expect("problem parsing index for lexical scope");
1198 if let Obj::Rs(var) = &app.as_ref().expect("could not get app state").objs[f] {
1199 v.push(ScopeVar::new(var.clone(), Some(s)));
1200 } else {
1201 panic!("expected Rust type to be restored");
1202 }
1203 } else {
1204 let id: usize = id.parse().expect("problem parsing id for lexical scope");
1205 if let Obj::Rs(var) = &app.as_ref().expect("could not get app state").objs[id] {
1206 v.push(ScopeVar::new(var.clone(), None));
1207 } else {
1208 panic!("expected Rust type to be restored");
1209 }
1210 }
1211 }
1212 })
1213 });
1214 v
1215}
1216
1217fn add_children(children: &mut Vec<Rsx>, node: &Node) {
1218 DOCUMENT.with(|document| {
1219 for child in children {
1220 node.append_child(&child.to_node(document)).expect("problem appending child");
1221 }
1222 });
1223}
1224
1225fn update(rsx: &mut Rsx, node: &mut Node) {
1226 match rsx {
1227 Rsx::Element(element) => {
1228 element.diff(node);
1229 if let Some(mut first_child) = node.first_child() {
1230 check_siblings(&mut element.children, &mut first_child);
1231 } else if !element.children.is_empty() {
1232 add_children(&mut element.children, node);
1233 }
1234 }
1235 Rsx::Text(text) => {
1236 set_content(node, text);
1237 }
1238 Rsx::Component(comp) => {
1239 check_siblings(&mut comp.children, node);
1240 }
1241 Rsx::Keyed(key) => {
1242 key.parent = node.parent_node();
1243 check_siblings(&mut key.children, node);
1244 }
1245 }
1246}
1247
1248fn vupdate(rsx: &mut Rsx, node: &Rsx, last: bool) {
1249 match rsx {
1250 Rsx::Element(element) => {
1251 if !last {
1252 element.vdiff(node);
1253 } else {
1254 element.vlast(node);
1255 }
1256 vcheck_children(&mut element.children, node);
1257 }
1258 Rsx::Text(text) => {
1259 if let Rsx::Text(t) = node {
1260 text.node = t.node.clone();
1261 if text.text == t.text {
1262 return;
1263 } else {
1264 text.node.as_ref().unwrap().set_data(&text.text);
1265 }
1266 }
1267 vset_content(node, text);
1268 }
1269 Rsx::Component(comp) => {
1270 vcheck_children(&mut comp.children, node);
1271 }
1272 Rsx::Keyed(keyed) => {
1273 if let Rsx::Keyed(k) = node {
1274 keyed.kcheck(k);
1275 } else {
1276 unimplemented!();
1277 }
1278 }
1279 }
1280}
1281
1282fn avcheck(node: &Node) -> bool {
1283 node.node_type() == Node::COMMENT_NODE && node.text_content().unwrap() == "/av"
1284}
1285
1286fn check_siblings(children: &mut Vec<Rsx>, node: &mut Node) {
1287 let mut children = children.iter_mut();
1288 let l = children.len();
1289 let mut n = 0;
1290
1291 loop {
1292 if let Some(mut child) = children.next() {
1293 update(&mut child, node);
1294
1295 if let Some(sib) = node.next_sibling() {
1296 if avcheck(&sib) {
1297 while let Some(c) = children.next() {
1298 c.edit(&node);
1299 *node = node.next_sibling().unwrap();
1300 }
1301 return;
1302 }
1303
1304 if n < l - 1 {
1305 *node = sib;
1306 }
1307 } else {
1308 if n < l - 1 {
1309 child.edit(&node);
1310 while let Some(c) = children.next() {
1311 if let Some(sib) = node.next_sibling() {
1312 *node = sib;
1313 c.edit(&node);
1314 } else {
1315 c.edit(&node);
1316 while let Some(d) = children.next() {
1317 d.edit(&node);
1318 }
1319 return;
1320 }
1321 }
1322 }
1323 return;
1324 };
1325 } else {
1326 if let Some(s) = node.next_sibling() {
1327 let parent = node.parent_node().unwrap();
1328 RECALLS.with(|r| {
1329 let mut recall = r.borrow_mut();
1330 remove_recall(&mut recall, &parent, &s);
1331 while let Some(sib) = node.next_sibling() {
1332 if !avcheck(&sib) {
1333 remove_recall(&mut recall, &parent, &sib);
1334 } else {
1335 return;
1336 }
1337 }
1338 });
1339 }
1340 return;
1341 }
1342 n += 1;
1343 }
1344}
1345
1346fn vcheck_children(children: &mut Vec<Rsx>, node: &Rsx) {
1347 if let Some(node) = node.children() {
1348 vcheck_both(children, node);
1349 } else {
1350 if !children.is_empty() {
1351 add_children(children, &node.node());
1352 }
1353 return;
1354 }
1355}
1356
1357fn vcheck_both(children: &mut Vec<Rsx>, node: &Vec<Rsx>) {
1358 let m = node.len();
1359 let mut node_children = node.iter();
1360 let mut children = children.iter_mut();
1361 let mut n = 0;
1362 let mut node = node_children.next().unwrap();
1363
1364 loop {
1365 if let Some(mut child) = children.next() {
1366 let last = children.len() == 0;
1367 vupdate(&mut child, &node, last);
1368
1369 if n + 1 == m {
1370 if children.len() > 0 {
1371 let mut sib = node.node();
1372 while let Some(c) = children.next() {
1373 let next_sibling = {
1374 c.edit(&sib);
1375 sib.next_sibling().unwrap()
1376 };
1377 sib = next_sibling;
1378 }
1379 }
1380 return;
1381 }
1382 } else {
1383 let parent = node.parent_node().unwrap();
1384 RECALLS.with(|r| {
1385 let mut recall = r.borrow_mut();
1386 remove_recall(&mut recall, &parent, &node.node());
1387 while let Some(sib) = node_children.next() {
1388 remove_recall(&mut recall, &parent, &sib.node());
1389 }
1390 });
1391 return;
1392 }
1393 if let Some(n) = node_children.next() {
1394 node = n;
1395 } else {
1396 break;
1397 }
1398 n += 1;
1399 }
1400}
1401
1402fn remove_recall(recalls: &mut HashMap<String, RecallData>, parent: &Node, child: &Node) {
1403 if child.node_type() == Node::ELEMENT_NODE {
1404 let el = child.dyn_ref::<Element>().unwrap();
1405 let attrs = el.attributes();
1406 if let Some(rid) = attrs.get_named_item("rid") {
1407 recalls.remove(&rid.value());
1408 }
1409 }
1410 parent.remove_child(child).unwrap();
1411}
1412
1413fn replace_recall(recalls: &mut HashMap<String, RecallData>, parent: &Node, child: &Node, new: &Node) {
1414 if child.node_type() == Node::ELEMENT_NODE {
1415 let el = child.dyn_ref::<Element>().unwrap();
1416 let attrs = el.attributes();
1417 if let Some(rid) = attrs.get_named_item("rid") {
1418 recalls.remove(&rid.value());
1419 }
1420 }
1421 parent.replace_child(new, child).unwrap();
1422}
1423
1424fn set_content(node: &mut Node, content: &mut Txt) {
1425 let text = Text::new_with_data(&content.text).unwrap();
1426 let parent = node.parent_node().unwrap();
1427 RECALLS.with(|r| {
1428 let mut recall = r.borrow_mut();
1429 content.node = Some(text.clone());
1430 let text_node = text.dyn_into::<Node>().unwrap();
1431 replace_recall(&mut recall, &parent, node, &text_node);
1432 *node = text_node;
1433 });
1434}
1435
1436fn vset_content(node: &Rsx, content: &mut Txt) {
1437 let text = Text::new_with_data(&content.text).unwrap();
1438 let parent = node.parent_node().unwrap();
1439 RECALLS.with(|r| {
1440 let mut recall = r.borrow_mut();
1441 content.node = Some(text.clone());
1442 let text_node = text.dyn_into::<Node>().unwrap();
1443 replace_recall(&mut recall, &parent, &node.node(), &text_node);
1444 });
1445}
1446
1447fn close_vnode(document: &Document, node: &Node) {
1448 if let Some(n) = node.next_sibling() {
1449 if n.node_type() == Node::COMMENT_NODE && n.text_content().unwrap() != "/av" {
1450 let c = document.create_comment("/av").dyn_into::<Node>().unwrap();
1451 add_sibling(&n, &c);
1452 }
1453 }
1454}