add component support

This commit is contained in:
Evan Almloff committed 2022-05-27 09:47:44 -05:00
1 parent 07da854455
commit a0c7e4d78a
8 files changed
+62 -14

No files matched your search

+18 -1
View File
@@ -21,7 +21,24 @@ fn app(cx: Scope) -> Element {
cx.render(rsx! { cx.render(rsx! {
h1 { h1 {
width: format!("{}px", count), 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<CompProps>) -> Element {
cx.render(rsx! {
h1 {
color: cx.props.color,
"Hello, from a component!"
} }
}) })
} }
+2 -2
View File
@@ -202,11 +202,11 @@ pub fn rsx(s: TokenStream) -> TokenStream {
#rsx_text.to_string(), #rsx_text.to_string(),
); );
}); });
LazyNodes::new(move |factory|{ LazyNodes::new(move |__cx|{
let read = rsx_text_index.read(); let read = rsx_text_index.read();
if let Some(text) = read.get(&line_num){ if let Some(text) = read.get(&line_num){
interpert_rsx( interpert_rsx(
factory, __cx,
&text, &text,
#captured #captured
) )
+3
View File
@@ -22,6 +22,7 @@ use syn::{
token, Expr, Ident, LitStr, Result, Token, token, Expr, Ident, LitStr, Result, Token,
}; };
#[derive(PartialEq, Eq)]
pub struct Component { pub struct Component {
pub name: syn::Path, pub name: syn::Path,
pub body: Vec<ComponentField>, pub body: Vec<ComponentField>,
@@ -149,11 +150,13 @@ impl ToTokens for Component {
} }
// the struct's fields info // the struct's fields info
#[derive(PartialEq, Eq)]
pub struct ComponentField { pub struct ComponentField {
pub name: Ident, pub name: Ident,
pub content: ContentField, pub content: ContentField,
} }
#[derive(PartialEq, Eq)]
pub enum ContentField { pub enum ContentField {
ManExpr(Expr), ManExpr(Expr),
Formatted(LitStr), Formatted(LitStr),
+3
View File
@@ -10,6 +10,7 @@ use syn::{
// ======================================= // =======================================
// Parse the VNode::Element type // Parse the VNode::Element type
// ======================================= // =======================================
#[derive(PartialEq, Eq)]
pub struct Element { pub struct Element {
pub name: Ident, pub name: Ident,
pub key: Option<LitStr>, pub key: Option<LitStr>,
@@ -189,6 +190,7 @@ impl ToTokens for Element {
} }
} }
#[derive(PartialEq, Eq)]
pub enum ElementAttr { pub enum ElementAttr {
/// attribute: "valuee {}" /// attribute: "valuee {}"
AttrText { AttrText {
@@ -225,6 +227,7 @@ pub enum ElementAttr {
Meta(String), Meta(String),
} }
#[derive(PartialEq, Eq)]
pub struct ElementAttrNamed { pub struct ElementAttrNamed {
pub el_name: Ident, pub el_name: Ident,
pub attr: ElementAttr, pub attr: ElementAttr,
+1
View File
@@ -15,6 +15,7 @@ Parse
-> "text {with_args}" -> "text {with_args}"
-> (0..10).map(|f| rsx!("asd")), // <--- notice the comma - must be a complete expr -> (0..10).map(|f| rsx!("asd")), // <--- notice the comma - must be a complete expr
*/ */
#[derive(PartialEq, Eq)]
pub enum BodyNode { pub enum BodyNode {
Element(Element), Element(Element),
Component(Component), Component(Component),
@@ -83,6 +83,13 @@ impl ToTokens for CapturedContextBuilder {
iterators, iterators,
captured_expressions, captured_expressions,
} = self; } = 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 let captured: Vec<_> = attributes
.iter() .iter()
.map(|(_, fmt)| fmt.named_args.iter()) .map(|(_, fmt)| fmt.named_args.iter())
@@ -99,8 +106,8 @@ impl ToTokens for CapturedContextBuilder {
captured: IfmtArgs{ captured: IfmtArgs{
named_args: vec![#((#captured_names, #captured_expr.to_string())),*] named_args: vec![#((#captured_names, #captured_expr.to_string())),*]
}, },
components: vec![#(#components),*], components: vec![#((#compontents_str, #components)),*],
iterators: vec![#(#iterators),*], iterators: vec![#((#iterators_str, #iterators)),*],
expressions: vec![#((#captured_attr_expressions_text, #captured_expressions.to_string())),*], 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 // // map of the attribute name and element path to the formated value
// pub captured_attribute_values: IfmtArgs, // pub captured_attribute_values: IfmtArgs,
// the only thing we can update in component is the children // the only thing we can update in component is the children
pub components: Vec<VNode<'a>>, pub components: Vec<(&'static str, VNode<'a>)>,
// we can't reasonably interpert iterators, so they are staticly inserted // we can't reasonably interpert iterators, so they are staticly inserted
pub iterators: Vec<VNode<'a>>, pub iterators: Vec<(&'static str, VNode<'a>)>,
// map expression to the value resulting from the expression // map expression to the value resulting from the expression
pub expressions: Vec<(&'static str, String)>, pub expressions: Vec<(&'static str, String)>,
} }
+23 -6
View File
@@ -1,7 +1,8 @@
use dioxus_core::{Attribute, NodeFactory, VNode}; 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 std::str::FromStr;
use syn::{parse_str, Expr}; use syn::{parse2, parse_str, Expr};
use crate::attributes::attrbute_to_static_str; use crate::attributes::attrbute_to_static_str;
use crate::captuered_context::{CapturedContext, IfmtArgs}; 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()); let children_built = factory.bump().alloc(Vec::new());
for (i, child) in rsx.roots.into_iter().enumerate() { 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()) factory.fragment_from_iter(children_built.iter())
} }
fn build_node<'a>( fn build_node<'a>(
node: BodyNode, node: BodyNode,
ctx: &CapturedContext, ctx: &mut CapturedContext<'a>,
factory: &NodeFactory<'a>, factory: &NodeFactory<'a>,
key: &str, key: &str,
) -> Option<VNode<'a>> { ) -> Option<VNode<'a>> {
@@ -190,7 +195,19 @@ fn build_node<'a>(
None 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::<Expr>(*code).unwrap() == expr)
{
let (_, vnode) = ctx.components.remove(idx);
Some(vnode)
} else {
panic!("could not resolve component {:?}", comp.name);
}
}
BodyNode::RawExpr(_) => todo!(), BodyNode::RawExpr(_) => todo!(),
BodyNode::Meta(_) => todo!(), BodyNode::Meta(_) => todo!(),
} }
+1 -1
View File
@@ -34,7 +34,7 @@ pub fn with_hot_reload(cx: Scope<Component>) -> Element {
pub fn interpert_rsx<'a, 'b>( pub fn interpert_rsx<'a, 'b>(
factory: dioxus_core::NodeFactory<'a>, factory: dioxus_core::NodeFactory<'a>,
text: &str, text: &str,
context: captuered_context::CapturedContext, context: captuered_context::CapturedContext<'a>,
) -> VNode<'a> { ) -> VNode<'a> {
build(parse_str(text).unwrap(), context, &factory) build(parse_str(text).unwrap(), context, &factory)
} }