bart/lib.rs
1/*!
2
3Bart is a compile time templating language inspired by
4[Mustache](https://mustache.github.io/mustache.5.html). It plays to Rust's
5strengths by statically compiling the template into efficient code and
6performing full variable resolution and type checking at compile time.
7
8 1. [Cargo dependencies](#cargo-dependencies)
9 2. [Example](#example)
10 1. [Line-by-line](#line-by-line)
11 3. [Bart language reference](#bart-language-reference)
12
13Cargo dependencies
14==================
15To use Bart, add these dependencies to your `Cargo.toml`:
16
17```toml
18[dependencies]
19bart = "0.1.0"
20bart_derive = "0.1.0"
21```
22
23Example
24=======
25Given the template file `hello_world.html`:
26
27```text
28Hello {{name}}
29```
30
31We can write the following:
32
33```
34#[derive(bart_derive::BartDisplay)]
35#[template = "examples/hello_world.html"]
36struct HelloWorld<'a> {
37 name: &'a str,
38}
39
40print!("{}", &HelloWorld { name: "World" });
41# assert_eq!("Hello World\n", format!("{}", &HelloWorld { name: "World" }));
42```
43
44To compile this example program, you need to add both `bart` and `bart_derive` as dependencies in your `Cargo.toml`.
45
46Running this program will output
47
48```text
49Hello World
50```
51
52You can run this example by cloning this repository and executing `cargo run --example hello_world`.
53
54Line by line
55------------
56```ignore
57#[derive(bart_derive::BartDisplay)]
58```
59
60The programmer interface to Bart is the procedural macro defined in the `bart_derive` crate, which implements support for `#[derive(bart_derive::BartDisplay)]`. It must be added as a dependency in your `Cargo.toml`. `bart_derive` generates code which is dependent on the `bart` crate, so you also need to pull this in as a dependency.
61
62Use `bart_derive::BartDisplay` to generate an `impl` of the [`Display`][Display] trait based on the template and struct below.
63
64```ignore
65#[template = "hello_world.html"]
66```
67
68`bart_derive` will read `hello_world.html` and use it to generate the template rendering code. The given file name is relative to your crate root, so, for example, you have to specify `#[template = "src/hello_world.html"]` if you want your template to reside in the `src/` directory.
69
70It is also possible to specify the template inline with `template_string`: `#[template_string = "Hello {{name}}"]`.
71
72```ignore
73struct HelloWorld<'a> {
74 name: &'a str,
75}
76```
77
78Values to be interpolated in the template will be resolved from the given `struct`. In this case `{{name}}` would be resolved to the `name` field of this struct. Fields to be interpolated must implement the [`Display`][Display] trait.
79
80```ignore
81fn main() {
82 print!("{}", &HelloWorld { name: "World" });
83}
84```
85
86As noted above, `bart_derive` has now generated an `impl` of [`Display`][Display] for `HelloWorld`. This means we can pass instances of `HelloWorld` to `print!`, `write!`, `format!` and so on. The template is rendered with the supplied data, generating `Hello World` to standard output.
87
88[Display]: https://doc.rust-lang.org/std/fmt/trait.Display.html
89
90Bart language reference
91=======================
92Bart supports: [interpolation](#interpolation), [verbatim
93interpolation](#verbatim-interpolation), …
94
95Interpolation
96-------------
97```
98# #[derive(bart_derive::BartDisplay)]
99# #[template_string = "\
100Hello {{name}}
101# "]
102# struct HelloWorld<'a> {
103# name: &'a str,
104# }
105#
106# fn main() {
107# assert_eq!(
108# "Hello World < &\n",
109# format!("{}", &HelloWorld { name: "World < &" })
110# );
111# }
112```
113Include fields by delegating to the [`Display`][Display] trait.
114
115Interpolations are HTML escaped, so it is safe to include user input this way.
116
117Verbatim interpolation
118----------------------
119```
120# #[derive(bart_derive::BartDisplay)]
121# #[template_string = "\
122Hello {{{name}}}
123# "]
124# struct HelloWorld<'a> {
125# name: &'a str,
126# }
127#
128# fn main() {
129# assert_eq!(
130# "Hello World < &\n",
131# format!("{}", &HelloWorld { name: "World < &" })
132# );
133# }
134```
135Include fields by delegating to the [`Display`][Display] trait.
136
137Verbatim interpolations are not HTML escaped and are suitable for including
138HTML content that is otherwise known to be safe.
139
140It can be valuable to use verbatim interpolation to include other Bart
141templates.
142
143*/
144
145#![cfg_attr(feature = "specialization", feature(specialization))]
146
147mod conditional;
148mod display_html_safe;
149mod negative_iterator;
150
151// With specialization, DisplayHtmlSafe could be something that the
152// user wants to deal with. But specialization is still unstable.
153#[doc(hidden)]
154pub use display_html_safe::DisplayHtmlSafe;
155
156pub use conditional::Conditional;
157pub use negative_iterator::NegativeIterator;