Skip to content
This repository was archived by the owner on Jul 5, 2025. It is now read-only.

Commit db903b4

Browse files
committed
wip: less opinionated rsx walker
1 parent b7ae6bb commit db903b4

File tree

7 files changed

+334
-115
lines changed

7 files changed

+334
-115
lines changed

crates/sweet_render/src/render/rsx_renderer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub struct RsxRenderVisitor {
3838
position: TreePosition,
3939
}
4040

41-
impl PositionVisitor for RsxRenderVisitor {
41+
impl VisitWithPosition for RsxRenderVisitor {
4242
fn position(&self) -> &TreePosition { &self.position }
4343
fn position_mut(&mut self) -> &mut TreePosition { &mut self.position }
4444
}
@@ -75,8 +75,8 @@ impl TreeVisitor<RsxNode<String>> for RsxRenderVisitor {
7575
self.html.push('>');
7676
}
7777
}
78-
RsxNode::TextBlock(val) => self.html += val,
79-
RsxNode::Component(_, _) => {
78+
RsxNode::Block(val) => self.html += val,
79+
RsxNode::Component(_) => {
8080
// components are not html
8181
}
8282
};

crates/sweet_render/src/render/sweet_rsx_visitor.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,10 @@ impl TreeMapper<RsxNode<RustParts>, RsxNode<String>> for SweetRsxVisitor {
5555
RsxNode::Comment(val) => RsxNode::Comment(val),
5656
RsxNode::Element(el) => RsxNode::Element(self.parse_element(el)?),
5757
RsxNode::Text(val) => RsxNode::Text(val),
58-
RsxNode::TextBlock(RustParts::TextBlock(val)) => {
59-
RsxNode::TextBlock(val)
60-
}
61-
RsxNode::TextBlock(parts) => {
58+
RsxNode::Block(RustParts::TextBlock(val)) => RsxNode::Block(val),
59+
RsxNode::Block(parts) => {
6260
return Err(ParseError::hydration("TextBlock", parts));
6361
}
64-
RsxNode::Component(RustParts::Component(component), children) => {
65-
// components arent html, return empty string
66-
let mut component_children = self.map_nodes(component.nodes)?;
67-
component_children.append(&mut self.map_nodes(children)?);
68-
RsxNode::Component(String::new(), component_children)
69-
}
70-
RsxNode::Component(parts, _) => {
71-
return Err(ParseError::hydration("Component", parts));
72-
}
7362
};
7463
Ok(node)
7564
}
@@ -140,7 +129,7 @@ impl SweetRsxVisitor {
140129
};
141130
RsxAttribute::BlockValue { key, value }
142131
}
143-
RsxAttribute::Block(RustParts::AttributeBlock(block_str)) => {
132+
RsxAttribute::Block(RustParts::AttributeBlock2(block_str)) => {
144133
RsxAttribute::Block(block_str)
145134
}
146135
RsxAttribute::Block(parts) => {

crates/sweet_rsx/examples/rsx_macro.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,26 @@ impl Component for MyComponent {
1515
}
1616

1717

18-
fn main() {
19-
let onclick = |_| {};
18+
// fn main() {
19+
// let onclick = |_| {};
20+
21+
// let _foo = rsx! {
22+
// <div onclick>
23+
// <p>hello</p>
24+
// <MyComponent value=7/>
25+
// </div>
26+
// };
2027

21-
let _foo = rsx! {
22-
<div onclick>
28+
// let str = _foo.to_info_string();
29+
// println!("{}", str);
30+
// }
31+
fn main() {
32+
let foo = rsx! {
33+
<div>
2334
<p>hello</p>
24-
<MyComponent value=7/>
2535
</div>
2636
};
2737

28-
let str = _foo.to_info_string();
38+
let str = foo.build_string();
2939
println!("{}", str);
3040
}

crates/sweet_rsx/src/parse_rsx/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
pub mod parse_rstml;
2+
mod rsx_node_tokens;
23
#[allow(unused_imports)]
34
pub use self::parse_rstml::*;
5+
pub use rsx_node_tokens::*;
46
pub mod rsx_file_visitor;
57
#[allow(unused_imports)]
68
pub use self::rsx_file_visitor::*;
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote;
3+
use quote::ToTokens;
4+
use sweet_core::tree_old::Node;
5+
use sweet_core::tree_old::TreeVisitor;
6+
use sweet_core::tree_old::TreeVisitorMut;
7+
8+
pub enum RsxNodeTokens {
9+
Doctype,
10+
Text(String),
11+
Comment(String),
12+
Block(TokenStream),
13+
Element {
14+
tag: String,
15+
attributes: Vec<RsxAttributeTokens>,
16+
children: Vec<RsxNodeTokens>,
17+
self_closing: bool,
18+
},
19+
Fragment(Vec<RsxNodeTokens>),
20+
Component(TokenStream),
21+
}
22+
23+
impl Node for RsxNodeTokens {
24+
fn children(&self) -> Option<&Vec<Self>> {
25+
match self {
26+
RsxNodeTokens::Element { children, .. } => Some(children),
27+
RsxNodeTokens::Fragment(vec) => Some(vec),
28+
_ => None,
29+
}
30+
}
31+
fn children_mut(&mut self) -> Option<&mut Vec<Self>> {
32+
match self {
33+
RsxNodeTokens::Element { children, .. } => Some(children),
34+
RsxNodeTokens::Fragment(vec) => Some(vec),
35+
_ => None,
36+
}
37+
}
38+
fn take_children(&mut self) -> Option<Vec<Self>> {
39+
match self {
40+
RsxNodeTokens::Element { children, .. } => {
41+
Some(std::mem::take(children))
42+
}
43+
RsxNodeTokens::Fragment(vec) => Some(std::mem::take(vec)),
44+
_ => None,
45+
}
46+
}
47+
}
48+
49+
pub enum RsxAttributeTokens {
50+
Key { key: String },
51+
KeyValue { key: String, value: String },
52+
BlockValue { key: String, value: TokenStream },
53+
Block(TokenStream),
54+
}
55+
56+
impl ToTokens for RsxNodeTokens {
57+
fn to_tokens(&self, tokens: &mut TokenStream) {
58+
match self {
59+
RsxNodeTokens::Doctype => quote!(RsxNode::Doctype),
60+
RsxNodeTokens::Text(text) => {
61+
quote!(RsxNode::Text(#text.to_string()))
62+
}
63+
RsxNodeTokens::Comment(comment) => {
64+
quote!(RsxNode::Comment(#comment.to_string()))
65+
}
66+
RsxNodeTokens::Block(block) => {
67+
quote!(RsxNode::Block(#block))
68+
}
69+
RsxNodeTokens::Element {
70+
tag,
71+
attributes,
72+
children,
73+
self_closing,
74+
} => {
75+
let children = flatten_children(children);
76+
quote!(RsxNode::Element(RsxElement {
77+
tag: #tag.to_string(),
78+
attributes: vec![#(#attributes),*],
79+
children: #children,
80+
self_closing: #self_closing,
81+
}))
82+
}
83+
RsxNodeTokens::Fragment(vec) => {
84+
quote!(#(#vec),*)
85+
}
86+
RsxNodeTokens::Component(token_stream) => quote!(#token_stream),
87+
}
88+
.to_tokens(tokens);
89+
}
90+
}
91+
92+
93+
fn flatten_children(children: &Vec<RsxNodeTokens>) -> TokenStream {
94+
let add = children.into_iter().map(|child| match child {
95+
RsxNodeTokens::Fragment(children) => {
96+
let children = flatten_children(children);
97+
quote!(vec.extend(#children);)
98+
}
99+
RsxNodeTokens::Component(component) => quote!(vec.extend(#component)),
100+
RsxNodeTokens::Block(block) => {
101+
// unimplemented!("this may be one or many?")
102+
quote!(vec.push(RsxNode::Block(#block)))
103+
}
104+
_ => quote!(vec.push(#child)),
105+
});
106+
107+
quote!({
108+
let mut vec = Vec::new();
109+
#(#add;)*
110+
vec
111+
})
112+
}
113+
114+
impl ToTokens for RsxAttributeTokens {
115+
fn to_tokens(&self, tokens: &mut TokenStream) {
116+
match self {
117+
RsxAttributeTokens::Key{key} => {
118+
quote!(RsxAttribute::Key { key: #key.to_string() })
119+
}
120+
RsxAttributeTokens::KeyValue { key, value } => {
121+
quote!(RsxAttribute::KeyValue { key: #key.to_string(), value: #value.to_string() })
122+
}
123+
RsxAttributeTokens::BlockValue { key,value } => {
124+
quote!(RsxAttribute::BlockValue { key: #key.to_string(),value: #value })
125+
}
126+
RsxAttributeTokens::Block(r) => quote!(RsxAttribute::Block(#r)), }
127+
.to_tokens(tokens);
128+
}
129+
}
130+
131+
132+
pub struct ParseStringNodeTokens {
133+
position: TreePosition,
134+
}
135+
136+
impl TreeVisitorMut<RsxNodeTokens> for ParseStringNodeTokens {
137+
fn visit_node(
138+
&mut self,
139+
node: &mut RsxNodeTokens,
140+
) -> sweet_core::prelude::ParseResult<()> {
141+
match node {
142+
RsxNodeTokens::Block(token_stream) => {
143+
*token_stream = quote! {#token_stream.to_string()}
144+
}
145+
RsxNodeTokens::Element { attributes, .. } => {
146+
for attribute in attributes {
147+
match attribute {
148+
RsxAttributeTokens::BlockValue { value, .. } => {
149+
*value = quote! {#value.to_string()}
150+
}
151+
RsxAttributeTokens::Block(token_stream) => {
152+
*token_stream = quote! {#token_stream.to_string()}
153+
}
154+
_ => {}
155+
}
156+
}
157+
}
158+
_ => {}
159+
}
160+
161+
Ok(())
162+
}
163+
164+
fn leave_node(
165+
&mut self,
166+
node: &mut RsxNodeTokens,
167+
) -> sweet_core::prelude::ParseResult<()> {
168+
Ok(())
169+
}
170+
171+
fn visit_children(
172+
&mut self,
173+
children: &mut Vec<RsxNodeTokens>,
174+
) -> sweet_core::prelude::ParseResult<()> {
175+
Ok(())
176+
}
177+
178+
fn leave_children(
179+
&mut self,
180+
children: &mut Vec<RsxNodeTokens>,
181+
) -> sweet_core::prelude::ParseResult<()> {
182+
Ok(())
183+
}
184+
}
185+
186+
187+
188+
// fn visit_attribute(&mut self, attr: NodeAttribute) -> RsxAttributeTokens {
189+
// match attr {
190+
// NodeAttribute::Block(block) => RsxAttributeTokens::Block(
191+
// quote! {RustParts::AttributeBlock(#block)},
192+
// ),
193+
// NodeAttribute::Attribute(attr) => {
194+
// let key = attr.key.to_string();
195+
196+
// if key.starts_with("on") {
197+
// let tokens = if let Some(value) = attr.value() {
198+
// value.to_token_stream()
199+
// } else {
200+
// // default to a function called onclick
201+
// Ident::new(&key, key.span()).to_token_stream()
202+
// };
203+
// RsxAttribute::BlockValue {
204+
// key,
205+
// value: quote! {RustParts::Event(Box::new(#tokens))},
206+
// }
207+
// } else if let Some(value) = attr.value() {
208+
// match value {
209+
// // only literals (string, number, bool) are not rusty
210+
// syn::Expr::Lit(expr_lit) => {
211+
// let value = match &expr_lit.lit {
212+
// syn::Lit::Str(s) => s.value(),
213+
// other => other.to_token_stream().to_string(),
214+
// };
215+
// RsxAttribute::KeyValue { key, value }
216+
// }
217+
// tokens => RsxAttribute::BlockValue {
218+
// key,
219+
// value: quote! {RustParts::AttributeValue(#tokens.to_string())},
220+
// },
221+
// }
222+
// } else {
223+
// RsxAttribute::Key { key }
224+
// }
225+
// }
226+
// }

crates/sweet_rsx/src/parse_rsx/rsx_parser.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use super::RsxFileVisitor;
33
use super::RsxFileVisitorOut;
44
use super::WalkNodesOutput;
55
use proc_macro2::TokenStream;
6-
use sweet_core::rsx::RsxTree;
76
use syn::visit_mut::VisitMut;
87
use syn::Expr;
98
use syn::File;
@@ -54,7 +53,6 @@ impl RsxParser {
5453
let (nodes, rstml_errors) = parse_rstml(tokens.clone());
5554
let mut output = WalkNodesOutput::default();
5655
let nodes = output.visit_nodes(nodes);
57-
let tree = RsxTree::new(nodes);
5856

5957
let WalkNodesOutput {
6058
errors,
@@ -77,7 +75,13 @@ impl RsxParser {
7775
*tokens = syn::parse_quote! {{
7876
use sweet::prelude::*;
7977
#errors
80-
#tree as RsxTree::<RustParts>
78+
79+
#[allow(unused_braces)]
80+
{
81+
RsxTree {
82+
nodes: Vec::from([#(#nodes),*]),
83+
} as RsxTree::<RustParts>
84+
}
8185
}};
8286
Ok(output)
8387
}

0 commit comments

Comments
 (0)