377f3108
—
Gal Schlezinger 6 years ago
README
- README.md +61 -0
- render_tests/src/lib.rs +65 -0
README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Render
|
|
2
|
+
|
|
3
|
+
> A simple template engine with the type-safety of Rust and the ergonomics of JSX
|
|
4
|
+
|
|
5
|
+
The `Renderable` trait contains a simple function that returns `String`. This is very handy for type-safe HTML templates, but can also work for writing tree-like terminal coloring mechanism like ReasonML's [Pastel](https://reason-native.com/docs/pastel/).
|
|
6
|
+
|
|
7
|
+
## Why this is different from `typed-html`?
|
|
8
|
+
|
|
9
|
+
`typed-html` is a wonderful library. Unfortunately, it focused its power in strictness of the HTML spec itself, and doesn't allow arbitrary compositions of custom elements.
|
|
10
|
+
|
|
11
|
+
`render` takes a different approach. For now, HTML is not typed at all. It can get any key and get any string value. The main focus is custom components, so you can create a composable and declarative template with no runtime errors.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```rust
|
|
16
|
+
// A simple HTML 5 doctype declaration
|
|
17
|
+
use render::html::HTML5Doctype;
|
|
18
|
+
use render::{
|
|
19
|
+
// A macro to compose components in JSX fashion
|
|
20
|
+
html,
|
|
21
|
+
// A component that just render its children
|
|
22
|
+
Fragment,
|
|
23
|
+
// A trait for custom components
|
|
24
|
+
Renderable,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// This can be any layout we want
|
|
28
|
+
#[derive(Debug)]
|
|
29
|
+
struct Page<'a, T: Renderable> {
|
|
30
|
+
title: &'a str,
|
|
31
|
+
children: T,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Implementing `Renderable` gives the ability to compose
|
|
35
|
+
// components
|
|
36
|
+
impl<'a, T: Renderable> Renderable for Page<'a, T> {
|
|
37
|
+
fn render(self) -> String {
|
|
38
|
+
html! {
|
|
39
|
+
<Fragment>
|
|
40
|
+
<HTML5Doctype />
|
|
41
|
+
<html>
|
|
42
|
+
<head><title>{self.title}</title></head>
|
|
43
|
+
<body>
|
|
44
|
+
{self.children}
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
47
|
+
</Fragment>
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// This can be a route in Rocket, the web framework,
|
|
53
|
+
// for instance.
|
|
54
|
+
pub fn some_page(user_name: &str) -> String {
|
|
55
|
+
html! {
|
|
56
|
+
<Page title={"Home"}>
|
|
57
|
+
{format!("Welcome, {}", user_name)}
|
|
58
|
+
</Page>
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
render_tests/src/lib.rs
CHANGED
|
@@ -44,3 +44,68 @@ pub fn it_works() -> String {
|
|
|
44
44
|
pub fn verify_works() {
|
|
45
45
|
println!("{}", it_works());
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
pub mod readme_code {
|
|
49
|
+
// A simple HTML 5 doctype declaration
|
|
50
|
+
use render::html::HTML5Doctype;
|
|
51
|
+
use render::{
|
|
52
|
+
// A macro to compose components in JSX fashion
|
|
53
|
+
html,
|
|
54
|
+
// A component that just render its children
|
|
55
|
+
Fragment,
|
|
56
|
+
// A trait for custom components
|
|
57
|
+
Renderable,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// This can be any layout we want
|
|
61
|
+
#[derive(Debug)]
|
|
62
|
+
struct Page<'a, T: Renderable> {
|
|
63
|
+
title: &'a str,
|
|
64
|
+
children: T,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Implementing `Renderable` gives the ability to compose
|
|
68
|
+
// components
|
|
69
|
+
impl<'a, T: Renderable> Renderable for Page<'a, T> {
|
|
70
|
+
fn render(self) -> String {
|
|
71
|
+
html! {
|
|
72
|
+
<Fragment>
|
|
73
|
+
<HTML5Doctype />
|
|
74
|
+
<html>
|
|
75
|
+
<head><title>{self.title}</title></head>
|
|
76
|
+
<body>
|
|
77
|
+
{self.children}
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
80
|
+
</Fragment>
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// This can be a route in Rocket, the web framework,
|
|
86
|
+
// for instance.
|
|
87
|
+
pub fn some_page(user_name: &str) -> String {
|
|
88
|
+
html! {
|
|
89
|
+
<Page title={"Home"}>
|
|
90
|
+
{format!("Welcome, {}", user_name)}
|
|
91
|
+
</Page>
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#[test]
|
|
97
|
+
fn test_readme_stuff() {
|
|
98
|
+
use pretty_assertions::assert_eq;
|
|
99
|
+
let result = readme_code::some_page("Gal");
|
|
100
|
+
let expected = concat!(
|
|
101
|
+
"<!DOCTYPE html>",
|
|
102
|
+
"<html>",
|
|
103
|
+
"<head><title>Home</title></head>",
|
|
104
|
+
"<body>",
|
|
105
|
+
"Welcome, Gal",
|
|
106
|
+
"</body>",
|
|
107
|
+
"</html>"
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
assert_eq!(result, expected);
|
|
111
|
+
}
|