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), … 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. 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;