1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*!

Bart is a compile time templating language inspired by
[Mustache](https://mustache.github.io/mustache.5.html). It plays to Rust's
strengths by statically compiling the template into efficient code and
performing full variable resolution and type checking at compile time.

 1. [Cargo dependencies](#cargo-dependencies)
 2. [Example](#example)
    1. [Line-by-line](#line-by-line)
 3. [Bart language reference](#bart-language-reference)

Cargo dependencies
==================
To use Bart, add these dependencies to your `Cargo.toml`:

```toml
[dependencies]
bart = "0.1.0"
bart_derive = "0.1.0"
```

Example
=======
Given the template file `hello_world.html`:

```text
Hello {{name}}
```

We can write the following program:

```
#[macro_use] extern crate bart_derive;

#[derive(BartDisplay)]
#[template = "examples/hello_world.html"]
struct HelloWorld<'a> {
    name: &'a str,
}

fn main() {
    print!("{}", &HelloWorld { name: "World" });
#   assert_eq!("Hello World\n", format!("{}", &HelloWorld { name: "World" }));
}
```

To compile this example program, you need to add both `bart` and `bart_derive` as dependencies in your `Cargo.toml`.

Running this program will output

```text
Hello World
```

You can run this example by cloning this repository and executing `cargo run --example hello_world`.

Line by line
------------
```ignore
#[macro_use] extern crate bart_derive;
```

The programmer interface to Bart is the procedural macro defined in the `bart_derive` crate, which implements support for `#[derive(BartDisplay)]`. It must be added as a dependency in your `Cargo.toml` and referenced like above. `bart_derive` generates code which is dependent on the `bart` crate, so you also need to pull this in as a dependency.

```ignore
#[derive(BartDisplay)]
```

Use `bart_derive` to generate an `impl` of the [`Display`][Display] trait based on the template and struct below.

```ignore
#[template = "hello_world.html"]
```

`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.

It is also possible to specify the template inline with `template_string`: `#[template_string = "Hello {{name}}"]`.

```ignore
struct HelloWorld<'a> {
    name: &'a str,
}
```

Values 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.

```ignore
fn main() {
    print!("{}", &HelloWorld { name: "World" });
}
```

As 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.

[Display]: https://doc.rust-lang.org/std/fmt/trait.Display.html

Bart language reference
=======================
Bart supports: [interpolation](#interpolation), [verbatim
interpolation](#verbatim-interpolation), &hellip;

Interpolation
-------------
```
# #[macro_use] extern crate bart_derive;
# #[derive(BartDisplay)]
# #[template_string = "\
Hello {{name}}
# "]
# struct HelloWorld<'a> {
#     name: &'a str,
# }
#
# fn main() {
#     assert_eq!(
#         "Hello World &lt; &amp;\n",
#         format!("{}", &HelloWorld { name: "World < &" })
#     );
# }
```
Include fields by delegating to the [`Display`][Display] trait.

Interpolations are HTML escaped, so it is safe to include user input this way.

Verbatim interpolation
----------------------
```
# #[macro_use] extern crate bart_derive;
# #[derive(BartDisplay)]
# #[template_string = "\
Hello {{{name}}}
# "]
# struct HelloWorld<'a> {
#     name: &'a str,
# }
#
# fn main() {
#     assert_eq!(
#         "Hello World < &\n",
#         format!("{}", &HelloWorld { name: "World < &" })
#     );
# }
```
Include fields by delegating to the [`Display`][Display] trait.

Verbatim interpolations are not HTML escaped and are suitable for including
HTML content that is otherwise known to be safe.

It can be valuable to use verbatim interpolation to include other Bart
templates.


*/

#![cfg_attr(feature = "specialization", feature(specialization))]

#[macro_use] extern crate nom;

mod display_html_safe;

// With specialization, DisplayHtmlSafe could be something that the
// user wants to deal with. But specialization is still unstable.
#[doc(hidden)]
pub use display_html_safe::DisplayHtmlSafe;

mod conditional;
pub use conditional::Conditional;

mod negative_iterator;
pub use negative_iterator::NegativeIterator;