Skip to content

Commit d1333a3

Browse files
committed
modify component attribute macro to allow snake_case fn names
1 parent 7fb7bb9 commit d1333a3

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ blob.rs
66
Cargo.lock
77
**/*.rs.bk
88
.DS_Store
9+
.idea

leptos/tests/ssr.rs

+34
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,40 @@ fn ssr_test_with_components() {
5555
});
5656
}
5757

58+
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
59+
#[test]
60+
fn ssr_test_with_snake_case_components() {
61+
use leptos::*;
62+
63+
#[component]
64+
fn snake_case_counter(cx: Scope, initial_value: i32) -> impl IntoView {
65+
let (value, set_value) = create_signal(cx, initial_value);
66+
view! {
67+
cx,
68+
<div>
69+
<button on:click=move |_| set_value.update(|value| *value -= 1)>"-1"</button>
70+
<span>"Value: " {move || value.get().to_string()} "!"</span>
71+
<button on:click=move |_| set_value.update(|value| *value += 1)>"+1"</button>
72+
</div>
73+
}
74+
}
75+
76+
_ = create_scope(create_runtime(), |cx| {
77+
let rendered = view! {
78+
cx,
79+
<div class="counters">
80+
<SnakeCaseCounter initial_value=1/>
81+
<SnakeCaseCounter initial_value=2/>
82+
</div>
83+
};
84+
85+
assert_eq!(
86+
rendered.into_view(cx).render_to_string(cx),
87+
"<div id=\"_0-1\" class=\"counters\"><!--hk=_0-1-0o|leptos-snake-case-counter-start--><div id=\"_0-1-1\"><button id=\"_0-1-2\">-1</button><span id=\"_0-1-3\">Value: <!--hk=_0-1-4o|leptos-dyn-child-start-->1<!--hk=_0-1-4c|leptos-dyn-child-end-->!</span><button id=\"_0-1-5\">+1</button></div><!--hk=_0-1-0c|leptos-snake-case-counter-end--><!--hk=_0-1-5-0o|leptos-snake-case-counter-start--><div id=\"_0-1-5-1\"><button id=\"_0-1-5-2\">-1</button><span id=\"_0-1-5-3\">Value: <!--hk=_0-1-5-4o|leptos-dyn-child-start-->2<!--hk=_0-1-5-4c|leptos-dyn-child-end-->!</span><button id=\"_0-1-5-5\">+1</button></div><!--hk=_0-1-5-0c|leptos-snake-case-counter-end--></div>"
88+
);
89+
});
90+
}
91+
5892
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
5993
#[test]
6094
fn test_classes() {

leptos_macro/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ leptos_dom = { workspace = true }
2727
leptos_reactive = { workspace = true }
2828
leptos_server = { workspace = true }
2929
lazy_static = "1.4"
30+
convert_case = "0.6.0"
3031

3132
[dev-dependencies]
3233
log = "0.4"

leptos_macro/src/component.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use convert_case::{Case::{Snake, Pascal}, Casing};
12
use itertools::Itertools;
23
use proc_macro2::{Ident, TokenStream};
34
use quote::{format_ident, ToTokens, TokenStreamExt};
@@ -75,7 +76,7 @@ impl Parse for Model {
7576
is_transparent: false,
7677
docs,
7778
vis: item.vis.clone(),
78-
name: item.sig.ident.clone(),
79+
name: convert_from_snake_case(&item.sig.ident),
7980
scope_name,
8081
props,
8182
ret: item.sig.output.clone(),
@@ -97,6 +98,15 @@ fn drain_filter<T>(vec: &mut Vec<T>, mut some_predicate: impl FnMut(&mut T) -> b
9798
}
9899
}
99100

101+
fn convert_from_snake_case(name: &Ident) -> Ident {
102+
let name_str = name.to_string();
103+
if !name_str.is_case(Snake) {
104+
name.clone()
105+
} else {
106+
Ident::new(&*name_str.to_case(Pascal), name.span().clone())
107+
}
108+
}
109+
100110
impl ToTokens for Model {
101111
fn to_tokens(&self, tokens: &mut TokenStream) {
102112
let Self {

0 commit comments

Comments
 (0)