aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Cargo.lock24
-rw-r--r--README.md7
-rw-r--r--askama/src/filters.rs49
-rw-r--r--askama/src/lib.rs11
-rw-r--r--askama_derive/Cargo.toml2
-rw-r--r--askama_derive/src/generator.rs16
-rw-r--r--askama_derive/src/parser.rs33
-rw-r--r--testing/templates/nested-attr.html1
-rw-r--r--testing/tests/simple.rs19
9 files changed, 132 insertions, 30 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 17e6fb0..979ddb5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -16,15 +16,31 @@ dependencies = [
name = "askama_derive"
version = "0.3.3"
dependencies = [
- "nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nom 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
+name = "libc"
+version = "0.2.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memchr"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "nom"
-version = "2.2.1"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "quote"
@@ -55,7 +71,9 @@ version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
-"checksum nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff"
+"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264"
+"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
+"checksum nom 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06989cbd367e06f787a451f3bc67d8c3e0eaa10b461cc01152ffab24261a31b1"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
diff --git a/README.md b/README.md
index a346348..f9b7286 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ Many thanks to [David Tolnay][dtolnay] for his support in improving Askama.
### Supported in templates
* Template inheritance (one level only)
-* Basic loops and if/else if/else statements
+* Basic loops and if/else statements
* Whitespace suppressing with '-' markers
* Some built-in filters
@@ -59,11 +59,10 @@ First, add the following to your crate's `Cargo.toml`:
build = "build.rs"
# in section [dependencies]
-askama = "0.1"
-askama_derive = "0.1"
+askama = "0.3"
# in section [build-dependencies]
-askama = "0.1"
+askama = "0.3"
```
Because Askama will generate Rust code from your template files,
diff --git a/askama/src/filters.rs b/askama/src/filters.rs
index 3f6aede..ccbf1a0 100644
--- a/askama/src/filters.rs
+++ b/askama/src/filters.rs
@@ -57,6 +57,34 @@ pub fn e(s: &fmt::Display) -> String {
/// the Askama code generator.
pub fn format() { }
+/// Converts to lowercase.
+pub fn lower(s: &fmt::Display) -> String {
+ let s = format!("{}", s);
+ s.to_lowercase()
+}
+
+/// Alias for the `lower()` filter.
+pub fn lowercase(s: &fmt::Display) -> String {
+ lower(s)
+}
+
+/// Converts to uppercase.
+pub fn upper(s: &fmt::Display) -> String {
+ let s = format!("{}", s);
+ s.to_uppercase()
+}
+
+/// Alias for the `upper()` filter.
+pub fn uppercase(s: &fmt::Display) -> String {
+ upper(s)
+}
+
+/// Strip leading and trailing whitespace.
+pub fn trim(s: &fmt::Display) -> String {
+ let s = format!("{}", s);
+ s.trim().to_owned()
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -67,4 +95,25 @@ mod tests {
assert_eq!(escape(&"bla&"), "bla&");
assert_eq!(escape(&"<foo"), "&lt;foo");
}
+
+ #[test]
+ fn test_lower() {
+ assert_eq!(lower(&"Foo"), "foo");
+ assert_eq!(lower(&"FOO"), "foo");
+ assert_eq!(lower(&"FooBar"), "foobar");
+ assert_eq!(lower(&"foo"), "foo");
+ }
+
+ #[test]
+ fn test_upper() {
+ assert_eq!(upper(&"Foo"), "FOO");
+ assert_eq!(upper(&"FOO"), "FOO");
+ assert_eq!(upper(&"FooBar"), "FOOBAR");
+ assert_eq!(upper(&"foo"), "FOO");
+ }
+
+ #[test]
+ fn test_trim() {
+ assert_eq!(trim(&" Hello\tworld\t"), "Hello\tworld");
+ }
}
diff --git a/askama/src/lib.rs b/askama/src/lib.rs
index 311992f..9126a99 100644
--- a/askama/src/lib.rs
+++ b/askama/src/lib.rs
@@ -51,8 +51,8 @@
//! Reading from variables is subject to the usual borrowing policies.
//! For example, `{{ name }}` will get the ``name`` field from the template
//! context,
-//! while `{{ user.name }}` will get the ``name`` field of the `user`
-//! ``field`` of the template context.
+//! while `{{ user.name }}` will get the ``name`` field of the ``user``
+//! field from the template context.
//!
//! ## Filters
//!
@@ -105,6 +105,8 @@
//!
//! The `block` tags define three blocks that can be filled in by child
//! templates. The base template defines a default version of the block.
+//! A base template must define one or more blocks in order to be enable
+//! inheritance.
//!
//! ### Child template
//!
@@ -133,6 +135,11 @@
//! have a field called `_parent` of the type used as the base template
//! context. Blocks can only refer to the context of their own template.
//!
+//! Note that, if the base template lives in another module than the child
+//! template, the child template's module should import all symbols from the
+//! base template's module in order for it to find the trait definition that
+//! supports the inheritance mechanism.
+//!
//! ## HTML escaping
//!
//! Askama does not yet support automatic escaping. Care must be taken to
diff --git a/askama_derive/Cargo.toml b/askama_derive/Cargo.toml
index 5f65f23..4aad3fb 100644
--- a/askama_derive/Cargo.toml
+++ b/askama_derive/Cargo.toml
@@ -12,6 +12,6 @@ workspace = ".."
proc-macro = true
[dependencies]
-nom = "2.1"
+nom = "3"
syn = "0.11"
quote = "0.3"
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index edde3fe..f055cb7 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -129,7 +129,7 @@ impl<'a> Generator<'a> {
if name == "format" {
self.write("format!(");
} else {
- self.write(&format!("askama::filters::{}(&", name));
+ self.write(&format!("::askama::filters::{}(&", name));
}
for (i, arg) in args.iter().enumerate() {
@@ -274,7 +274,7 @@ impl<'a> Generator<'a> {
ws2: &WS) {
self.writeln("#[allow(unused_variables)]");
self.writeln(&format!(
- "fn render_block_{}_to(&self, writer: &mut std::fmt::Write) {{",
+ "fn render_block_{}_to(&self, writer: &mut ::std::fmt::Write) {{",
name));
self.prepare_ws(ws1);
self.handle(nodes);
@@ -351,7 +351,7 @@ impl<'a> Generator<'a> {
let name = if let Some(suffix) = trait_suffix {
format!("TraitFrom{}", suffix)
} else {
- "askama::Template".to_string()
+ "::askama::Template".to_string()
};
self.writeln(&format!("impl{} {} for {}{}{} {{",
full_anno.as_str(), &name, ast.ident.as_ref(),
@@ -360,7 +360,7 @@ impl<'a> Generator<'a> {
fn impl_template(&mut self, ast: &syn::DeriveInput, nodes: &'a [Node]) {
self.write_header(ast, None);
- self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
+ self.writeln("fn render_to(&self, writer: &mut ::std::fmt::Write) {");
self.handle(nodes);
self.flush_ws(&WS(false, false));
self.writeln("}");
@@ -375,7 +375,7 @@ impl<'a> Generator<'a> {
self.writeln("#[allow(unused_variables)]");
let trait_name = format!("TraitFrom{}", path_as_identifier(base));
self.writeln(&format!(
- "fn render_trait_to(&self, timpl: &{}, writer: &mut std::fmt::Write) {{",
+ "fn render_trait_to(&self, timpl: &{}, writer: &mut ::std::fmt::Write) {{",
trait_name));
if let Some(nodes) = nodes {
@@ -392,7 +392,7 @@ impl<'a> Generator<'a> {
fn impl_template_for_trait(&mut self, ast: &syn::DeriveInput, derived: bool) {
self.write_header(ast, None);
- self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
+ self.writeln("fn render_to(&self, writer: &mut ::std::fmt::Write) {");
if derived {
self.writeln("self._parent.render_trait_to(self, writer);");
} else {
@@ -408,11 +408,11 @@ impl<'a> Generator<'a> {
for bname in block_names {
self.writeln(&format!(
- "fn render_block_{}_to(&self, writer: &mut std::fmt::Write);",
+ "fn render_block_{}_to(&self, writer: &mut ::std::fmt::Write);",
bname));
}
self.writeln(&format!(
- "fn render_trait_to(&self, timpl: &{}, writer: &mut std::fmt::Write);",
+ "fn render_trait_to(&self, timpl: &{}, writer: &mut ::std::fmt::Write);",
trait_name));
self.writeln("}");
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index 74140bf..61ccb09 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -156,18 +156,27 @@ named!(expr_single<Expr>, alt!(
expr_group
));
-named!(expr_attr<Expr>, alt!(
- do_parse!(
- obj: expr_single >>
- tag_s!(".") >>
- attr: identifier >>
- args: arguments >>
- (if args.is_some() {
- Expr::Call(Box::new(obj), attr, args.unwrap())
- } else {
- Expr::Attr(Box::new(obj), attr)
- })
- ) | expr_single
+named!(attr<(&str, Option<Vec<Expr>>)>, do_parse!(
+ tag_s!(".") >>
+ attr: identifier >>
+ args: arguments >>
+ (attr, args)
+));
+
+named!(expr_attr<Expr>, do_parse!(
+ obj: expr_single >>
+ attrs: many0!(attr) >>
+ ({
+ let mut res = obj;
+ for (aname, args) in attrs {
+ res = if args.is_some() {
+ Expr::Call(Box::new(res), aname, args.unwrap())
+ } else {
+ Expr::Attr(Box::new(res), aname)
+ };
+ }
+ res
+ })
));
named!(filter<(&str, Option<Vec<Expr>>)>, do_parse!(
diff --git a/testing/templates/nested-attr.html b/testing/templates/nested-attr.html
new file mode 100644
index 0000000..3bbbbc3
--- /dev/null
+++ b/testing/templates/nested-attr.html
@@ -0,0 +1 @@
+{{ inner.holder.a }}
diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs
index 6d8afa3..c924e85 100644
--- a/testing/tests/simple.rs
+++ b/testing/tests/simple.rs
@@ -93,6 +93,25 @@ fn test_attr() {
}
+struct NestedHolder {
+ holder: Holder,
+}
+
+#[derive(Template)]
+#[template(path = "nested-attr.html")]
+struct NestedAttrTemplate {
+ inner: NestedHolder,
+}
+
+#[test]
+fn test_nested_attr() {
+ let t = NestedAttrTemplate {
+ inner: NestedHolder { holder: Holder { a: 5 } }
+ };
+ assert_eq!(t.render(), "5");
+}
+
+
#[derive(Template)]
#[template(path = "option.html")]
struct OptionTemplate<'a> {