old.rs 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. mod old {
  2. // #![feature(type_alias_impl_trait)]
  3. //
  4. use std::future::Future;
  5. trait Props {}
  6. struct Context<T: Props> {
  7. _props: std::marker::PhantomData<T>,
  8. }
  9. struct VNode {}
  10. // type FC<T: Props> = fn(&mut Context<T>) -> VNode;
  11. // type FC<T: Props> = fn(&mut Context<T>) -> Box<dyn Future<Output = VNode>>;
  12. impl Props for () {}
  13. // async fn some_component(g: &mut Context<()>) -> VNode {
  14. // rsx! {
  15. // <div>
  16. // </div>
  17. // }
  18. // }
  19. // Absolve ourselves of any type data about the context itself
  20. trait ContextApplier {
  21. fn use_hook<O, H>(
  22. &mut self,
  23. initializer: impl FnOnce() -> H,
  24. runner: impl Fn(&mut H) -> O,
  25. tear_down: impl Fn(&mut H),
  26. ) -> O;
  27. }
  28. impl<T: Props> ContextApplier for Context<T> {
  29. fn use_hook<O, H>(
  30. &mut self,
  31. initializer: impl FnOnce() -> H,
  32. runner: impl Fn(&mut H) -> O,
  33. tear_down: impl Fn(&mut H),
  34. ) -> O {
  35. todo!()
  36. }
  37. }
  38. fn use_state<T>(c: &mut impl ContextApplier, g: impl Fn() -> T) -> T {
  39. c.use_hook(|| {}, |_| {}, |_| {});
  40. g()
  41. }
  42. enum SomeComponent {
  43. Imperative,
  44. Async,
  45. }
  46. // impl<F, G> From<F> for SomeComponent
  47. // where
  48. // F: Fn() -> G,
  49. // G: Future<Output = ()>,
  50. // {
  51. // fn from(_: F) -> Self {
  52. // SomeComponent::Async
  53. // }
  54. // }
  55. // impl From<fn() -> ()> for SomeComponent {
  56. // fn from(_: F) -> Self {
  57. // SomeComponent::Async
  58. // }
  59. // }
  60. // impl<F> Into<SomeComponent> for fn() -> F
  61. // where
  62. // F: Future<Output = ()>,
  63. // {
  64. // fn into(self) -> SomeComponent {
  65. // todo!()
  66. // }
  67. // }
  68. // #[test]
  69. // fn test() {
  70. // let b: SomeComponent = test_comp.into();
  71. // }
  72. // Does this make sense?
  73. // Any component labeled with async can halt its rendering, but won't be able to process updates?
  74. // Or, those updates can still happen virtually, just not propogated into the view?
  75. // async fn test_comp() -> () {
  76. // timer::new(300).await;
  77. // html! {
  78. // <div>
  79. // "hello world!"
  80. // </div>
  81. // }
  82. // }
  83. // fn use_state<T: Props>(c: &mut Context<T>) {}
  84. // async fn another_component(ctx: &mut Context<()>) -> VNode {
  85. // // delay the re-render until component when the future is ready
  86. // // "use_future" loads the promise and provides a value (aka a loadable)
  87. // let value = use_effect(move || async {
  88. // get_value().join(timer::new(300));
  89. // set_value(blah);
  90. // });
  91. // rsx! {
  92. // <Suspense fallback={<div>"Loading..."</div>}>
  93. // <div>
  94. // "hello {name}!"
  95. // </div>
  96. // <Suspense />
  97. // }
  98. // }
  99. /*
  100. Rationale
  101. Today, you can do use_async and do some async operations,
  102. */
  103. // type FC<P: Props> = fn(&mut Context<P>) -> VNode;
  104. // static Example: FC<()> = |_| async {
  105. // // some async work
  106. // };
  107. // type FC2 = fn() -> impl Future<Output = ()>;
  108. // struct fc<P: Props>(fn(&mut Context<P>) -> G);
  109. // fn blah<P: Props, G: Future<Output = VNode>>(a: fn(&mut Context<P>) -> G) {}
  110. // static Example2: FC2<()> = fc(|_| async { VNode {} });
  111. // static Example2: () = blah(|_: &mut Context<()>| async { VNode {} });
  112. // static Example: FC<()> = |_| {
  113. // let g = async { VNode {} };
  114. // Box::new(g)
  115. // };
  116. // static Example2: = || {};
  117. // type FA<R: Future<Output = i32>> = fn(i32) -> R;
  118. // async fn my_component()
  119. // static MyThing: FA<dyn Future<Output = i32>> = |_| async { 10 };
  120. // type SomeFn = fn() -> ();
  121. // static MyFn: SomeFn = || {};
  122. }
  123. mod old2 {
  124. mod vdom {
  125. //! Virtual DOM implementation
  126. use super::*;
  127. pub struct VDom {
  128. patches: Vec<Patch>,
  129. }
  130. impl VDom {
  131. // fn new(root: ComponentFn) -> Self {
  132. // let scope = Scope::new();
  133. // Self {}
  134. // }
  135. }
  136. }
  137. mod nodes {}
  138. mod patch {}
  139. mod scope {
  140. //! Wrappers around components
  141. pub struct Scope {}
  142. impl Scope {
  143. fn new() -> Self {
  144. Self {}
  145. }
  146. }
  147. }
  148. mod context {}
  149. struct EventListener {}
  150. struct VNode {
  151. /// key-value pairs of attributes
  152. attributes: Vec<(&'static str, &'static str)>,
  153. /// onclick/onhover/on etc listeners
  154. /// goal is to standardize around a set of cross-platform listeners?
  155. listeners: Vec<EventListener>,
  156. /// Direct children, non arena-allocated
  157. children: Vec<VNode>,
  158. }
  159. enum ElementType {
  160. div,
  161. p,
  162. a,
  163. img,
  164. }
  165. struct ComponentContext {}
  166. type ComponentFn = fn(ctx: &ComponentContext) -> VNode;
  167. enum Patch {}
  168. mod tests {
  169. use super::*;
  170. /// Ensure components can be made from the raw components
  171. #[test]
  172. fn simple_test() {
  173. fn component(ctx: &ComponentContext) -> VNode {
  174. println!("Running component");
  175. VNode {}
  176. }
  177. let dom = VDom::new(component);
  178. }
  179. /// Ensure components can be made from the raw components
  180. #[test]
  181. fn simple_test_closure() {
  182. let component: ComponentFn = |ctx| {
  183. println!("Running component");
  184. VNode {}
  185. };
  186. let dom = VDom::new(component);
  187. }
  188. }
  189. }
  190. mod text {
  191. //! Old methods that clouded the element implementation
  192. //! These all add a dedicated text renderer implementation
  193. mod vnode {
  194. impl From<&str> for VNode {
  195. fn from(other: &str) -> Self {
  196. VNode::text(other)
  197. }
  198. }
  199. impl From<String> for VNode {
  200. fn from(other: String) -> Self {
  201. VNode::text(other.as_str())
  202. }
  203. }
  204. // -----------------------------------------------
  205. // Allow VNodes to be iterated for map-based UI
  206. // -----------------------------------------------
  207. impl IntoIterator for VNode {
  208. type Item = VNode;
  209. // TODO: Is this possible with an array [VNode] instead of a vec?
  210. type IntoIter = ::std::vec::IntoIter<VNode>;
  211. fn into_iter(self) -> Self::IntoIter {
  212. vec![self].into_iter()
  213. }
  214. }
  215. impl Into<::std::vec::IntoIter<VNode>> for VNode {
  216. fn into(self) -> ::std::vec::IntoIter<VNode> {
  217. self.into_iter()
  218. }
  219. }
  220. // -----------------------------------------------
  221. // Allow debug/display adherent to the HTML spec
  222. // -----------------------------------------------
  223. use std::fmt;
  224. impl fmt::Debug for VNode {
  225. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  226. match self {
  227. VNode::Element(e) => write!(f, "Node::{:?}", e),
  228. VNode::Text(t) => write!(f, "Node::{:?}", t),
  229. VNode::Component(c) => write!(f, "Node::{:?}", c),
  230. }
  231. }
  232. }
  233. // Turn a VNode into an HTML string (delegate impl to variants)
  234. impl fmt::Display for VNode {
  235. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  236. match self {
  237. VNode::Element(element) => write!(f, "{}", element),
  238. VNode::Text(text) => write!(f, "{}", text),
  239. VNode::Component(c) => write!(f, "{}", c),
  240. }
  241. }
  242. }
  243. }
  244. mod velement {
  245. // -----------------------------------------------
  246. // Allow debug/display adherent to the HTML spec
  247. // -----------------------------------------------
  248. use std::fmt;
  249. impl fmt::Debug for VElement {
  250. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  251. write!(
  252. f,
  253. "Element(<{}>, attrs: {:?}, children: {:?})",
  254. self.tag, self.attrs, self.children,
  255. )
  256. }
  257. }
  258. impl fmt::Display for VElement {
  259. // Turn a VElement and all of it's children (recursively) into an HTML string
  260. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  261. write!(f, "<{}", self.tag).unwrap();
  262. for (attr, value) in self.attrs.iter() {
  263. write!(f, r#" {}="{}""#, attr, value)?;
  264. }
  265. write!(f, ">")?;
  266. for child in self.children.iter() {
  267. write!(f, "{}", child.to_string())?;
  268. }
  269. if !crate::validation::is_self_closing(&self.tag) {
  270. write!(f, "</{}>", self.tag)?;
  271. }
  272. Ok(())
  273. }
  274. }
  275. }
  276. mod vtext {
  277. // -----------------------------------------------
  278. // Convert from primitives directly into VText
  279. // -----------------------------------------------
  280. impl From<&str> for VText {
  281. fn from(text: &str) -> Self {
  282. VText {
  283. text: text.to_string(),
  284. }
  285. }
  286. }
  287. impl From<String> for VText {
  288. fn from(text: String) -> Self {
  289. VText { text }
  290. }
  291. }
  292. // -----------------------------------------------
  293. // Allow debug/display adherent to the HTML spec
  294. // -----------------------------------------------
  295. use std::fmt;
  296. impl fmt::Debug for VText {
  297. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  298. write!(f, "Text({})", self.text)
  299. }
  300. }
  301. // Turn a VText into an HTML string
  302. impl fmt::Display for VText {
  303. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  304. write!(f, "{}", self.text)
  305. }
  306. }
  307. }
  308. mod iterables {
  309. // TODO @Jon
  310. // Set this up so instead of the view trait, we can just take functions
  311. // Functions with no context should just be rendered
  312. // But functions with a context should be treated as regular components
  313. // impl<V: View> From<Vec<V>> for IterableNodes {
  314. // fn from(other: Vec<V>) -> Self {
  315. // IterableNodes(other.into_iter().map(|it| it.render()).collect())
  316. // }
  317. // }
  318. // impl<V: View> From<&Vec<V>> for IterableNodes {
  319. // fn from(other: &Vec<V>) -> Self {
  320. // IterableNodes(other.iter().map(|it| it.render()).collect())
  321. // }
  322. // }
  323. // impl<V: View> From<&[V]> for IterableNodes {
  324. // fn from(other: &[V]) -> Self {
  325. // IterableNodes(other.iter().map(|it| it.render()).collect())
  326. // }
  327. // }
  328. impl From<&str> for IterableNodes {
  329. fn from(other: &str) -> Self {
  330. IterableNodes(vec![VNode::text(other)])
  331. }
  332. }
  333. impl From<String> for IterableNodes {
  334. fn from(other: String) -> Self {
  335. IterableNodes(vec![VNode::text(other.as_str())])
  336. }
  337. }
  338. }
  339. mod tests {
  340. #[cfg(test)]
  341. mod tests {
  342. use super::*;
  343. #[test]
  344. fn self_closing_tag_to_string() {
  345. let node = VNode::element("br");
  346. // No </br> since self closing tag
  347. assert_eq!(&node.to_string(), "<br>");
  348. }
  349. #[test]
  350. fn to_string() {
  351. let mut node = VNode::Element(VElement::new("div"));
  352. node.as_velement_mut()
  353. .unwrap()
  354. .attrs
  355. .insert("id".into(), "some-id".into());
  356. let mut child = VNode::Element(VElement::new("span"));
  357. let mut text = VNode::Text(VText::new("Hello world"));
  358. child.as_velement_mut().unwrap().children.push(text);
  359. node.as_velement_mut().unwrap().children.push(child);
  360. let expected = r#"<div id="some-id"><span>Hello world</span></div>"#;
  361. assert_eq!(node.to_string(), expected);
  362. }
  363. }
  364. }
  365. mod ddiff {
  366. /// The diffing algorithm to compare two VNode trees and generate a list of patches to update the VDom.
  367. /// Currently, using an index-based patching algorithm
  368. ///
  369. pub mod diff {
  370. use super::*;
  371. use crate::nodes::{VNode, VText};
  372. use std::cmp::min;
  373. use std::collections::HashMap;
  374. use std::mem;
  375. // pub use apply_patches::patch;
  376. /// A Patch encodes an operation that modifies a real DOM element.
  377. ///
  378. /// To update the real DOM that a user sees you'll want to first diff your
  379. /// old virtual dom and new virtual dom.
  380. ///
  381. /// This diff operation will generate `Vec<Patch>` with zero or more patches that, when
  382. /// applied to your real DOM, will make your real DOM look like your new virtual dom.
  383. ///
  384. /// Each Patch has a u32 node index that helps us identify the real DOM node that it applies to.
  385. ///
  386. /// Our old virtual dom's nodes are indexed depth first, as shown in this illustration
  387. /// (0 being the root node, 1 being it's first child, 2 being it's first child's first child).
  388. ///
  389. /// ```text
  390. /// .─.
  391. /// ( 0 )
  392. /// `┬'
  393. /// ┌────┴──────┐
  394. /// │ │
  395. /// ▼ ▼
  396. /// .─. .─.
  397. /// ( 1 ) ( 4 )
  398. /// `┬' `─'
  399. /// ┌────┴───┐ │
  400. /// │ │ ├─────┬─────┐
  401. /// ▼ ▼ │ │ │
  402. /// .─. .─. ▼ ▼ ▼
  403. /// ( 2 ) ( 3 ) .─. .─. .─.
  404. /// `─' `─' ( 5 ) ( 6 ) ( 7 )
  405. /// `─' `─' `─'
  406. /// ```
  407. ///
  408. /// The patching process is tested in a real browser in crates/virtual-dom-rs/tests/diff_patch.rs
  409. #[derive(PartialEq)]
  410. pub enum Patch<'a> {
  411. /// Append a vector of child nodes to a parent node id.
  412. AppendChildren(NodeIdx, Vec<&'a VNode>),
  413. /// For a `node_i32`, remove all children besides the first `len`
  414. TruncateChildren(NodeIdx, usize),
  415. /// Replace a node with another node. This typically happens when a node's tag changes.
  416. /// ex: <div> becomes <span>
  417. Replace(NodeIdx, &'a VNode),
  418. /// Add attributes that the new node has that the old node does not
  419. AddAttributes(NodeIdx, HashMap<&'a str, &'a str>),
  420. /// Remove attributes that the old node had that the new node doesn't
  421. RemoveAttributes(NodeIdx, Vec<&'a str>),
  422. /// Change the text of a Text node.
  423. ChangeText(NodeIdx, &'a VText),
  424. }
  425. type NodeIdx = usize;
  426. impl<'a> Patch<'a> {
  427. /// Every Patch is meant to be applied to a specific node within the DOM. Get the
  428. /// index of the DOM node that this patch should apply to. DOM nodes are indexed
  429. /// depth first with the root node in the tree having index 0.
  430. pub fn node_idx(&self) -> usize {
  431. match self {
  432. Patch::AppendChildren(node_idx, _) => *node_idx,
  433. Patch::TruncateChildren(node_idx, _) => *node_idx,
  434. Patch::Replace(node_idx, _) => *node_idx,
  435. Patch::AddAttributes(node_idx, _) => *node_idx,
  436. Patch::RemoveAttributes(node_idx, _) => *node_idx,
  437. Patch::ChangeText(node_idx, _) => *node_idx,
  438. }
  439. }
  440. }
  441. /// Given two VNode's generate Patch's that would turn the old virtual node's
  442. /// real DOM node equivalent into the new VNode's real DOM node equivalent.
  443. pub fn diff_vnodes<'a>(old: &'a VNode, new: &'a VNode) -> Vec<Patch<'a>> {
  444. diff_recursive(&old, &new, &mut 0)
  445. }
  446. fn diff_recursive<'a, 'b>(
  447. old: &'a VNode,
  448. new: &'a VNode,
  449. cur_node_idx: &'b mut usize,
  450. ) -> Vec<Patch<'a>> {
  451. let mut patches = vec![];
  452. let mut replace = false;
  453. // Different enum variants, replace!
  454. // VNodes are of different types, and therefore will cause a re-render.
  455. // TODO: Handle previously-mounted children so they don't get re-mounted
  456. if mem::discriminant(old) != mem::discriminant(new) {
  457. replace = true;
  458. }
  459. if let (VNode::Element(old_element), VNode::Element(new_element)) = (old, new) {
  460. // Replace if there are different element tags
  461. if old_element.tag != new_element.tag {
  462. replace = true;
  463. }
  464. // Replace if two elements have different keys
  465. // TODO: More robust key support. This is just an early stopgap to allow you to force replace
  466. // an element... say if it's event changed. Just change the key name for now.
  467. // In the future we want keys to be used to create a Patch::ReOrder to re-order siblings
  468. if old_element.attrs.get("key").is_some()
  469. && old_element.attrs.get("key") != new_element.attrs.get("key")
  470. {
  471. replace = true;
  472. }
  473. }
  474. // Handle replacing of a node
  475. if replace {
  476. patches.push(Patch::Replace(*cur_node_idx, &new));
  477. if let VNode::Element(old_element_node) = old {
  478. for child in old_element_node.children.iter() {
  479. increment_node_idx_for_children(child, cur_node_idx);
  480. }
  481. }
  482. return patches;
  483. }
  484. // The following comparison can only contain identical variants, other
  485. // cases have already been handled above by comparing variant
  486. // discriminants.
  487. match (old, new) {
  488. // We're comparing two text nodes
  489. (VNode::Text(old_text), VNode::Text(new_text)) => {
  490. if old_text != new_text {
  491. patches.push(Patch::ChangeText(*cur_node_idx, &new_text));
  492. }
  493. }
  494. // We're comparing two element nodes
  495. (VNode::Element(old_element), VNode::Element(new_element)) => {
  496. let mut add_attributes: HashMap<&str, &str> = HashMap::new();
  497. let mut remove_attributes: Vec<&str> = vec![];
  498. // TODO: -> split out into func
  499. for (new_attr_name, new_attr_val) in new_element.attrs.iter() {
  500. match old_element.attrs.get(new_attr_name) {
  501. Some(ref old_attr_val) => {
  502. if old_attr_val != &new_attr_val {
  503. add_attributes.insert(new_attr_name, new_attr_val);
  504. }
  505. }
  506. None => {
  507. add_attributes.insert(new_attr_name, new_attr_val);
  508. }
  509. };
  510. }
  511. // TODO: -> split out into func
  512. for (old_attr_name, old_attr_val) in old_element.attrs.iter() {
  513. if add_attributes.get(&old_attr_name[..]).is_some() {
  514. continue;
  515. };
  516. match new_element.attrs.get(old_attr_name) {
  517. Some(ref new_attr_val) => {
  518. if new_attr_val != &old_attr_val {
  519. remove_attributes.push(old_attr_name);
  520. }
  521. }
  522. None => {
  523. remove_attributes.push(old_attr_name);
  524. }
  525. };
  526. }
  527. if add_attributes.len() > 0 {
  528. patches.push(Patch::AddAttributes(*cur_node_idx, add_attributes));
  529. }
  530. if remove_attributes.len() > 0 {
  531. patches.push(Patch::RemoveAttributes(*cur_node_idx, remove_attributes));
  532. }
  533. let old_child_count = old_element.children.len();
  534. let new_child_count = new_element.children.len();
  535. if new_child_count > old_child_count {
  536. let append_patch: Vec<&'a VNode> =
  537. new_element.children[old_child_count..].iter().collect();
  538. patches.push(Patch::AppendChildren(*cur_node_idx, append_patch))
  539. }
  540. if new_child_count < old_child_count {
  541. patches.push(Patch::TruncateChildren(*cur_node_idx, new_child_count))
  542. }
  543. let min_count = min(old_child_count, new_child_count);
  544. for index in 0..min_count {
  545. *cur_node_idx = *cur_node_idx + 1;
  546. let old_child = &old_element.children[index];
  547. let new_child = &new_element.children[index];
  548. patches.append(&mut diff_recursive(
  549. &old_child,
  550. &new_child,
  551. cur_node_idx,
  552. ))
  553. }
  554. if new_child_count < old_child_count {
  555. for child in old_element.children[min_count..].iter() {
  556. increment_node_idx_for_children(child, cur_node_idx);
  557. }
  558. }
  559. }
  560. (VNode::Text(_), VNode::Element(_)) | (VNode::Element(_), VNode::Text(_)) => {
  561. unreachable!(
  562. "Unequal variant discriminants should already have been handled"
  563. );
  564. }
  565. _ => todo!("Diffing Not yet implemented for all node types"),
  566. };
  567. // new_root.create_element()
  568. patches
  569. }
  570. fn increment_node_idx_for_children<'a, 'b>(
  571. old: &'a VNode,
  572. cur_node_idx: &'b mut usize,
  573. ) {
  574. *cur_node_idx += 1;
  575. if let VNode::Element(element_node) = old {
  576. for child in element_node.children.iter() {
  577. increment_node_idx_for_children(&child, cur_node_idx);
  578. }
  579. }
  580. }
  581. // #[cfg(test)]
  582. // mod tests {
  583. // use super::*;
  584. // use crate::prelude::*;
  585. // type VirtualNode = VNode;
  586. // /// Test that we generate the right Vec<Patch> for some start and end virtual dom.
  587. // pub struct DiffTestCase<'a> {
  588. // // ex: "Patching root level nodes works"
  589. // pub description: &'static str,
  590. // // ex: html! { <div> </div> }
  591. // pub old: VNode,
  592. // // ex: html! { <strong> </strong> }
  593. // pub new: VNode,
  594. // // ex: vec![Patch::Replace(0, &html! { <strong></strong> })],
  595. // pub expected: Vec<Patch<'a>>,
  596. // }
  597. // impl<'a> DiffTestCase<'a> {
  598. // pub fn test(&self) {
  599. // // ex: vec![Patch::Replace(0, &html! { <strong></strong> })],
  600. // let patches = diff_vnodes(&self.old, &self.new);
  601. // assert_eq!(patches, self.expected, "{}", self.description);
  602. // }
  603. // }
  604. // use super::*;
  605. // use crate::nodes::{VNode, VText};
  606. // use std::collections::HashMap;
  607. // #[test]
  608. // fn replace_node() {
  609. // DiffTestCase {
  610. // description: "Replace the root if the tag changed",
  611. // old: html! { <div> </div> },
  612. // new: html! { <span> </span> },
  613. // expected: vec![Patch::Replace(0, &html! { <span></span> })],
  614. // }
  615. // .test();
  616. // DiffTestCase {
  617. // description: "Replace a child node",
  618. // old: html! { <div> <b></b> </div> },
  619. // new: html! { <div> <strong></strong> </div> },
  620. // expected: vec![Patch::Replace(1, &html! { <strong></strong> })],
  621. // }
  622. // .test();
  623. // DiffTestCase {
  624. // description: "Replace node with a child",
  625. // old: html! { <div> <b>1</b> <b></b> </div> },
  626. // new: html! { <div> <i>1</i> <i></i> </div>},
  627. // expected: vec![
  628. // Patch::Replace(1, &html! { <i>1</i> }),
  629. // Patch::Replace(3, &html! { <i></i> }),
  630. // ], //required to check correct index
  631. // }
  632. // .test();
  633. // }
  634. // #[test]
  635. // fn add_children() {
  636. // DiffTestCase {
  637. // description: "Added a new node to the root node",
  638. // old: html! { <div> <b></b> </div> },
  639. // new: html! { <div> <b></b> <span></span> </div> },
  640. // expected: vec![Patch::AppendChildren(0, vec![&html! { <span></span> }])],
  641. // }
  642. // .test();
  643. // }
  644. // #[test]
  645. // fn remove_nodes() {
  646. // DiffTestCase {
  647. // description: "Remove all child nodes at and after child sibling index 1",
  648. // old: html! { <div> <b></b> <span></span> </div> },
  649. // new: html! { <div> </div> },
  650. // expected: vec![Patch::TruncateChildren(0, 0)],
  651. // }
  652. // .test();
  653. // DiffTestCase {
  654. // description: "Remove a child and a grandchild node",
  655. // old: html! {
  656. // <div>
  657. // <span>
  658. // <b></b>
  659. // // This `i` tag will get removed
  660. // <i></i>
  661. // </span>
  662. // // This `strong` tag will get removed
  663. // <strong></strong>
  664. // </div> },
  665. // new: html! {
  666. // <div>
  667. // <span>
  668. // <b></b>
  669. // </span>
  670. // </div> },
  671. // expected: vec![Patch::TruncateChildren(0, 1), Patch::TruncateChildren(1, 1)],
  672. // }
  673. // .test();
  674. // DiffTestCase {
  675. // description: "Removing child and change next node after parent",
  676. // old: html! { <div> <b> <i></i> <i></i> </b> <b></b> </div> },
  677. // new: html! { <div> <b> <i></i> </b> <i></i> </div>},
  678. // expected: vec![
  679. // Patch::TruncateChildren(1, 1),
  680. // Patch::Replace(4, &html! { <i></i> }),
  681. // ], //required to check correct index
  682. // }
  683. // .test();
  684. // }
  685. // #[test]
  686. // fn add_attributes() {
  687. // let mut attributes = HashMap::new();
  688. // attributes.insert("id", "hello");
  689. // DiffTestCase {
  690. // old: html! { <div> </div> },
  691. // new: html! { <div id="hello"> </div> },
  692. // expected: vec![Patch::AddAttributes(0, attributes.clone())],
  693. // description: "Add attributes",
  694. // }
  695. // .test();
  696. // DiffTestCase {
  697. // old: html! { <div id="foobar"> </div> },
  698. // new: html! { <div id="hello"> </div> },
  699. // expected: vec![Patch::AddAttributes(0, attributes)],
  700. // description: "Change attribute",
  701. // }
  702. // .test();
  703. // }
  704. // #[test]
  705. // fn remove_attributes() {
  706. // DiffTestCase {
  707. // old: html! { <div id="hey-there"></div> },
  708. // new: html! { <div> </div> },
  709. // expected: vec![Patch::RemoveAttributes(0, vec!["id"])],
  710. // description: "Add attributes",
  711. // }
  712. // .test();
  713. // }
  714. // #[test]
  715. // fn change_attribute() {
  716. // let mut attributes = HashMap::new();
  717. // attributes.insert("id", "changed");
  718. // DiffTestCase {
  719. // description: "Add attributes",
  720. // old: html! { <div id="hey-there"></div> },
  721. // new: html! { <div id="changed"> </div> },
  722. // expected: vec![Patch::AddAttributes(0, attributes)],
  723. // }
  724. // .test();
  725. // }
  726. // #[test]
  727. // fn replace_text_node() {
  728. // DiffTestCase {
  729. // description: "Replace text node",
  730. // old: html! { Old },
  731. // new: html! { New },
  732. // expected: vec![Patch::ChangeText(0, &VText::new("New"))],
  733. // }
  734. // .test();
  735. // }
  736. // // Initially motivated by having two elements where all that changed was an event listener
  737. // // because right now we don't patch event listeners. So.. until we have a solution
  738. // // for that we can just give them different keys to force a replace.
  739. // #[test]
  740. // fn replace_if_different_keys() {
  741. // DiffTestCase {
  742. // description: "If two nodes have different keys always generate a full replace.",
  743. // old: html! { <div key="1"> </div> },
  744. // new: html! { <div key="2"> </div> },
  745. // expected: vec![Patch::Replace(0, &html! {<div key="2"> </div>})],
  746. // }
  747. // .test()
  748. // }
  749. // // // TODO: Key support
  750. // // #[test]
  751. // // fn reorder_chldren() {
  752. // // let mut attributes = HashMap::new();
  753. // // attributes.insert("class", "foo");
  754. // //
  755. // // let old_children = vec![
  756. // // // old node 0
  757. // // html! { <div key="hello", id="same-id", style="",></div> },
  758. // // // removed
  759. // // html! { <div key="gets-removed",> { "This node gets removed"} </div>},
  760. // // // old node 2
  761. // // html! { <div key="world", class="changed-class",></div>},
  762. // // // removed
  763. // // html! { <div key="this-got-removed",> { "This node gets removed"} </div>},
  764. // // ];
  765. // //
  766. // // let new_children = vec![
  767. // // html! { <div key="world", class="foo",></div> },
  768. // // html! { <div key="new",> </div>},
  769. // // html! { <div key="hello", id="same-id",></div>},
  770. // // ];
  771. // //
  772. // // test(DiffTestCase {
  773. // // old: html! { <div> { old_children } </div> },
  774. // // new: html! { <div> { new_children } </div> },
  775. // // expected: vec![
  776. // // // TODO: Come up with the patch structure for keyed nodes..
  777. // // // keying should only work if all children have keys..
  778. // // ],
  779. // // description: "Add attributes",
  780. // // })
  781. // // }
  782. // }
  783. }
  784. }
  785. mod vcomponent {
  786. // -----------------------------------------------
  787. // Allow debug/display adherent to the HTML spec
  788. // -----------------------------------------------
  789. impl fmt::Debug for VComponent {
  790. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  791. // TODO: @JON Implement how components should be formatted when spit out to html
  792. // It probably can't be as straightforward as renderinng their VNodes
  793. // It _could_ be, but we can't really implement that directly
  794. // Instead, we should drop a vnode labeled with the component id/key
  795. // write!(
  796. // f,
  797. // "Element(<{}>, attrs: {:?}, children: {:?})",
  798. // self.tag, self.attrs, self.children,
  799. // )
  800. Ok(())
  801. }
  802. }
  803. impl fmt::Display for VComponent {
  804. // Turn a VElement and all of it's children (recursively) into an HTML string
  805. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  806. // write!(f, "<{}", self.tag).unwrap();
  807. // for (attr, value) in self.attrs.iter() {
  808. // write!(f, r#" {}="{}""#, attr, value)?;
  809. // }
  810. // write!(f, ">")?;
  811. // for child in self.children.iter() {
  812. // write!(f, "{}", child.to_string())?;
  813. // }
  814. // if !crate::validation::is_self_closing(&self.tag) {
  815. // write!(f, "</{}>", self.tag)?;
  816. // }
  817. Ok(())
  818. }
  819. }
  820. }
  821. }
  822. // pub mod iterables {
  823. // use super::*;
  824. // /// Used by the html! macro for all braced child nodes so that we can use any type
  825. // /// that implements Into<IterableNodes>
  826. // ///
  827. // /// html! { <div> { nodes } </div> }
  828. // ///
  829. // /// nodes can be a String .. VNode .. Vec<VNode> ... etc
  830. // pub struct IterableNodes(Vec<VNode>);
  831. // impl IterableNodes {
  832. // /// Retrieve the first node mutably
  833. // pub fn first(&mut self) -> &mut VNode {
  834. // self.0.first_mut().unwrap()
  835. // }
  836. // /// Retrieve the last node mutably
  837. // pub fn last(&mut self) -> &mut VNode {
  838. // self.0.last_mut().unwrap()
  839. // }
  840. // }
  841. // impl IntoIterator for IterableNodes {
  842. // type Item = VNode;
  843. // // TODO: Is this possible with an array [VNode] instead of a vec?
  844. // type IntoIter = ::std::vec::IntoIter<VNode>;
  845. // fn into_iter(self) -> Self::IntoIter {
  846. // self.0.into_iter()
  847. // }
  848. // }
  849. // impl From<VNode> for IterableNodes {
  850. // fn from(other: VNode) -> Self {
  851. // IterableNodes(vec![other])
  852. // }
  853. // }
  854. // impl From<Vec<VNode>> for IterableNodes {
  855. // fn from(other: Vec<VNode>) -> Self {
  856. // IterableNodes(other)
  857. // }
  858. // }
  859. // }