~repos /tide-jsx

#rust#proc-macro#jsx

git clone https://pyrossh.dev/repos/tide-jsx.git

Tide + JSX


a2a8cc93 Peter John

3 years ago
update readme
Files changed (1) hide show
  1. README.md +40 -106
README.md CHANGED
@@ -1,119 +1,53 @@
1
- # tide-jsx
1
+ # tide-jsx [![Build Status](https://github.com/pyrossh/tide-jsx/workflows/Test/badge.svg)](https://github.com/pyrossh/tide-jsx/actions?query=workflow%3ATest) [![crates.io](https://img.shields.io/crates/v/tide-jsx.svg)](https://crates.io/crates/tide-jsx)
2
2
 
3
- In order to render a simple HTML fragment into a `String`, use the `rsx!` macro to generate a
3
+ This crate allows to use jsx like templating engine (which is a slightly modified version of [render.rs](https://github.com/render-rs/render.rs)) as templates in your tide request handlers.
4
- component tree, and call `render` on it:
5
4
 
6
- ```rust
7
- use tide_jsx::{rsx, Render};
8
-
9
- let tree = rsx! {
10
- <div>
5
+ ## Example
11
- <h1>{"Hello!"}</h1>
12
- <p>{"Hello world!"}</p>
13
- </div>
14
- };
15
-
16
- assert_eq!(tree.render(), "<div><h1>Hello!</h1><p>Hello world!</p></div>");
17
- ```
18
-
19
- Because this is so common, there's another macro called `html!` that calls `rsx!` to generate
20
- a component tree, and then calls `render` on it. Most of the time, you'll find yourself using
21
- the `rsx!` macro to compose arbitrary components, and only calling `html!` when you need a
22
- String output, when sending a response or generating a Markdown file.
23
-
24
- In Render, attributes and plain strings are escaped using the `render::html_escaping` module. In order to
25
- use un-escaped values so you can dangerously insert raw HTML, use the `raw!` macro around your
26
- string:
27
6
 
28
7
  ```rust
8
+ use tide::http::mime;
9
+ use tide::utils::After;
10
+ use tide::{log, Request, Response};
29
- use tide_jsx::{html, raw};
11
+ use tide_jsx::html::HTML5Doctype;
30
-
31
- let tree = html! {
32
- <div>
33
- <p>{"<Hello />"}</p>
34
- <p>{raw!("<Hello />")}</p>
35
- </div>
36
- };
37
-
38
- assert_eq!(tree, "<div><p>&lt;Hello /&gt;</p><p><Hello /></p></div>");
39
- ```
40
-
41
- ### Custom components
42
-
43
- Render's greatest ability is to provide type-safety along with custom renderable components.
44
- Introducing new components is as easy as defining a function that returns a `Render` value.
45
-
46
- In order to build up components from other components or HTML nodes, you can use the `rsx!`
47
- macro, which generates a `Render` component tree:
48
-
49
- ```rust
50
- use tide_jsx::{component, rsx, html};
12
+ use tide_jsx::{component, rsx, view};
51
13
 
52
14
  #[component]
53
15
  fn Heading<'title>(title: &'title str) {
54
- rsx! { <h1 class={"title"}>{title}</h1> }
16
+ rsx! { <h1 class={"title"}>{title}</h1> }
55
17
  }
56
18
 
19
+ async fn index(_req: Request<()>) -> tide::Result {
20
+ view! {
21
+ <>
57
- let rendered_html = html! {
22
+ <HTML5Doctype />
23
+ <html>
24
+ <head><title>{"Tide JSX"}</title></head>
25
+ <body>
26
+ <div>
58
- <Heading title={"Hello world!"} />
27
+ <Heading title={"Hello world"} />
59
- };
60
-
61
- assert_eq!(rendered_html, r#"<h1 class="title">Hello world!</h1>"#);
62
- ```
63
-
64
- If you pay close attention, you see that the function `Heading` is:
65
-
66
- - declared with an uppercase. Underneath, it generates a struct with the same name, and
67
- implements the `Render` trait on it.
68
- - does not have a return type. This is because everything is written to a writer, for
69
- performance reasons.
70
-
71
- ### Visibility & Component Libraries
72
-
73
- Often you're going to want to store your components somewhere else in your
74
- project tree other than the module you're working on (if not in a different
75
- module entirely!). In these cases, the visibility applied top the function that
76
- defines your component will flow down into all fields of that struct.
77
-
78
- For example, if we add "pub" to the front of our Heading component above:
79
-
80
- ```rust
81
- #[component]
82
- pub fn Heading<'title>(title: &'title str) {
83
- rsx! { <h1 class={"title"}>{title}</h1> }
84
- }
85
- ```
86
-
87
- ...the struct that is generated would look something like...
88
-
89
- ```rust
90
- pub struct Heading {
91
- pub title: &'title str
28
+ </div>
92
- }
93
- ```
94
-
95
- This is important to understand from a safety point of view when structuring
96
- your libraries.
97
-
98
- #### Full example
99
-
100
- ```rust
101
- use render::html::HTML5Doctype;
102
- use render::{component, rsx, html, Render};
103
-
104
- #[component]
105
- fn Page<'a, Children: Render>(title: &'a str, children: Children) {
106
- rsx! {
107
-
108
- }
109
- }
110
-
111
- pub fn some_page(user_name: &str) -> String {
112
- html! {
113
- <Page title={"Home"}>
114
- {format!("Welcome, {}", user_name)}
115
- </Page>
29
+ </body>
30
+ </html>
31
+ </>
116
32
  }
117
33
  }
118
34
 
35
+ #[async_std::main]
36
+ async fn main() -> tide::Result<()> {
37
+ log::start();
38
+ let mut app = tide::new();
39
+ app.with(tide::log::LogMiddleware::new());
40
+ app.with(After(|mut res: Response| async {
41
+ if let Some(err) = res.error() {
42
+ let msg = format!("<h1>Error: {:?}</h1>", err);
43
+ res.set_status(err.status());
44
+ res.set_content_type(mime::HTML);
45
+ res.set_body(msg);
46
+ }
47
+ Ok(res)
48
+ }));
49
+ app.at("/").get(index);
50
+ app.listen("127.0.0.1:5000").await?;
51
+ Ok(())
52
+ }
119
53
  ```