or for now. Sorry for the pain!")
+ } else {
+ _ = expected;
+ panic!("Renderer error. You can find a more detailed error message if you compile in debug mode.")
+ }
+ }
+}
diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs
index c5616b8ce..8efd1b3e4 100644
--- a/leptos_macro/src/lib.rs
+++ b/leptos_macro/src/lib.rs
@@ -244,6 +244,60 @@ pub fn view(tokens: TokenStream) -> TokenStream {
}
}
+/// Annotates a function so that it can be used with your template as a
+///
+/// Here are some things you should know.
+/// 1. The component name should be `CamelCase` instead of `snake_case`. This is how the renderer
+/// recognizes that a particular tag is a component, not an HTML element.
+///
+/// ```
+/// # use leptos::*;
+/// // ❌ not snake_case
+/// #[component]
+/// fn my_component(cx: Scope) -> Element { todo!() }
+///
+/// // ✅ CamelCase
+/// #[component]
+/// fn MyComponent(cx: Scope) -> Element { todo!() }
+/// ```
+///
+/// 2. The macro generates a type `ComponentProps` for every `Component` (so, `HomePage` generates `HomePageProps`,
+/// `Button` generates `ButtonProps`, etc.) When you’re importing the component, you also need to **explicitly import
+/// the prop type.**
+///
+/// ```
+/// # use leptos::*;
+///
+/// use component::{MyComponent, MyComponentProps};
+///
+/// mod component {
+/// use leptos::*;
+///
+/// #[component]
+/// pub fn MyComponent(cx: Scope) -> Element { todo!() }
+/// }
+/// ```
+///
+/// 3. You can pass generic arguments, but they should be defined in a `where` clause and not inline.
+///
+/// ```compile_error
+/// # use leptos::*;
+/// #[component]
+/// fn MyComponent Element>(cx: Scope, render_prop: T) -> Element {
+/// todo!()
+/// }
+/// ```
+///
+/// ```
+/// # use leptos::*;
+/// #[component]
+/// fn MyComponent(cx: Scope, render_prop: T) -> Element
+/// where
+/// T: Fn() -> Element,
+/// {
+/// todo!()
+/// }
+/// ```
#[proc_macro_attribute]
pub fn component(_args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
match syn::parse::(s) {
diff --git a/leptos_macro/src/view.rs b/leptos_macro/src/view.rs
index 56bc18a90..3de95801a 100644
--- a/leptos_macro/src/view.rs
+++ b/leptos_macro/src/view.rs
@@ -383,14 +383,14 @@ fn element_to_tokens(
quote_spanned! {
span => let #this_el_ident = #debug_name;
//log::debug!("next_sibling ({})", #debug_name);
- let #this_el_ident = #prev_sib.next_sibling().unwrap_throw();
+ let #this_el_ident = #prev_sib.next_sibling().unwrap_or_else(|| ::leptos::__leptos_renderer_error(#debug_name, "nextSibling"));
//log::debug!("=> got {}", #this_el_ident.node_name());
}
} else {
quote_spanned! {
span => let #this_el_ident = #debug_name;
//log::debug!("first_child ({})", #debug_name);
- let #this_el_ident = #parent.first_child().unwrap_throw();
+ let #this_el_ident = #parent.first_child().unwrap_or_else(|| ::leptos::__leptos_renderer_error(#debug_name, "firstChild"));
//log::debug!("=> got {}", #this_el_ident.node_name());
}
};
@@ -816,13 +816,13 @@ fn block_to_tokens(
let location = if let Some(sibling) = &prev_sib {
quote_spanned! {
span => //log::debug!("-> next sibling");
- let #name = #sibling.next_sibling().unwrap_throw();
+ let #name = #sibling.next_sibling().unwrap_or_else(|| ::leptos::__leptos_renderer_error("{block}", "nextSibling"));
//log::debug!("\tnext sibling = {}", #name.node_name());
}
} else {
quote_spanned! {
span => //log::debug!("\\|/ first child on {}", #parent.node_name());
- let #name = #parent.first_child().unwrap_throw();
+ let #name = #parent.first_child().unwrap_or_else(|| ::leptos::__leptos_renderer_error("{block}", "firstChild"));
//log::debug!("\tfirst child = {}", #name.node_name());
}
};
@@ -938,6 +938,8 @@ fn component_to_tokens(
mode: Mode,
is_first_child: bool,
) -> PrevSibChange {
+ let component_name = ident_from_tag_name(&node.name);
+ let component_name = format!("<{component_name}/>");
let create_component = create_component(cx, node, mode);
let span = node.name.span();
@@ -974,13 +976,13 @@ fn component_to_tokens(
let starts_at = if let Some(prev_sib) = prev_sib {
quote::quote! {{
//log::debug!("starts_at = next_sibling");
- #prev_sib.next_sibling().unwrap_throw()
+ #prev_sib.next_sibling().unwrap_or_else(|| ::leptos::__leptos_renderer_error(#component_name, "nextSibling"))
//log::debug!("ok starts_at");
}}
} else {
quote::quote! {{
//log::debug!("starts_at first_child");
- #parent.first_child().unwrap_throw()
+ #parent.first_child().unwrap_or_else(|| ::leptos::__leptos_renderer_error(#component_name, "firstChild"))
//log::debug!("starts_at ok");
}}
};