diff --git a/.gitignore b/.gitignore
index 84a323e..ea56ff2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
target
**/*.rs.bk
+.DS_Store
\ No newline at end of file
diff --git a/README.md b/README.md
index 8069ce7..d6cf677 100644
--- a/README.md
+++ b/README.md
@@ -11,9 +11,9 @@ XML rendering, but can work with other usages as well, like ReasonML's [`Pastel`
A renderable component is a struct that implements the `Render` trait. There
are multiple macros that provide a better experience implementing Renderable:
-* `#[component]` for defining components using a function
-* `rsx!` for composing elements with JSX ergonomics
-* `html!` for composing elements and render them to a string
+- `#[component]` for defining components using a function
+- `rsx!` for composing elements with JSX ergonomics
+- `html!` for composing elements and render them to a string
## Why is this different from...
@@ -113,10 +113,37 @@ assert_eq!(rendered_html, r#"
Hello world!
"#);
If you pay close attention, you see that the function `Heading` is:
-* declared with an uppercase. Underneath, it generates a struct with the same name, and
-implements the `Render` trait on it.
-* does not have a return type. This is because everything is written to a writer, for
-performance reasons.
+- declared with an uppercase. Underneath, it generates a struct with the same name, and
+ implements the `Render` trait on it.
+- does not have a return type. This is because everything is written to a writer, for
+ performance reasons.
+
+### Visibility & Component Libraries
+
+Often you're going to want to store your components somewhere else in your
+project tree other than the module you're working on (if not in a different
+module entirely!). In these cases, the visibility applied top the function that
+defines your component will flow down into all fields of that struct.
+
+For example, if we add "pub" to the front of our Heading component above:
+
+```rust
+#[component]
+pub fn Heading<'title>(title: &'title str) {
+ rsx! { {title}
}
+}
+```
+
+...the struct that is generated would look something like...
+
+```rust
+pub struct Heading {
+ pub title: &'title str
+}
+```
+
+This is important to understand from a safety point of view when structuring
+your libraries.
#### Full example
diff --git a/render_macros/src/children.rs b/render_macros/src/children.rs
index 8d9feeb..7de0a43 100644
--- a/render_macros/src/children.rs
+++ b/render_macros/src/children.rs
@@ -24,16 +24,19 @@ impl Children {
quote! { #child }
})
.collect();
+
match children_quotes.len() {
0 => quote! { Option::<()>::None },
- 1 => quote! { Some(#(#children_quotes)*) },
+ 1 => quote! { Some(#(#children_quotes),*) },
_ => {
let mut iter = children_quotes.iter();
+
let first = iter.next().unwrap();
let second = iter.next().unwrap();
+
let tuple_of_tuples = iter.fold(
quote!((#first, #second)),
- |renderable, current| quote!((#current, #renderable)),
+ |renderable, current| quote!((#renderable, #current)),
);
quote! { Some(#tuple_of_tuples) }
diff --git a/render_macros/src/function_component.rs b/render_macros/src/function_component.rs
index 261528b..b4d3511 100644
--- a/render_macros/src/function_component.rs
+++ b/render_macros/src/function_component.rs
@@ -10,7 +10,11 @@ pub fn create_function_component(f: syn::ItemFn) -> TokenStream {
let vis = f.vis;
let inputs_block = if inputs.len() > 0 {
- quote!({ #inputs })
+ let input_names: Vec<_> = inputs
+ .iter()
+ .collect();
+
+ quote!({ #(#vis #input_names),* })
} else {
quote!(;)
};
diff --git a/render_tests/src/lib.rs b/render_tests/src/lib.rs
index 63070e0..bf1ced5 100644
--- a/render_tests/src/lib.rs
+++ b/render_tests/src/lib.rs
@@ -20,6 +20,36 @@ pub fn works_with_raw() {
assert_eq!(actual, "
");
}
+#[test]
+pub fn element_ordering() {
+ use pretty_assertions::assert_eq;
+ use render::{html, raw};
+
+ let actual = html! {
+
+ - {"1"}
+ - {"2"}
+ - {"3"}
+
+ };
+
+ assert_eq!(actual, "");
+
+ let deep = html! {
+
+
{"A list"}
+
+
+ - {"1"}
+ - {"2"}
+ - {"3"}
+
+
+ };
+
+ assert_eq!(deep, "");
+}
+
mod kaki {
// A simple HTML 5 doctype declaration
use render::html::HTML5Doctype;
@@ -67,4 +97,57 @@ mod kaki {
);
assert_eq!(actual, expected);
}
+
+ #[test]
+ fn externals_test() {
+ use pretty_assertions::assert_eq;
+ use crate::other::ExternalPage;
+
+ let actual = render::html! {
+
+ {format!("Welcome, {}", "Gal")}
+
+ };
+
+ let expected = concat!(
+ "",
+ "",
+ "Home",
+ "",
+ "Foo
",
+ "Welcome, Gal",
+ "",
+ ""
+ );
+ assert_eq!(actual, expected);
+ }
}
+
+/// ## Other
+///
+/// Module for testing component visibility when imported from other modules.
+
+mod other {
+ use render::html::HTML5Doctype;
+ use render::{ component, rsx, Render };
+
+ #[component]
+ pub fn ExternalPage<'title, 'subtitle, Children: Render>(
+ title: &'title str,
+ subtitle: &'subtitle str,
+ children: Children
+ ) {
+ rsx! {
+ <>
+
+
+ {title}
+
+ {subtitle}
+ {children}
+
+
+ >
+ }
+ }
+}
\ No newline at end of file