Disambiguate expressions in rsx by requiring curlies
This commit is contained in:
53 files changed
+399
-373
No files matched your search
@@ -1,11 +1,11 @@
|
||||
use dioxus_rsx::{AttributeType, BodyNode, ElementAttrValue, ForLoop};
|
||||
use dioxus_rsx::{AttributeType, BodyNode, ElementAttrValue, ForLoop, IfChain};
|
||||
use proc_macro2::{LineColumn, Span};
|
||||
use quote::ToTokens;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
fmt::{Result, Write},
|
||||
};
|
||||
use syn::{spanned::Spanned, Expr, ExprIf};
|
||||
use syn::{spanned::Spanned, Expr};
|
||||
|
||||
use crate::buffer::Buffer;
|
||||
use crate::ifmt_to_string;
|
||||
@@ -231,8 +231,9 @@ impl<'a> Writer<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_if_chain(&mut self, ifchain: &ExprIf) -> std::fmt::Result {
|
||||
self.write_raw_expr(ifchain.span())
|
||||
fn write_if_chain(&mut self, ifchain: &IfChain) -> std::fmt::Result {
|
||||
todo!()
|
||||
// self.write_raw_expr(ifchain.span())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ fn create() {
|
||||
fn create_list() {
|
||||
let mut dom = VirtualDom::new(|cx| {
|
||||
cx.render(rsx! {
|
||||
(0..3).map(|f| rsx!( div { "hello" } ))
|
||||
{(0..3).map(|f| rsx!( div { "hello" } ))}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ fn create_components() {
|
||||
fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
|
||||
cx.render(rsx! {
|
||||
h1 {}
|
||||
div { &cx.props.children }
|
||||
div { {&cx.props.children} }
|
||||
p {}
|
||||
})
|
||||
}
|
||||
@@ -163,10 +163,10 @@ fn anchors() {
|
||||
let mut dom = VirtualDom::new(|cx| {
|
||||
cx.render(rsx! {
|
||||
if true {
|
||||
rsx!( div { "hello" } )
|
||||
div { "hello" }
|
||||
}
|
||||
if false {
|
||||
rsx!( div { "goodbye" } )
|
||||
div { "goodbye" }
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ use dioxus_core::ElementId;
|
||||
#[test]
|
||||
fn empty_fragment_creates_nothing() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx!(()))
|
||||
cx.render(rsx!({ () }))
|
||||
}
|
||||
|
||||
let mut vdom = VirtualDom::new(app);
|
||||
@@ -43,18 +43,18 @@ fn fragments_nested() {
|
||||
cx.render(rsx!(
|
||||
div { "hello" }
|
||||
div { "goodbye" }
|
||||
rsx! {
|
||||
{rsx! {
|
||||
div { "hello" }
|
||||
div { "goodbye" }
|
||||
rsx! {
|
||||
{rsx! {
|
||||
div { "hello" }
|
||||
div { "goodbye" }
|
||||
rsx! {
|
||||
{rsx! {
|
||||
div { "hello" }
|
||||
div { "goodbye" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
))
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ fn fragments_across_components() {
|
||||
let world = "world";
|
||||
cx.render(rsx! {
|
||||
"hellO!"
|
||||
world
|
||||
{world}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ fn list_fragments() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx!(
|
||||
h1 {"hello"}
|
||||
(0..6).map(|f| rsx!( span { "{f}" }))
|
||||
{(0..6).map(|f| rsx!( span { "{f}" }))}
|
||||
))
|
||||
}
|
||||
assert_eq!(
|
||||
|
||||
@@ -11,12 +11,12 @@ use dioxus_core::ElementId;
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
(0..3).map(|i| rsx! {
|
||||
for i in 0..3 {
|
||||
div {
|
||||
h1 { "hello world! "}
|
||||
p { "{i}" }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ fn nested_passthru_creates() {
|
||||
|
||||
#[component]
|
||||
fn PassThru<'a>(cx: Scope<'a>, children: Element<'a>) -> Element {
|
||||
cx.render(rsx!(children))
|
||||
cx.render(rsx!({ children }))
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(App);
|
||||
@@ -60,7 +60,7 @@ fn nested_passthru_creates_add() {
|
||||
|
||||
#[component]
|
||||
fn ChildComp<'a>(cx: Scope, children: Element<'a>) -> Element {
|
||||
cx.render(rsx! { children })
|
||||
cx.render(rsx! { {children} })
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(App);
|
||||
|
||||
@@ -41,7 +41,7 @@ fn component_swap() {
|
||||
cx.render(rsx! {
|
||||
h1 {
|
||||
"NavBar"
|
||||
(0..3).map(|_| rsx!(nav_link {}))
|
||||
{(0..3).map(|_| rsx!(nav_link {}))}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ fn keyed_diffing_out_of_order() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
{
|
||||
@@ -59,7 +59,7 @@ fn keyed_diffing_out_of_order_adds() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -85,7 +85,7 @@ fn keyed_diffing_out_of_order_adds_3() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -111,7 +111,7 @@ fn keyed_diffing_out_of_order_adds_4() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -137,7 +137,7 @@ fn keyed_diffing_out_of_order_adds_5() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -162,7 +162,7 @@ fn keyed_diffing_additions() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -187,7 +187,7 @@ fn keyed_diffing_additions_and_moves_on_ends() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -216,7 +216,7 @@ fn keyed_diffing_additions_and_moves_in_middle() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -250,7 +250,7 @@ fn controlled_keyed_diffing_out_of_order() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -284,7 +284,7 @@ fn controlled_keyed_diffing_out_of_order_max_test() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -313,7 +313,7 @@ fn remove_list() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
@@ -338,7 +338,7 @@ fn no_common_keys() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
|
||||
cx.render(rsx!({ order.iter().map(|i| rsx!(div { key: "{i}" })) }))
|
||||
});
|
||||
|
||||
_ = dom.rebuild();
|
||||
|
||||
@@ -9,9 +9,9 @@ fn list_creates_one_by_one() {
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
(0..gen).map(|i| rsx! {
|
||||
for i in 0..gen {
|
||||
div { "{i}" }
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -78,9 +78,9 @@ fn removes_one_by_one() {
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
(0..gen).map(|i| rsx! {
|
||||
for i in 0..gen {
|
||||
div { "{i}" }
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -153,10 +153,10 @@ fn list_shrink_multiroot() {
|
||||
let mut dom = VirtualDom::new(|cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
(0..cx.generation()).map(|i| rsx! {
|
||||
for i in 0..cx.generation() {
|
||||
div { "{i}" }
|
||||
div { "{i}" }
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -214,10 +214,10 @@ fn removes_one_by_one_multiroot() {
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
(0..gen).map(|i| rsx! {
|
||||
{(0..gen).map(|i| rsx! {
|
||||
div { "{i}" }
|
||||
div { "{i}" }
|
||||
})
|
||||
})}
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -276,9 +276,9 @@ fn removes_one_by_one_multiroot() {
|
||||
fn two_equal_fragments_are_equal_static() {
|
||||
let mut dom = VirtualDom::new(|cx| {
|
||||
cx.render(rsx! {
|
||||
(0..5).map(|_| rsx! {
|
||||
for _ in 0..5 {
|
||||
div { "hello" }
|
||||
})
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -290,9 +290,9 @@ fn two_equal_fragments_are_equal_static() {
|
||||
fn two_equal_fragments_are_equal() {
|
||||
let mut dom = VirtualDom::new(|cx| {
|
||||
cx.render(rsx! {
|
||||
(0..5).map(|i| rsx! {
|
||||
for i in 0..5 {
|
||||
div { "hello {i}" }
|
||||
})
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -311,7 +311,9 @@ fn remove_many() {
|
||||
};
|
||||
|
||||
cx.render(rsx! {
|
||||
(0..num).map(|i| rsx! { div { "hello {i}" } })
|
||||
for i in 0..num {
|
||||
div { "hello {i}" }
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ fn app(cx: Scope) -> Element {
|
||||
*CLICKS.lock().unwrap() += 1;
|
||||
},
|
||||
|
||||
vec![
|
||||
{vec![
|
||||
render! {
|
||||
problematic_child {}
|
||||
}
|
||||
].into_iter()
|
||||
].into_iter()}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ fn events_generate() {
|
||||
"Click me!"
|
||||
}
|
||||
}),
|
||||
_ => cx.render(rsx!(())),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ fn App(cx: Scope) -> Element {
|
||||
}
|
||||
button { onclick: move |_| idx -= 1, "-" }
|
||||
ul {
|
||||
(0..**idx).map(|i| rsx! {
|
||||
{(0..**idx).map(|i| rsx! {
|
||||
ChildExample { i: i, onhover: onhover }
|
||||
})
|
||||
})}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ fn test_memory_leak() {
|
||||
cx.spawn(async {});
|
||||
|
||||
if val == 2 || val == 4 {
|
||||
return cx.render(rsx!(()));
|
||||
return None;
|
||||
}
|
||||
|
||||
let name = cx.use_hook(|| String::from("numbers: "));
|
||||
@@ -73,7 +73,7 @@ fn memo_works_properly() {
|
||||
let val = cx.generation();
|
||||
|
||||
if val == 2 || val == 4 {
|
||||
return cx.render(rsx!(()));
|
||||
return None;
|
||||
}
|
||||
|
||||
let name = cx.use_hook(|| String::from("asd"));
|
||||
|
||||
@@ -25,7 +25,7 @@ async fn it_works() {
|
||||
});
|
||||
});
|
||||
|
||||
cx.render(rsx!(()))
|
||||
None
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
|
||||
@@ -89,7 +89,7 @@ fn check_html_renders(cx: Scope) -> Element {
|
||||
h1 {
|
||||
"text"
|
||||
}
|
||||
dyn_element
|
||||
{dyn_element}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ fn app(cx: Scope) -> Element {
|
||||
|
||||
"Hover, click, type or scroll to see the info down below"
|
||||
}
|
||||
div { width: "80%", height: "50%", flex_direction: "column", events_rendered }
|
||||
div { width: "80%", height: "50%", flex_direction: "column", {events_rendered} }
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -27,26 +27,25 @@ fn Button(cx: Scope<ButtonProps>) -> Element {
|
||||
height: "100%",
|
||||
background_color: "{color}",
|
||||
tabindex: "{cx.props.layer}",
|
||||
onkeydown: |e| {
|
||||
onkeydown: move |e| {
|
||||
if let Code::Space = e.inner().code() {
|
||||
toggle.modify(|f| !f);
|
||||
}
|
||||
},
|
||||
onclick: |_| {
|
||||
onclick: move |_| {
|
||||
toggle.modify(|f| !f);
|
||||
},
|
||||
onmouseenter: |_|{
|
||||
onmouseenter: move |_| {
|
||||
hovered.set(true);
|
||||
},
|
||||
onmouseleave: |_|{
|
||||
onmouseleave: move |_|{
|
||||
hovered.set(false);
|
||||
},
|
||||
justify_content: "center",
|
||||
align_items: "center",
|
||||
display: "flex",
|
||||
flex_direction: "column",
|
||||
|
||||
p{"tabindex: {cx.props.layer}"}
|
||||
p{ "tabindex: {cx.props.layer}" }
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -58,37 +57,28 @@ fn app(cx: Scope) -> Element {
|
||||
flex_direction: "column",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
||||
(1..8).map(|y|
|
||||
rsx!{
|
||||
div{
|
||||
display: "flex",
|
||||
flex_direction: "row",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
(1..8).map(|x|{
|
||||
if (x + y) % 2 == 0{
|
||||
rsx!{
|
||||
div{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
background_color: "rgb(100, 100, 100)",
|
||||
}
|
||||
}
|
||||
for y in 1..8 {
|
||||
div {
|
||||
display: "flex",
|
||||
flex_direction: "row",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
for x in 1..8 {
|
||||
if (x + y) % 2 == 0 {
|
||||
div {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
background_color: "rgb(100, 100, 100)",
|
||||
}
|
||||
else{
|
||||
let layer = (x + y) % 3;
|
||||
rsx!{
|
||||
Button{
|
||||
color_offset: x * y,
|
||||
layer: layer as u16,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Button {
|
||||
color_offset: x * y,
|
||||
layer: ((x + y) % 3) as u16,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -14,32 +14,25 @@ fn app(cx: Scope) -> Element {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
flex_direction: "column",
|
||||
(0..=steps).map(|x|
|
||||
{
|
||||
let hue = x as f32*360.0/steps as f32;
|
||||
rsx! {
|
||||
div{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
flex_direction: "row",
|
||||
(0..=steps).map(|y|
|
||||
{
|
||||
let alpha = y as f32*100.0/steps as f32;
|
||||
rsx! {
|
||||
div {
|
||||
left: "{x}px",
|
||||
top: "{y}px",
|
||||
width: "10%",
|
||||
height: "100%",
|
||||
background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
|
||||
}
|
||||
}
|
||||
for x in 0..=steps {
|
||||
div { width: "100%", height: "100%", flex_direction: "row",
|
||||
for y in 0..=steps {
|
||||
{
|
||||
let hue = x as f32*360.0/steps as f32;
|
||||
let alpha = y as f32*100.0/steps as f32;
|
||||
rsx! {
|
||||
div {
|
||||
left: "{x}px",
|
||||
top: "{y}px",
|
||||
width: "10%",
|
||||
height: "100%",
|
||||
background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -19,9 +19,9 @@ fn app(cx: Scope) -> Element {
|
||||
ul {
|
||||
flex_direction: "column",
|
||||
padding_left: "3px",
|
||||
(0..10).map(|i| rsx!(
|
||||
for i in 0..10 {
|
||||
"> hello {i}"
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -71,32 +71,28 @@ fn Grid(cx: Scope<GridProps>) -> Element {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
flex_direction: "column",
|
||||
(0..size).map(|x|
|
||||
{
|
||||
rsx! {
|
||||
div{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
flex_direction: "row",
|
||||
(0..size).map(|y|
|
||||
{
|
||||
let alpha = y as f32*100.0/size as f32 + counts.read()[x*size + y] as f32;
|
||||
let key = format!("{}-{}", x, y);
|
||||
rsx! {
|
||||
Box {
|
||||
x: x,
|
||||
y: y,
|
||||
alpha: 100.0,
|
||||
hue: alpha,
|
||||
key: "{key}",
|
||||
}
|
||||
}
|
||||
for x in 0..size {
|
||||
div{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
flex_direction: "row",
|
||||
for y in 0..size {
|
||||
{
|
||||
let alpha = y as f32*100.0/size as f32 + counts.read()[x*size + y] as f32;
|
||||
let key = format!("{}-{}", x, y);
|
||||
rsx! {
|
||||
Box {
|
||||
x: x,
|
||||
y: y,
|
||||
alpha: 100.0,
|
||||
hue: alpha,
|
||||
key: "{key}",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@ fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx! (
|
||||
table {
|
||||
tbody {
|
||||
(0..10_000_usize).map(|f| {
|
||||
let label = Label::new(&mut rng);
|
||||
rsx!( table_row { row_id: f, label: label } )
|
||||
})
|
||||
for f in 0..10_000_usize {
|
||||
table_row {
|
||||
row_id: f,
|
||||
label: Label::new(&mut rng)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
|
||||
@@ -306,15 +306,10 @@ fn persist_removes() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
render!(
|
||||
div{
|
||||
(0..children).map(|i|{
|
||||
rsx!{
|
||||
p{
|
||||
key: "{i}",
|
||||
"{i}"
|
||||
}
|
||||
}
|
||||
})
|
||||
div {
|
||||
for i in 0..children {
|
||||
p { key: "{i}", "{i}" }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -387,15 +382,10 @@ fn persist_instertions_before() {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
render!(
|
||||
div{
|
||||
(0..children).map(|i|{
|
||||
rsx!{
|
||||
p{
|
||||
key: "{i}",
|
||||
"{i}"
|
||||
}
|
||||
}
|
||||
})
|
||||
div {
|
||||
for i in 0..children {
|
||||
p { key: "{i}", "{i}" }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -446,14 +436,9 @@ fn persist_instertions_after() {
|
||||
};
|
||||
render!(
|
||||
div{
|
||||
(0..children).map(|i|{
|
||||
rsx!{
|
||||
p{
|
||||
key: "{i}",
|
||||
"{i}"
|
||||
}
|
||||
}
|
||||
})
|
||||
for i in 0..children {
|
||||
p { key: "{i}", "{i}" }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ fn Route1(cx: Scope, user_id: usize, dynamic: usize, query: String, extra: Strin
|
||||
fn Route2(cx: Scope, user_id: usize) -> Element {
|
||||
render! {
|
||||
pre { "Route2{{\n\tuser_id:{user_id}\n}}" }
|
||||
(0..*user_id).map(|i| rsx!{ p { "{i}" } }),
|
||||
{(0..*user_id).map(|i| rsx!{ p { "{i}" } })},
|
||||
p { "Footer" }
|
||||
Link {
|
||||
to: Route::Route3 {
|
||||
|
||||
@@ -77,7 +77,7 @@ pub fn GoBackButton<'a>(cx: Scope<'a, HistoryButtonProps<'a>>) -> Element {
|
||||
disabled: "{disabled}",
|
||||
prevent_default: "onclick",
|
||||
onclick: move |_| router.go_back(),
|
||||
children
|
||||
{children}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ pub fn GoForwardButton<'a>(cx: Scope<'a, HistoryButtonProps<'a>>) -> Element {
|
||||
disabled: "{disabled}",
|
||||
prevent_default: "onclick",
|
||||
onclick: move |_| router.go_forward(),
|
||||
children
|
||||
{children}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ impl Debug for LinkProps<'_> {
|
||||
/// new_tab: true,
|
||||
/// rel: "link_rel",
|
||||
/// to: Route::Index {},
|
||||
///
|
||||
///
|
||||
/// "A fully configured link"
|
||||
/// }
|
||||
/// }
|
||||
@@ -250,7 +250,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
|
||||
id: "{id}",
|
||||
rel: "{rel}",
|
||||
target: "{tag_target}",
|
||||
children
|
||||
{children}
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
-66
@@ -6,7 +6,8 @@ use syn::{
|
||||
braced,
|
||||
parse::{Parse, ParseStream},
|
||||
spanned::Spanned,
|
||||
token, Expr, ExprIf, LitStr, Pat, Result,
|
||||
token::{self, Brace},
|
||||
Expr, ExprIf, LitStr, Pat, Result,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -15,14 +16,14 @@ Parse
|
||||
-> Component {}
|
||||
-> component()
|
||||
-> "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 curly braces
|
||||
*/
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub enum BodyNode {
|
||||
Element(Element),
|
||||
Component(Component),
|
||||
ForLoop(ForLoop),
|
||||
IfChain(ExprIf),
|
||||
IfChain(IfChain),
|
||||
Text(IfmtInput),
|
||||
RawExpr(Expr),
|
||||
}
|
||||
@@ -112,7 +113,27 @@ impl Parse for BodyNode {
|
||||
return Ok(BodyNode::IfChain(stream.parse()?));
|
||||
}
|
||||
|
||||
Ok(BodyNode::RawExpr(stream.parse::<Expr>()?))
|
||||
// Match statements are special but have no special arm syntax
|
||||
// we could allow arm syntax if we wanted
|
||||
//
|
||||
// ```
|
||||
// match {
|
||||
// val => div {}
|
||||
// other_val => div {}
|
||||
// }
|
||||
// ```
|
||||
if stream.peek(Token![match]) {
|
||||
return Ok(BodyNode::RawExpr(stream.parse::<Expr>()?));
|
||||
}
|
||||
|
||||
if stream.peek(token::Brace) {
|
||||
return Ok(BodyNode::RawExpr(stream.parse::<Expr>()?));
|
||||
}
|
||||
|
||||
Err(syn::Error::new(
|
||||
stream.span(),
|
||||
"Expected a valid body node.\nExpressions must be wrapped in curly braces.",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,71 +172,52 @@ impl ToTokens for BodyNode {
|
||||
})
|
||||
}
|
||||
BodyNode::IfChain(chain) => {
|
||||
if is_if_chain_terminated(chain) {
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes = (#chain).into_dyn_node(__cx);
|
||||
___nodes
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let ExprIf {
|
||||
let mut body = TokenStream2::new();
|
||||
let mut terminated = false;
|
||||
|
||||
let mut elif = Some(chain);
|
||||
|
||||
while let Some(chain) = elif {
|
||||
let IfChain {
|
||||
if_token,
|
||||
cond,
|
||||
then_branch,
|
||||
else_if_branch,
|
||||
else_branch,
|
||||
..
|
||||
} = chain;
|
||||
|
||||
let mut body = TokenStream2::new();
|
||||
let mut renderer: TemplateRenderer = TemplateRenderer {
|
||||
roots: then_branch,
|
||||
location: None,
|
||||
};
|
||||
|
||||
body.append_all(quote! {
|
||||
if #cond {
|
||||
Some(#then_branch)
|
||||
}
|
||||
});
|
||||
body.append_all(quote! { #if_token #cond { Some({#renderer}) } });
|
||||
|
||||
let mut elif = else_branch;
|
||||
|
||||
while let Some((_, ref branch)) = elif {
|
||||
match branch.as_ref() {
|
||||
Expr::If(ref eelif) => {
|
||||
let ExprIf {
|
||||
cond,
|
||||
then_branch,
|
||||
else_branch,
|
||||
..
|
||||
} = eelif;
|
||||
|
||||
body.append_all(quote! {
|
||||
else if #cond {
|
||||
Some(#then_branch)
|
||||
}
|
||||
});
|
||||
|
||||
elif = else_branch;
|
||||
}
|
||||
_ => {
|
||||
body.append_all(quote! {
|
||||
else {
|
||||
#branch
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(next) = else_if_branch {
|
||||
body.append_all(quote! { else });
|
||||
elif = Some(next);
|
||||
} else if let Some(else_branch) = else_branch {
|
||||
renderer.roots = else_branch;
|
||||
body.append_all(quote! { else { Some({#renderer}) } });
|
||||
terminated = true;
|
||||
break;
|
||||
} else {
|
||||
elif = None;
|
||||
}
|
||||
}
|
||||
|
||||
if !terminated {
|
||||
body.append_all(quote! {
|
||||
else { None }
|
||||
});
|
||||
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes = (#body).into_dyn_node(__cx);
|
||||
___nodes
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
tokens.append_all(quote! {
|
||||
{
|
||||
let ___nodes = (#body).into_dyn_node(__cx);
|
||||
___nodes
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,26 +242,73 @@ impl Parse for ForLoop {
|
||||
let in_token: Token![in] = input.parse()?;
|
||||
let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
|
||||
|
||||
let content;
|
||||
let brace_token = braced!(content in input);
|
||||
|
||||
let mut children = vec![];
|
||||
|
||||
while !content.is_empty() {
|
||||
children.push(content.parse()?);
|
||||
}
|
||||
let (brace_token, body) = parse_buffer_as_braced_children(input)?;
|
||||
|
||||
Ok(Self {
|
||||
for_token,
|
||||
pat,
|
||||
in_token,
|
||||
body: children,
|
||||
expr: Box::new(expr),
|
||||
body,
|
||||
brace_token,
|
||||
expr: Box::new(expr),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub struct IfChain {
|
||||
pub if_token: Token![if],
|
||||
pub cond: Box<Expr>,
|
||||
pub then_branch: Vec<BodyNode>,
|
||||
pub else_if_branch: Option<Box<IfChain>>,
|
||||
pub else_branch: Option<Vec<BodyNode>>,
|
||||
}
|
||||
|
||||
impl Parse for IfChain {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let if_token: Token![if] = input.parse()?;
|
||||
|
||||
// stolen from ExprIf
|
||||
let cond = Box::new(input.call(Expr::parse_without_eager_brace)?);
|
||||
|
||||
let (_, then_branch) = parse_buffer_as_braced_children(input)?;
|
||||
|
||||
let mut else_branch = None;
|
||||
let mut else_if_branch = None;
|
||||
|
||||
// if the next token is `else`, set the else branch as the next if chain
|
||||
if input.peek(Token![else]) {
|
||||
input.parse::<Token![else]>()?;
|
||||
if input.peek(Token![if]) {
|
||||
else_if_branch = Some(Box::new(input.parse::<IfChain>()?));
|
||||
} else {
|
||||
let (_, else_branch_nodes) = parse_buffer_as_braced_children(input)?;
|
||||
else_branch = Some(else_branch_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
cond,
|
||||
if_token,
|
||||
then_branch,
|
||||
else_if_branch,
|
||||
else_branch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_buffer_as_braced_children(
|
||||
input: &syn::parse::ParseBuffer<'_>,
|
||||
) -> Result<(Brace, Vec<BodyNode>)> {
|
||||
let content;
|
||||
let brace_token = braced!(content in input);
|
||||
let mut then_branch = vec![];
|
||||
while !content.is_empty() {
|
||||
then_branch.push(content.parse()?);
|
||||
}
|
||||
Ok((brace_token, then_branch))
|
||||
}
|
||||
|
||||
pub(crate) fn is_if_chain_terminated(chain: &ExprIf) -> bool {
|
||||
let mut current = chain;
|
||||
loop {
|
||||
|
||||
@@ -242,7 +242,9 @@ fn to_string_works() {
|
||||
div {}
|
||||
div { "nest 2" }
|
||||
"{dyn2}"
|
||||
(0..5).map(|i| rsx! { div { "finalize {i}" } })
|
||||
for i in (0..5) {
|
||||
div { "finalize {i}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ fn text_nodes() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
let dynamic_text = "hello";
|
||||
render! {
|
||||
div { dynamic_text }
|
||||
div { {dynamic_text} }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ fn components_hydrate() {
|
||||
fn Child2(cx: Scope) -> Element {
|
||||
let dyn_text = "hello";
|
||||
render! {
|
||||
div { dyn_text }
|
||||
div { {dyn_text} }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,11 +159,7 @@ fn components_hydrate() {
|
||||
fn Child4(cx: Scope) -> Element {
|
||||
render! {
|
||||
for _ in 0..2 {
|
||||
render! {
|
||||
render! {
|
||||
"{1}"
|
||||
}
|
||||
}
|
||||
{render! { "{1}" }}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ fn lists() {
|
||||
assert_eq!(
|
||||
dioxus_ssr::render_lazy(rsx! {
|
||||
ul {
|
||||
(0..5).map(|i| rsx! {
|
||||
for i in 0..5 {
|
||||
li { "item {i}" }
|
||||
})
|
||||
}
|
||||
}
|
||||
}),
|
||||
"<ul><li>item 0</li><li>item 1</li><li>item 2</li><li>item 3</li><li>item 4</li></ul>"
|
||||
@@ -53,9 +53,9 @@ fn components() {
|
||||
assert_eq!(
|
||||
dioxus_ssr::render_lazy(rsx! {
|
||||
div {
|
||||
(0..5).map(|name| rsx! {
|
||||
for name in 0..5 {
|
||||
MyComponent { name: name }
|
||||
})
|
||||
}
|
||||
}
|
||||
}),
|
||||
"<div><div>component 0</div><div>component 1</div><div>component 2</div><div>component 3</div><div>component 4</div></div>"
|
||||
@@ -67,7 +67,9 @@ fn fragments() {
|
||||
assert_eq!(
|
||||
dioxus_ssr::render_lazy(rsx! {
|
||||
div {
|
||||
(0..5).map(|_| rsx! (()))
|
||||
for _ in 0..5 {
|
||||
{()}
|
||||
}
|
||||
}
|
||||
}),
|
||||
"<div></div>"
|
||||
|
||||
@@ -12,11 +12,11 @@ fn app(cx: Scope) -> Element {
|
||||
"asd"
|
||||
Bapp {}
|
||||
}
|
||||
(0..10).map(|f| rsx!{
|
||||
{(0..10).map(|f| rsx!{
|
||||
div {
|
||||
"thing {f}"
|
||||
}
|
||||
})
|
||||
})}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,11 @@ fn app(cx: Scope) -> Element {
|
||||
start();
|
||||
*count.write() += 1;
|
||||
},
|
||||
// format is needed as {count} does not seemed to work in `if` within content
|
||||
if **started { format!("Current score: {}", count.write()) } else { "Start".to_string() }
|
||||
if **started {
|
||||
"Current score: {count.read()}"
|
||||
} else {
|
||||
"Start"
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -43,7 +43,7 @@ fn rehydrates() {
|
||||
},
|
||||
"listener test"
|
||||
}
|
||||
false.then(|| rsx!{ "hello" })
|
||||
{false.then(|| rsx!{ "hello" })}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user