diff --git a/.gitignore b/.gitignore
index fbe21a7..d6359fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ blob.rs
Cargo.lock
**/*.rs.bk
.DS_Store
+.idea
diff --git a/leptos/tests/ssr.rs b/leptos/tests/ssr.rs
index d9bdc3d..ddf1bdb 100644
--- a/leptos/tests/ssr.rs
+++ b/leptos/tests/ssr.rs
@@ -55,6 +55,40 @@ fn ssr_test_with_components() {
});
}
+#[cfg(not(any(feature = "csr", feature = "hydrate")))]
+#[test]
+fn ssr_test_with_snake_case_components() {
+ use leptos::*;
+
+ #[component]
+ fn snake_case_counter(cx: Scope, initial_value: i32) -> impl IntoView {
+ let (value, set_value) = create_signal(cx, initial_value);
+ view! {
+ cx,
+
+
+ "Value: " {move || value.get().to_string()} "!"
+
+
+ }
+ }
+
+ _ = create_scope(create_runtime(), |cx| {
+ let rendered = view! {
+ cx,
+
+
+
+
+ };
+
+ assert_eq!(
+ rendered.into_view(cx).render_to_string(cx),
+ "Value: 1!
Value: 2!
"
+ );
+ });
+}
+
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
#[test]
fn test_classes() {
diff --git a/leptos_macro/Cargo.toml b/leptos_macro/Cargo.toml
index 9c3d7d1..61be4d4 100644
--- a/leptos_macro/Cargo.toml
+++ b/leptos_macro/Cargo.toml
@@ -27,6 +27,7 @@ leptos_dom = { workspace = true }
leptos_reactive = { workspace = true }
leptos_server = { workspace = true }
lazy_static = "1.4"
+convert_case = "0.6.0"
[dev-dependencies]
log = "0.4"
diff --git a/leptos_macro/src/component.rs b/leptos_macro/src/component.rs
index d1c5dbd..4678421 100644
--- a/leptos_macro/src/component.rs
+++ b/leptos_macro/src/component.rs
@@ -1,3 +1,4 @@
+use convert_case::{Case::{Snake, Pascal}, Casing};
use itertools::Itertools;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, ToTokens, TokenStreamExt};
@@ -75,7 +76,7 @@ impl Parse for Model {
is_transparent: false,
docs,
vis: item.vis.clone(),
- name: item.sig.ident.clone(),
+ name: convert_from_snake_case(&item.sig.ident),
scope_name,
props,
ret: item.sig.output.clone(),
@@ -97,6 +98,15 @@ fn drain_filter(vec: &mut Vec, mut some_predicate: impl FnMut(&mut T) -> b
}
}
+fn convert_from_snake_case(name: &Ident) -> Ident {
+ let name_str = name.to_string();
+ if !name_str.is_case(Snake) {
+ name.clone()
+ } else {
+ Ident::new(&*name_str.to_case(Pascal), name.span().clone())
+ }
+}
+
impl ToTokens for Model {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self {