leon/lib.rs
1//! Dead-simple string templating.
2//!
3//! Leon parses a template string into a list of tokens, and then substitutes
4//! provided values in. Unlike other templating engines, it is extremely simple:
5//! it supports no logic, only replaces. It is even simpler than `format!()`,
6//! albeit with a similar syntax.
7//!
8//! # Syntax
9//!
10//! ```plain
11//! it is better to rule { group }
12//! one can live {adverb} without power
13//! ```
14//!
15//! A replacement is denoted by `{` and `}`. The contents of the braces, trimmed
16//! of any whitespace, are the key. Any text outside of braces is left as-is.
17//!
18//! To escape a brace, use `\{` or `\}`. To escape a backslash, use `\\`. Keys
19//! cannot contain escapes.
20//!
21//! ```plain
22//! \{ leon \}
23//! ```
24//!
25//! The above examples, given the values `group = "no one"` and
26//! `adverb = "honourably"`, would render to:
27//!
28//! ```plain
29//! it is better to rule no one
30//! one can live honourably without power
31//! { leon }
32//! ```
33//!
34//! # Usage
35//!
36//! A template is first parsed to a token list:
37//!
38//! ```
39//! use leon::Template;
40//!
41//! let template = Template::parse("hello {name}").unwrap();
42//! ```
43//!
44//! The template can be inspected, for example to check if a key is present:
45//!
46//! ```
47//! # use leon::Template;
48//! #
49//! # let template = Template::parse("hello {name}").unwrap();
50//! assert!(template.has_key("name"));
51//! ```
52//!
53//! The template can be rendered to a string:
54//!
55//! ```
56//! # use leon::Template;
57//! use leon::vals;
58//! #
59//! # let template = Template::parse("hello {name}").unwrap();
60//! assert_eq!(
61//! template.render(
62//! &&vals(|_key| Some("marcus".into()))
63//! ).unwrap().as_str(),
64//! "hello marcus",
65//! );
66//! ```
67//!
68//! …or to a writer:
69//!
70//! ```
71//! use std::io::Write;
72//! # use leon::Template;
73//! use leon::vals;
74//! #
75//! # let template = Template::parse("hello {name}").unwrap();
76//! let mut buf: Vec<u8> = Vec::new();
77//! template.render_into(
78//! &mut buf,
79//! &&vals(|key| if key == "name" {
80//! Some("julius".into())
81//! } else {
82//! None
83//! })
84//! ).unwrap();
85//! assert_eq!(buf.as_slice(), b"hello julius");
86//! ```
87//!
88//! …with a map:
89//!
90//! ```
91//! use std::collections::HashMap;
92//! # use leon::Template;
93//! # let template = Template::parse("hello {name}").unwrap();
94//! let mut values = HashMap::new();
95//! values.insert("name", "brutus");
96//! assert_eq!(template.render(&values).unwrap().as_str(), "hello brutus");
97//! ```
98//!
99//! …or with your own type, if you implement the [`Values`] trait:
100//!
101//! ```
102//! # use leon::Template;
103//! use std::borrow::Cow;
104//! use leon::Values;
105//!
106//! struct MyMap {
107//! name: &'static str,
108//! }
109//! impl Values for MyMap {
110//! fn get_value(&self, key: &str) -> Option<Cow<'_, str>> {
111//! if key == "name" {
112//! Some(self.name.into())
113//! } else {
114//! None
115//! }
116//! }
117//! }
118//! #
119//! # let template = Template::parse("hello {name}").unwrap();
120//! let values = MyMap { name: "pontifex" };
121//! assert_eq!(template.render(&values).unwrap().as_str(), "hello pontifex");
122//! ```
123//!
124//! # Compile-time parsing
125//!
126//! You can either use [`leon-macros`](https://docs.rs/leon-macros)'s
127//! [`template!`](https://docs.rs/leon-macros/latest/leon_macros/macro.template.html),
128//! a proc-macro, with the exact same syntax as the normal parser, or this
129//! crate's [`template!`] rules-macro, which requires a slightly different
130//! syntax but doesn't bring in additional dependencies. In either case,
131//! the leon library is required as a runtime dependency.
132//!
133//! # Errors
134//!
135//! Leon will return a [`ParseError`] if the template fails to
136//! parse. This can happen if there are unbalanced braces, or if a key is empty.
137//!
138//! Leon will return a [`RenderError::MissingKey`] if a key is missing from keyed
139//! values passed to [`Template::render()`], unless a default value is provided
140//! with [`Template.default`].
141//!
142//! It will also pass through I/O errors when using [`Template::render_into()`].
143
144#[doc(inline)]
145pub use error::*;
146
147#[doc(inline)]
148pub use template::*;
149
150#[doc(inline)]
151pub use values::*;
152
153mod error;
154mod macros;
155mod parser;
156mod template;
157mod values;