Reign View is a component based HTML templating library for Rust inspired by [Vue.js](https://vuejs.org) 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][ann]][[2][ann]]. 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](https://docs.rs/reign_view) for more details. **NOTE**: Minimum supported Rust version is **1.45.0** # Table of contents * [Quickstart](#quickstart) * [How it works](#how-it-works) * [Template Syntax](#template-syntax) * [Components](#components) * [Helpers & Feature Gates](#helpers--feature-gates) * [Appendix](#appendix) # Quickstart 1. Add [reign](https://docs.rs/reign) to your code base with default features ommitted and `view` feature enabled ```toml [dependencies] reign = { version = "*", features = ["view"], default-features = false } ``` 2. Initiate the templates in your `main.rs` ```rust,ignore use reign::prelude::*; // If your templates live under `src/views` folder views!("src", "views"); ``` 3. Write a template in `src/views/pages/about.html` ```html

{{ name }} aged {{ age: u8 }}

``` 4. 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) ``` # How it works There are multiple steps that goes into this templating library. * Building a *view* out of the HTML template. * Rendering the *view* into a String. ### Building 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, "{}{}{}{}{}", "

\n ", self.name, "\n aged ", self.age, "\n

" ) } } } } ``` 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](#template-syntax) ### Rendering 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

``` If you want to use `"` inside the attribute value for an *expression*, you can follow the HTML spec and surround the value with `'`. ```html
``` ### Variable Attributes If you want to have an attribute that is completely interpolated with just one mustache tag and nothing else, you can do this. ```html
``` The value of the attribute `title` will be the value of `page_name` field. ### Control Attributes The library doesn't allow `if` conditions and `for` loops as expressions inside the mustache tags. You can use a control attribute on html tags to do this. ```html
Welcome
{{ page_name }}
``` The above template prints either the first or the second `div` depending on the *expression* provided to the `!if` control attribute. `!else-if` is also supported as you would expect. `for` loops also make use of control attribute syntax like shown below. ```html
{{ char }}
``` The above template prints `div` tags for all the characters in `page_name` field. Other than the name difference in the control attribute, `!for` needs *pattern **in** expression* syntax. ### Grouping Elements Because `!if` and `!for` are attributes, they need to be attached to a single tag. But sometimes, you might need to render more than one element. In that case, you can use the `template` tag which works like an invisible wrapper. ```html ``` A template doesn't allow multiple elements to be defined at the root. Which means, you can use the `template` tag to group elements at the root of the template. ```html ``` ### Class & Style bindings To be implemented # Components Every template can be used as a component by default and thus is reusable. Let us assume we have a template `src/views/shared/button.html` with the following: ```html ``` The generated view for this would look like the following: ```rust struct Button<'a> { href: &'a str, text: &'a str, } ``` The above template can be used in other templates using the following syntax: ```HTML ``` The attributes on a component work just like the attirbutes on a normal HTML element described [above](#attributes). Any template can be used as a component. We can refer to the template by using it's tag reference. Tag reference can be achieved by joining all the parts in the path of the component with `:` after converting them to kebab case. A template that lives at `src/views/users/avatar.html` can be used with `users:avatar`, and similarily a template that lives at `src/views/common/simple/small_icon.html` can be used with `common:simple:small-icon`. ### Slots Just like with HTML elements, it’s often useful to be able to pass content to a component, like this: ```html
Dashboard
``` Fortunately, this is possible by using our custom `slot` element in the `button.html`. ```html ``` The `` above will be replaced by the elements we described inside `shared:button` element when it's used. ### Scope When we use a variable inside a component's slot, such as: ```html
{{ link_text }}
``` That slot tries to access this templates fields (i.e. the same `scope`). The slot does not have access to ``'s fields. For example, trying to access `href` would not work: ```html
{{ href }}
``` It would instead create a `href` field on the template itself. ### Fallback To be implemented ### Named Slots There are times when it’s useful to have multiple slots. For example, in a `` component with the following template: ```html
``` For these cases, the `` element has a special attribute, `name`, which can be used to define additional slots: ```html
``` A `` outlet without `name` implicitly has the name `"default"`. To provide content to named slots, we can use a special attribute on a `