Skip to content

Commit

Permalink
Merge pull request #7 from thomaseizinger/feat/reference-props
Browse files Browse the repository at this point in the history
Implement reference props
  • Loading branch information
Pitasi authored Feb 11, 2024
2 parents 6064209 + 5f4ede3 commit d048fc7
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
22 changes: 15 additions & 7 deletions rscx-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rstml::{
Parser, ParserConfig,
};
use syn::punctuated::Punctuated;
use syn::{parse::Parse, parse_quote, spanned::Spanned, Expr, ExprLit, FnArg, ItemStruct, Token};
use syn::{parse::Parse, parse_quote, spanned::Spanned, Expr, ExprLit, FnArg, ItemStruct, Token, Type, Lifetime};

#[proc_macro]
pub fn html(tokens: TokenStream) -> TokenStream {
Expand Down Expand Up @@ -378,8 +378,8 @@ impl ToTokens for PropsStruct {
#[builder(doc, crate_module_path=::rscx::typed_builder)]
#item

impl ::rscx::props::Props for #name {
type Builder = #builder_name;
impl<'a> ::rscx::props::Props for #name<'a> {
type Builder = #builder_name<'a>;
fn builder() -> Self::Builder {
#name::builder()
}
Expand Down Expand Up @@ -456,6 +456,12 @@ impl ToTokens for ComponentFn {
panic!("receiver arguments unsupported");
}
FnArg::Typed(mut t) => {
if let Type::Reference(ty_ref) = t.ty.as_mut() {
if ty_ref.lifetime.is_none() {
ty_ref.lifetime = Some(Lifetime::new("'a", ty_ref.span()));
}
}

if t.attrs.is_empty() {
t.attrs.push(parse_quote! { #[builder(setter(into))] });
}
Expand All @@ -481,11 +487,13 @@ impl ToTokens for ComponentFn {
(
quote! {
#[rscx::props]
pub struct #props_name {
#field_defs
pub struct #props_name<'a> {
#field_defs,
#[builder(default)]
phantom: std::marker::PhantomData<&'a ()>
}
},
quote! { #props_name { #field_names }: #props_name },
quote! { #props_name { #field_names, .. }: #props_name<'a> },
)
}
};
Expand All @@ -497,7 +505,7 @@ impl ToTokens for ComponentFn {
tokens.extend(quote! {
#defs
#[allow(non_snake_case)]
#vis async fn #name(#args) #output {
#vis async fn #name<'a>(#args) #output {
#body
}
});
Expand Down
38 changes: 38 additions & 0 deletions rscx/examples/reference_props.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use rscx::{component, html};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let app = app().await;
println!("{}", app);
Ok(())
}

// simple function returning a String
async fn app() -> String {
let s = "ul { color: red; }";
html! {
<!DOCTYPE html>
<html>
<head>
<style>{s}</style>
</head>
<body>
// call a component with props and children
<Section title="Hello">
<p>"I am a paragraph"</p>
</Section>
</body>
</html>
}
}

#[component]
/// mark functions with #[component] to use them as components inside html! macro
fn Section(title: &str, children: String) -> String {
html! {
<div>
<h1>{ title }</h1>
{ children }
</div>
}
}

0 comments on commit d048fc7

Please sign in to comment.