diff --git a/examples/hot_reload.rs b/examples/hot_reload.rs index 7fe3f4d5a..3e9d980cc 100644 --- a/examples/hot_reload.rs +++ b/examples/hot_reload.rs @@ -21,7 +21,24 @@ fn app(cx: Scope) -> Element { cx.render(rsx! { h1 { width: format!("{}px", count), - "High-Five counter: {count}" + "High-Five counter: {count}", + Comp{ + color: "#083289" + } + } + }) +} + +#[derive(PartialEq, Props)] +struct CompProps { + color: &'static str, +} + +fn Comp(cx: Scope) -> Element { + cx.render(rsx! { + h1 { + color: cx.props.color, + "Hello, from a component!" } }) } diff --git a/packages/core-macro/src/lib.rs b/packages/core-macro/src/lib.rs index 23822dbad..e024be7f6 100644 --- a/packages/core-macro/src/lib.rs +++ b/packages/core-macro/src/lib.rs @@ -202,11 +202,11 @@ pub fn rsx(s: TokenStream) -> TokenStream { #rsx_text.to_string(), ); }); - LazyNodes::new(move |factory|{ + LazyNodes::new(move |__cx|{ let read = rsx_text_index.read(); if let Some(text) = read.get(&line_num){ interpert_rsx( - factory, + __cx, &text, #captured ) diff --git a/packages/rsx/src/component.rs b/packages/rsx/src/component.rs index 158660baa..72a803a50 100644 --- a/packages/rsx/src/component.rs +++ b/packages/rsx/src/component.rs @@ -22,6 +22,7 @@ use syn::{ token, Expr, Ident, LitStr, Result, Token, }; +#[derive(PartialEq, Eq)] pub struct Component { pub name: syn::Path, pub body: Vec, @@ -149,11 +150,13 @@ impl ToTokens for Component { } // the struct's fields info +#[derive(PartialEq, Eq)] pub struct ComponentField { pub name: Ident, pub content: ContentField, } +#[derive(PartialEq, Eq)] pub enum ContentField { ManExpr(Expr), Formatted(LitStr), diff --git a/packages/rsx/src/element.rs b/packages/rsx/src/element.rs index d1188ae55..b74403b83 100644 --- a/packages/rsx/src/element.rs +++ b/packages/rsx/src/element.rs @@ -10,6 +10,7 @@ use syn::{ // ======================================= // Parse the VNode::Element type // ======================================= +#[derive(PartialEq, Eq)] pub struct Element { pub name: Ident, pub key: Option, @@ -189,6 +190,7 @@ impl ToTokens for Element { } } +#[derive(PartialEq, Eq)] pub enum ElementAttr { /// attribute: "valuee {}" AttrText { @@ -225,6 +227,7 @@ pub enum ElementAttr { Meta(String), } +#[derive(PartialEq, Eq)] pub struct ElementAttrNamed { pub el_name: Ident, pub attr: ElementAttr, diff --git a/packages/rsx/src/node.rs b/packages/rsx/src/node.rs index a41bd7098..6828ab58c 100644 --- a/packages/rsx/src/node.rs +++ b/packages/rsx/src/node.rs @@ -15,6 +15,7 @@ Parse -> "text {with_args}" -> (0..10).map(|f| rsx!("asd")), // <--- notice the comma - must be a complete expr */ +#[derive(PartialEq, Eq)] pub enum BodyNode { Element(Element), Component(Component), diff --git a/packages/rsx_interperter/src/captuered_context.rs b/packages/rsx_interperter/src/captuered_context.rs index 2bfa2dcc9..9e4f2cd34 100644 --- a/packages/rsx_interperter/src/captuered_context.rs +++ b/packages/rsx_interperter/src/captuered_context.rs @@ -83,6 +83,13 @@ impl ToTokens for CapturedContextBuilder { iterators, captured_expressions, } = self; + let compontents_str = components + .iter() + .map(|comp| comp.to_token_stream().to_string()); + let components = components.iter().map(|comp| comp); + let iterators_str = iterators + .iter() + .map(|expr| expr.to_token_stream().to_string()); let captured: Vec<_> = attributes .iter() .map(|(_, fmt)| fmt.named_args.iter()) @@ -99,8 +106,8 @@ impl ToTokens for CapturedContextBuilder { captured: IfmtArgs{ named_args: vec![#((#captured_names, #captured_expr.to_string())),*] }, - components: vec![#(#components),*], - iterators: vec![#(#iterators),*], + components: vec![#((#compontents_str, #components)),*], + iterators: vec![#((#iterators_str, #iterators)),*], expressions: vec![#((#captured_attr_expressions_text, #captured_expressions.to_string())),*], } }) @@ -113,9 +120,9 @@ pub struct CapturedContext<'a> { // // map of the attribute name and element path to the formated value // pub captured_attribute_values: IfmtArgs, // the only thing we can update in component is the children - pub components: Vec>, + pub components: Vec<(&'static str, VNode<'a>)>, // we can't reasonably interpert iterators, so they are staticly inserted - pub iterators: Vec>, + pub iterators: Vec<(&'static str, VNode<'a>)>, // map expression to the value resulting from the expression pub expressions: Vec<(&'static str, String)>, } diff --git a/packages/rsx_interperter/src/interperter.rs b/packages/rsx_interperter/src/interperter.rs index a23dda040..8a7f0b1ed 100644 --- a/packages/rsx_interperter/src/interperter.rs +++ b/packages/rsx_interperter/src/interperter.rs @@ -1,7 +1,8 @@ use dioxus_core::{Attribute, NodeFactory, VNode}; -use dioxus_rsx::{BodyNode, CallBody, ElementAttr}; +use dioxus_rsx::{BodyNode, CallBody, Component, ElementAttr}; +use quote::ToTokens; use std::str::FromStr; -use syn::{parse_str, Expr}; +use syn::{parse2, parse_str, Expr}; use crate::attributes::attrbute_to_static_str; use crate::captuered_context::{CapturedContext, IfmtArgs}; @@ -83,17 +84,21 @@ impl FromStr for InterperedIfmt { } } -pub fn build<'a>(rsx: CallBody, ctx: CapturedContext, factory: &NodeFactory<'a>) -> VNode<'a> { +pub fn build<'a>( + rsx: CallBody, + mut ctx: CapturedContext<'a>, + factory: &NodeFactory<'a>, +) -> VNode<'a> { let children_built = factory.bump().alloc(Vec::new()); for (i, child) in rsx.roots.into_iter().enumerate() { - children_built.push(build_node(child, &ctx, factory, i.to_string().as_str())); + children_built.push(build_node(child, &mut ctx, factory, i.to_string().as_str())); } factory.fragment_from_iter(children_built.iter()) } fn build_node<'a>( node: BodyNode, - ctx: &CapturedContext, + ctx: &mut CapturedContext<'a>, factory: &NodeFactory<'a>, key: &str, ) -> Option> { @@ -190,7 +195,19 @@ fn build_node<'a>( None } } - BodyNode::Component(_) => todo!(), + BodyNode::Component(comp) => { + let expr: Expr = parse2(comp.to_token_stream()).unwrap(); + if let Some(idx) = ctx + .components + .iter() + .position(|(code, _)| parse_str::(*code).unwrap() == expr) + { + let (_, vnode) = ctx.components.remove(idx); + Some(vnode) + } else { + panic!("could not resolve component {:?}", comp.name); + } + } BodyNode::RawExpr(_) => todo!(), BodyNode::Meta(_) => todo!(), } diff --git a/packages/rsx_interperter/src/lib.rs b/packages/rsx_interperter/src/lib.rs index aae307bef..708d21edb 100644 --- a/packages/rsx_interperter/src/lib.rs +++ b/packages/rsx_interperter/src/lib.rs @@ -34,7 +34,7 @@ pub fn with_hot_reload(cx: Scope) -> Element { pub fn interpert_rsx<'a, 'b>( factory: dioxus_core::NodeFactory<'a>, text: &str, - context: captuered_context::CapturedContext, + context: captuered_context::CapturedContext<'a>, ) -> VNode<'a> { build(parse_str(text).unwrap(), context, &factory) }