Reign View is a component based HTML templating library for Rust inspired by Vue.js templates.
This library makes using templates as easy as pie. It uses HTML based template syntax that are valid and can be parsed by spec-compliant browsers and HTML parsers [1][2]. It has been developed foremost with ease of use in mind followed by future extensibility, modularization and customization.
This library also provides multiple helpers and feature gates which an user can use to customize, allowing the library to be used directly with or without reign_router.
Please refer to API documentation for more details.
NOTE: Minimum supported Rust version is 1.45.0
Add reign to your code base with
default features ommitted and view
feature enabled
toml
[dependencies]
reign = { version = "*", features = ["view"], default-features = false }
Initiate the templates in your main.rs
```rust,ignore use reign::prelude::*;
// If your templates live under src/views
folder
views!("src", "views");
```
Write a template in src/views/pages/about.html
```html
{{ name }} aged {{ age: u8 }}
```
Render the template
```rust,ignore use reign::prelude::*;
let (name, age) = ("John", 28);
// The macro automatically captures all the
// variables it needs, builds the view to display
// and returns a String
//
// pages::about
is the unique path of the above template
render!(pages::about)
```
There are multiple steps that goes into this templating library.
Let's assume that you have written the template described in the previous section at the respective path.
Now, when you initiate the templating library by writing the following:
```rust,ignore use reign::prelude::*;
views!("src", "views"); ```
The library expands the views!
macro to something like the following:
``rust
// It will create a module which is always called
views`
mod views {
// Then it will create a module for `pages` subdirectory
pub mod pages {
// Then it will create a struct for the template file
pub struct About<'a> {
// It will add a raw string field for every variable
// found which does not have a type described
pub name: &'a str,
// It will add a typed field for every variable found
// that was given a type (once in a template is enough)
pub age: u8,
}
use std::fmt::{Display, Formatter, Result};
// Then it will implement std::fmt::Display for it
impl Display for About<'_> {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}{}{}{}{}",
"<p>\n ", self.name, "\n <sub>aged ", self.age, "</sub>\n</p>"
)
}
}
}
} ```
The above expansion is approximate. There might be small changes in the way they were expanded or other hidden things that are for internal use.
You can read more about template syntax below here
When the plain view feature is enabled and when you try to render a template like the following:
```rust,ignore use reign::prelude::*;
let (name, age) = ("John", 28);
render!(pages::about); ```
The library expands the render!
macro to something like the following:
rust,ignore
format!("{}", crate::views::pages::About {
name: name.as_ref(),
age,
});
Which returns the following String:
```html
John aged 28
```
# Template Syntax
Before we start talking about the template syntax, let's agree on a few terms
for this section so that it will be easier to refer to them later on.
An **expression** is a custom subset of all the types of expressions available
in Rust language. You can read about them [here](#expressions).
A **pattern** is a custom rust pattern syntax where the expressions allowed are
the only ones defined in the above paragraph. You can read more about them
[here](#patterns).
A **field** refers to a field of the struct that is built for the template by
the `views!` macro when initiating the template library.
All html style tags that are used in the template should be closed either by a
self closing syntax or an end tag. The only exception are the tags which are
allowed by HTML spec to be self closing by default called **void elements**.
### Text
The most basic form of templating is *"interpolation"* using the *"mustache"*
syntax (double curly braces).
```html
Message: {{ msg }}
```
The mustache tag will be replaced with the value of the `msg` *field*. You can
also use an *expression* inside the mustache tags. Any type that has
`std::fmt::Display` implemented can be the final result of the *expression*
defined by the mustache tags.
```html
Word Count: {{ msg.len() }}
```
### Attributes
Interpolation can also be used in values of attributes.
```html
md5-657b7fa289296ba2e5a439fd91c75b6c
```
Fortunately, this is possible by using our custom `slot` element in the `button.html`.
```html
```
The ` A paragraph for the main content. And another one.Here might be a page title
Here's some contact info
Now everything inside the <template>
elements will be passed to the corresponding
slots. Any content not wrapped in a <template>
is assumed to be for the default slot.
However, we can still wrap default slot content in a <template>
if you wish to be explicit.
There are multiple feature gates on Reign to help the user select what he wants from the library.
Please refer to examples to see how they are used.
Please refer to reign_derive for more information about the usage of macros.
views!
can be used to build the views.render!
can be used to render a view into a string.views!
can be used to build the views.render
helper and render!
renders a view into response for reign_router handler.redirect
helper for reign_router handler.json
helper and json!
builds response for reign_router handlerAllowed expressions are described below with bop
being a binary operator and
uop
being an unary operator. ...
represents possible repetitions.
literal
ident
[expr, ...]
expr bop expr
uop expr
expr(expr, ...)
expr.ident
expr.number
expr[expr]
(expr)
[expr; expr]
(expr, ...)
& expr
expr as type
expr: type
expr..expr
type { ident: expr, ..expr, ... }
Allowed patterns are described below with expr
represents the above mentioned
expression. ...
represents possible repetitions.
ident
_
& pat
type { pat, .., ... }
(pat, ...)
type(pat, .., ...)
:
which is not completely supported by pure HTML5
spec but most of the parsers support it.