feat: enable arbitrary body in rsx! macro

This commit is contained in:
Jonathan Kelley committed 2021-07-07 18:17:00 -04:00
1 parent fd7933561f
commit 7aec40d57e
38 files changed
+142 -88

No files matched your search

+5
View File
@@ -39,6 +39,11 @@ impl Parse for AmbiguousElement {
}
}
// if input.peek(Ident) {
// let name_str = input.fork().parse::<Ident>().unwrap().to_string();
// } else {
// }
if let Ok(name) = input.fork().parse::<Ident>() {
let name_str = name.to_string();
+57 -27
View File
@@ -45,27 +45,17 @@ impl Parse for Component {
let mut children: Vec<Node> = Vec::new();
let mut manual_props = None;
'parsing: loop {
// [1] Break if empty
if content.is_empty() {
break 'parsing;
}
if content.peek(Token![..]) {
content.parse::<Token![..]>()?;
manual_props = Some(content.parse::<Expr>()?);
} else if content.peek(Ident) && content.peek2(Token![:]) {
body.push(content.parse::<ComponentField>()?);
} else {
children.push(content.parse::<Node>()?);
}
// consume comma if it exists
// we don't actually care if there *are* commas between attrs
if content.peek(Token![,]) {
let _ = content.parse::<Token![,]>();
}
}
parse_component_body(
&content,
&BodyParseConfig {
allow_children: true,
allow_fields: true,
allow_manual_props: true,
},
&mut body,
&mut children,
&mut manual_props,
)?;
Ok(Self {
name,
@@ -76,6 +66,52 @@ impl Parse for Component {
}
}
pub struct BodyParseConfig {
pub allow_fields: bool,
pub allow_children: bool,
pub allow_manual_props: bool,
}
pub fn parse_component_body(
content: &ParseBuffer,
cfg: &BodyParseConfig,
body: &mut Vec<ComponentField>,
children: &mut Vec<Node>,
manual_props: &mut Option<Expr>,
) -> Result<()> {
'parsing: loop {
// [1] Break if empty
if content.is_empty() {
break 'parsing;
}
if content.peek(Token![..]) {
if !cfg.allow_manual_props {
// toss an error
}
content.parse::<Token![..]>()?;
*manual_props = Some(content.parse::<Expr>()?);
} else if content.peek(Ident) && content.peek2(Token![:]) {
if !cfg.allow_fields {
// toss an error
}
body.push(content.parse::<ComponentField>()?);
} else {
if !cfg.allow_children {
// toss an error
}
children.push(content.parse::<Node>()?);
}
// consume comma if it exists
// we don't actually care if there *are* commas between attrs
if content.peek(Token![,]) {
let _ = content.parse::<Token![,]>();
}
}
Ok(())
}
impl ToTokens for Component {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let name = &self.name;
@@ -135,12 +171,6 @@ impl ToTokens for Component {
let children = quote! {
[ #( #childs ),* ]
};
// ChildrenList::new(__cx)
// #( .add_child(#childs) )*
// .finish()
// ChildrenList::new(__cx)
// #( .add_child(#childs) )*
// .finish()
tokens.append_all(quote! {
__cx.virtual_child(
+19 -9
View File
@@ -34,14 +34,14 @@ use syn::{
pub struct RsxRender {
custom_context: Option<Ident>,
roots: Vec<AmbiguousElement>,
roots: Vec<Node>,
}
impl Parse for RsxRender {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(LitStr) {
return input.parse::<LitStr>()?.parse::<RsxRender>();
}
// if input.peek(LitStr) {
// return input.parse::<LitStr>()?.parse::<RsxRender>();
// }
// try to parse the first ident and comma
let custom_context =
@@ -61,13 +61,23 @@ impl Parse for RsxRender {
None
};
let mut roots = Vec::new();
while !input.is_empty() {
roots.push(input.parse::<AmbiguousElement>()?);
}
let mut body = Vec::new();
let mut children = Vec::new();
let mut manual_props = None;
parse_component_body(
input,
&BodyParseConfig {
allow_children: true,
allow_fields: false,
allow_manual_props: false,
},
&mut body,
&mut children,
&mut manual_props,
)?;
Ok(Self {
roots,
roots: children,
custom_context,
})
}
+12 -12
View File
@@ -16,18 +16,6 @@ pub enum Node {
RawExpr(Expr),
}
impl ToTokens for Node {
fn to_tokens(&self, tokens: &mut TokenStream2) {
match &self {
Node::Element(el) => el.to_tokens(tokens),
Node::Text(txt) => txt.to_tokens(tokens),
Node::RawExpr(exp) => tokens.append_all(quote! {
__cx.fragment_from_iter(#exp)
}),
}
}
}
impl Parse for Node {
fn parse(stream: ParseStream) -> Result<Self> {
// Supposedly this approach is discouraged due to inability to return proper errors
@@ -47,6 +35,18 @@ impl Parse for Node {
}
}
impl ToTokens for Node {
fn to_tokens(&self, tokens: &mut TokenStream2) {
match &self {
Node::Element(el) => el.to_tokens(tokens),
Node::Text(txt) => txt.to_tokens(tokens),
Node::RawExpr(exp) => tokens.append_all(quote! {
__cx.fragment_from_iter(#exp)
}),
}
}
}
// =======================================
// Parse just plain text
// =======================================