Fix formatting with cargo fmt

This commit is contained in:
Dirkjan Ochtman 2018-06-21 12:19:54 +02:00
parent f05a924c49
commit 31b90ccc65
20 changed files with 281 additions and 184 deletions

View File

@ -338,16 +338,16 @@ pub trait Template {
} }
} }
pub use shared::filters;
pub use askama_derive::*; pub use askama_derive::*;
pub use shared::filters;
pub use shared::{Error, MarkupDisplay, Result}; pub use shared::{Error, MarkupDisplay, Result};
#[cfg(feature = "with-iron")] #[cfg(feature = "with-iron")]
pub mod iron { pub mod iron {
extern crate iron; extern crate iron;
pub use self::iron::headers::ContentType;
pub use self::iron::modifier::Modifier; pub use self::iron::modifier::Modifier;
pub use self::iron::response::Response; pub use self::iron::response::Response;
pub use self::iron::headers::ContentType;
} }
#[cfg(feature = "with-rocket")] #[cfg(feature = "with-rocket")]

View File

@ -2,16 +2,15 @@ use input::TemplateInput;
use parser::{self, Cond, Expr, Macro, MatchParameter, MatchVariant, Node, Target, When, WS}; use parser::{self, Cond, Expr, Macro, MatchParameter, MatchVariant, Node, Target, When, WS};
use shared::{filters, path}; use shared::{filters, path};
use quote::ToTokens;
use proc_macro2::Span; use proc_macro2::Span;
use quote::ToTokens;
use std::{cmp, hash, str};
use std::path::Path;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::Path;
use std::{cmp, hash, str};
use syn; use syn;
pub fn generate(input: &TemplateInput, nodes: &[Node]) -> String { pub fn generate(input: &TemplateInput, nodes: &[Node]) -> String {
let mut sources = HashMap::new(); let mut sources = HashMap::new();
let mut parsed = HashMap::new(); let mut parsed = HashMap::new();
@ -26,20 +25,20 @@ pub fn generate(input: &TemplateInput, nodes: &[Node]) -> String {
Some(_) => panic!("multiple extend blocks found"), Some(_) => panic!("multiple extend blocks found"),
None => { None => {
base = Some(*path); base = Some(*path);
}, }
}, },
def @ Node::BlockDef(_, _, _, _) => { def @ Node::BlockDef(_, _, _, _) => {
blocks.push(def); blocks.push(def);
}, }
Node::Macro(name, m) => { Node::Macro(name, m) => {
macros.insert((None, *name), m); macros.insert((None, *name), m);
}, }
Node::Import(_, import_path, scope) => { Node::Import(_, import_path, scope) => {
let path = path::find_template_from_path(import_path, Some(&input.path)); let path = path::find_template_from_path(import_path, Some(&input.path));
sources.insert(path.clone(), path::get_template_source(&path)); sources.insert(path.clone(), path::get_template_source(&path));
imported.push((*scope, path)); imported.push((*scope, path));
} }
_ => {}, _ => {}
} }
} }
for (path, src) in &sources { for (path, src) in &sources {
@ -77,9 +76,9 @@ pub fn generate(input: &TemplateInput, nodes: &[Node]) -> String {
blocks: &blocks, blocks: &blocks,
macros: &macros, macros: &macros,
trait_name: match base { trait_name: match base {
Some(user_path) => trait_name_for_path( Some(user_path) => {
&path::find_template_from_path(user_path, Some(&input.path)) trait_name_for_path(&path::find_template_from_path(user_path, Some(&input.path)))
), }
None => trait_name_for_path(&input.path), None => trait_name_for_path(&input.path),
}, },
derived: base.is_some(), derived: base.is_some(),
@ -176,8 +175,10 @@ impl<'a> Generator<'a> {
// Implement `Template` for the given context struct. // Implement `Template` for the given context struct.
fn impl_template(&mut self, state: &'a State) { fn impl_template(&mut self, state: &'a State) {
self.write_header(state, "::askama::Template", None); self.write_header(state, "::askama::Template", None);
self.writeln("fn render_into(&self, writer: &mut ::std::fmt::Write) -> \ self.writeln(
::askama::Result<()> {"); "fn render_into(&self, writer: &mut ::std::fmt::Write) -> \
::askama::Result<()> {",
);
self.handle(state, state.nodes, AstLevel::Top); self.handle(state, state.nodes, AstLevel::Top);
self.flush_ws(&WS(false, false)); self.flush_ws(&WS(false, false));
self.writeln("Ok(())"); self.writeln("Ok(())");
@ -197,7 +198,10 @@ impl<'a> Generator<'a> {
// Implement `Deref<Parent>` for an inheriting context struct. // Implement `Deref<Parent>` for an inheriting context struct.
fn deref_to_parent(&mut self, state: &'a State, parent_type: &syn::Type) { fn deref_to_parent(&mut self, state: &'a State, parent_type: &syn::Type) {
self.write_header(state, "::std::ops::Deref", None); self.write_header(state, "::std::ops::Deref", None);
self.writeln(&format!("type Target = {};", parent_type.into_token_stream())); self.writeln(&format!(
"type Target = {};",
parent_type.into_token_stream()
));
self.writeln("fn deref(&self) -> &Self::Target {"); self.writeln("fn deref(&self) -> &Self::Target {");
self.writeln("&self._parent"); self.writeln("&self._parent");
self.writeln("}"); self.writeln("}");
@ -234,8 +238,10 @@ impl<'a> Generator<'a> {
// Implement `Template` for templates that implement a template trait. // Implement `Template` for templates that implement a template trait.
fn impl_template_for_trait(&mut self, state: &'a State) { fn impl_template_for_trait(&mut self, state: &'a State) {
self.write_header(state, "::askama::Template", None); self.write_header(state, "::askama::Template", None);
self.writeln("fn render_into(&self, writer: &mut ::std::fmt::Write) \ self.writeln(
-> ::askama::Result<()> {"); "fn render_into(&self, writer: &mut ::std::fmt::Write) \
-> ::askama::Result<()> {",
);
if state.derived { if state.derived {
self.writeln("self._parent.render_trait_into(self, writer)"); self.writeln("self._parent.render_trait_into(self, writer)");
} else { } else {
@ -252,21 +258,30 @@ impl<'a> Generator<'a> {
self.writeln(&format!( self.writeln(&format!(
"fn render_trait_into(&self, timpl: &{}, writer: &mut ::std::fmt::Write) \ "fn render_trait_into(&self, timpl: &{}, writer: &mut ::std::fmt::Write) \
-> ::askama::Result<()>;", -> ::askama::Result<()>;",
state.trait_name)); state.trait_name
));
self.writeln("}"); self.writeln("}");
} }
// Implement iron's Modifier<Response> if enabled // Implement iron's Modifier<Response> if enabled
fn impl_modifier_response(&mut self, state: &'a State) { fn impl_modifier_response(&mut self, state: &'a State) {
self.write_header(state, "::askama::iron::Modifier<::askama::iron::Response>", None); self.write_header(
state,
"::askama::iron::Modifier<::askama::iron::Response>",
None,
);
self.writeln("fn modify(self, res: &mut ::askama::iron::Response) {"); self.writeln("fn modify(self, res: &mut ::askama::iron::Response) {");
self.writeln("res.body = Some(Box::new(self.render().unwrap().into_bytes()));"); self.writeln("res.body = Some(Box::new(self.render().unwrap().into_bytes()));");
let ext = state.input.path.extension().map_or("", |s| s.to_str().unwrap_or("")); let ext = state
.input
.path
.extension()
.map_or("", |s| s.to_str().unwrap_or(""));
match ext { match ext {
"html" | "htm" => { "html" | "htm" => {
self.writeln("::askama::iron::ContentType::html().0.modify(res);"); self.writeln("::askama::iron::ContentType::html().0.modify(res);");
}, }
_ => (), _ => (),
}; };
@ -278,9 +293,15 @@ impl<'a> Generator<'a> {
fn impl_responder(&mut self, state: &'a State) { fn impl_responder(&mut self, state: &'a State) {
let lifetime = syn::Lifetime::new("'askama", Span::call_site()); let lifetime = syn::Lifetime::new("'askama", Span::call_site());
let param = syn::GenericParam::Lifetime(syn::LifetimeDef::new(lifetime)); let param = syn::GenericParam::Lifetime(syn::LifetimeDef::new(lifetime));
self.write_header(state, "::askama::rocket::Responder<'askama>", Some(vec![param])); self.write_header(
self.writeln("fn respond_to(self, _: &::askama::rocket::Request) \ state,
-> ::askama::rocket::Result<'askama> {"); "::askama::rocket::Responder<'askama>",
Some(vec![param]),
);
self.writeln(
"fn respond_to(self, _: &::askama::rocket::Request) \
-> ::askama::rocket::Result<'askama> {",
);
let ext = match state.input.path.extension() { let ext = match state.input.path.extension() {
Some(s) => s.to_str().unwrap(), Some(s) => s.to_str().unwrap(),
@ -294,8 +315,12 @@ impl<'a> Generator<'a> {
// Writes header for the `impl` for `TraitFromPathName` or `Template` // Writes header for the `impl` for `TraitFromPathName` or `Template`
// for the given context struct. // for the given context struct.
fn write_header(&mut self, state: &'a State, target: &str, fn write_header(
params: Option<Vec<syn::GenericParam>>) { &mut self,
state: &'a State,
target: &str,
params: Option<Vec<syn::GenericParam>>,
) {
let mut generics = state.input.ast.generics.clone(); let mut generics = state.input.ast.generics.clone();
if let Some(params) = params { if let Some(params) = params {
for param in params { for param in params {
@ -322,61 +347,64 @@ impl<'a> Generator<'a> {
match *n { match *n {
Node::Lit(lws, val, rws) => { Node::Lit(lws, val, rws) => {
self.write_lit(lws, val, rws); self.write_lit(lws, val, rws);
}, }
Node::Comment(ref ws) => { Node::Comment(ref ws) => {
self.write_comment(ws); self.write_comment(ws);
}, }
Node::Expr(ref ws, ref val) => { Node::Expr(ref ws, ref val) => {
self.write_expr(state, ws, val); self.write_expr(state, ws, val);
}, }
Node::LetDecl(ref ws, ref var) => { Node::LetDecl(ref ws, ref var) => {
self.write_let_decl(ws, var); self.write_let_decl(ws, var);
}, }
Node::Let(ref ws, ref var, ref val) => { Node::Let(ref ws, ref var, ref val) => {
self.write_let(ws, var, val); self.write_let(ws, var, val);
}, }
Node::Cond(ref conds, ref ws) => { Node::Cond(ref conds, ref ws) => {
self.write_cond(state, conds, ws); self.write_cond(state, conds, ws);
}, }
Node::Match(ref ws1, ref expr, inter, ref arms, ref ws2) => { Node::Match(ref ws1, ref expr, inter, ref arms, ref ws2) => {
self.write_match(state, ws1, expr, inter, arms, ws2); self.write_match(state, ws1, expr, inter, arms, ws2);
}, }
Node::Loop(ref ws1, ref var, ref iter, ref body, ref ws2) => { Node::Loop(ref ws1, ref var, ref iter, ref body, ref ws2) => {
self.write_loop(state, ws1, var, iter, body, ws2); self.write_loop(state, ws1, var, iter, body, ws2);
}, }
Node::BlockDef(ref ws1, name, _, ref ws2) => { Node::BlockDef(ref ws1, name, _, ref ws2) => {
if let AstLevel::Nested = level { if let AstLevel::Nested = level {
panic!("blocks ('{}') are only allowed at the top level of a template \ panic!(
or another block", name); "blocks ('{}') are only allowed at the top level of a template \
or another block",
name
);
} }
self.write_block(ws1, name, ws2); self.write_block(ws1, name, ws2);
}, }
Node::Include(ref ws, path) => { Node::Include(ref ws, path) => {
self.handle_include(state, ws, path); self.handle_include(state, ws, path);
}, }
Node::Call(ref ws, scope, name, ref args) => { Node::Call(ref ws, scope, name, ref args) => {
self.write_call(state, ws, scope, name, args); self.write_call(state, ws, scope, name, args);
}, }
Node::Macro(_, ref m) => { Node::Macro(_, ref m) => {
if level != AstLevel::Top { if level != AstLevel::Top {
panic!("macro blocks only allowed at the top level"); panic!("macro blocks only allowed at the top level");
} }
self.flush_ws(&m.ws1); self.flush_ws(&m.ws1);
self.prepare_ws(&m.ws2); self.prepare_ws(&m.ws2);
}, }
Node::Import(ref ws, _, _) => { Node::Import(ref ws, _, _) => {
if level != AstLevel::Top { if level != AstLevel::Top {
panic!("import blocks only allowed at the top level"); panic!("import blocks only allowed at the top level");
} }
self.handle_ws(ws); self.handle_ws(ws);
}, }
Node::Extends(_) => { Node::Extends(_) => {
if level != AstLevel::Top { if level != AstLevel::Top {
panic!("extend blocks only allowed at the top level"); panic!("extend blocks only allowed at the top level");
} }
// No whitespace handling: child template top-level is not used, // No whitespace handling: child template top-level is not used,
// except for the blocks defined in it. // except for the blocks defined in it.
}, }
} }
} }
} }
@ -418,11 +446,11 @@ impl<'a> Generator<'a> {
self.write("} else if "); self.write("} else if ");
} }
self.write(&expr_code); self.write(&expr_code);
}, }
None => { None => {
self.dedent(); self.dedent();
self.write("} else"); self.write("} else");
}, }
} }
self.writeln(" {"); self.writeln(" {");
self.locals.push(); self.locals.push();
@ -433,8 +461,15 @@ impl<'a> Generator<'a> {
self.writeln("}"); self.writeln("}");
} }
fn write_match(&mut self, state: &'a State, ws1: &WS, expr: &Expr, inter: Option<&'a str>, fn write_match(
arms: &'a [When], ws2: &WS) { &mut self,
state: &'a State,
ws1: &WS,
expr: &Expr,
inter: Option<&'a str>,
arms: &'a [When],
ws2: &WS,
) {
self.flush_ws(ws1); self.flush_ws(ws1);
if let Some(inter) = inter { if let Some(inter) = inter {
if !inter.is_empty() { if !inter.is_empty() {
@ -450,7 +485,7 @@ impl<'a> Generator<'a> {
match *variant { match *variant {
Some(ref param) => { Some(ref param) => {
self.visit_match_variant(param); self.visit_match_variant(param);
}, }
None => self.write("_"), None => self.write("_"),
}; };
if !params.is_empty() { if !params.is_empty() {
@ -477,8 +512,15 @@ impl<'a> Generator<'a> {
self.handle_ws(ws2); self.handle_ws(ws2);
} }
fn write_loop(&mut self, state: &'a State, ws1: &WS, var: &'a Target, iter: &Expr, fn write_loop(
body: &'a [Node], ws2: &WS) { &mut self,
state: &'a State,
ws1: &WS,
var: &'a Target,
iter: &Expr,
body: &'a [Node],
ws2: &WS,
) {
self.handle_ws(ws1); self.handle_ws(ws1);
self.locals.push(); self.locals.push();
@ -497,8 +539,14 @@ impl<'a> Generator<'a> {
self.locals.pop(); self.locals.pop();
} }
fn write_call(&mut self, state: &'a State, ws: &WS, scope: Option<&str>, name: &str, fn write_call(
args: &[Expr]) { &mut self,
state: &'a State,
ws: &WS,
scope: Option<&str>,
name: &str,
args: &[Expr],
) {
let def = state.macros.get(&(scope, name)).unwrap_or_else(|| { let def = state.macros.get(&(scope, name)).unwrap_or_else(|| {
if let Some(s) = scope { if let Some(s) = scope {
panic!(format!("macro '{}::{}' not found", s, name)); panic!(format!("macro '{}::{}' not found", s, name));
@ -513,8 +561,10 @@ impl<'a> Generator<'a> {
self.prepare_ws(&def.ws1); self.prepare_ws(&def.ws1);
for (i, arg) in def.args.iter().enumerate() { for (i, arg) in def.args.iter().enumerate() {
let expr_code = self.visit_expr_root(args.get(i) let expr_code = self.visit_expr_root(
.expect(&format!("macro '{}' takes more than {} arguments", name, i))); args.get(i)
.expect(&format!("macro '{}' takes more than {} arguments", name, i)),
);
self.write(&format!("let {} = &{};", arg, expr_code)); self.write(&format!("let {} = &{};", arg, expr_code));
self.locals.insert(arg); self.locals.insert(arg);
} }
@ -547,7 +597,7 @@ impl<'a> Generator<'a> {
Target::Name(name) => { Target::Name(name) => {
self.locals.insert(name); self.locals.insert(name);
self.write(name); self.write(name);
}, }
} }
self.writeln(";"); self.writeln(";");
} }
@ -564,18 +614,14 @@ impl<'a> Generator<'a> {
self.locals.insert(name); self.locals.insert(name);
} }
self.write(name); self.write(name);
}, }
} }
self.write(&format!(" = {};", &code)); self.write(&format!(" = {};", &code));
} }
fn write_block(&mut self, ws1: &WS, name: &str, ws2: &WS) { fn write_block(&mut self, ws1: &WS, name: &str, ws2: &WS) {
self.flush_ws(ws1); self.flush_ws(ws1);
let ctx = if self.impl_blocks { let ctx = if self.impl_blocks { "timpl" } else { "self" };
"timpl"
} else {
"self"
};
self.writeln(&format!("{}.render_block_{}_into(writer)?;", ctx, name)); self.writeln(&format!("{}.render_block_{}_into(writer)?;", ctx, name));
self.prepare_ws(ws2); self.prepare_ws(ws2);
} }
@ -590,9 +636,7 @@ impl<'a> Generator<'a> {
use super::input::EscapeMode::*; use super::input::EscapeMode::*;
self.write("writer.write_fmt(format_args!(\"{}\", "); self.write("writer.write_fmt(format_args!(\"{}\", ");
self.write(match (wrapped, &state.input.escaping) { self.write(match (wrapped, &state.input.escaping) {
(Wrapped, &Html) | (Wrapped, &Html) | (Wrapped, &None) | (Unwrapped, &None) => "askama_expr",
(Wrapped, &None) |
(Unwrapped, &None) => "askama_expr",
(Unwrapped, &Html) => "&::askama::MarkupDisplay::from(askama_expr)", (Unwrapped, &Html) => "&::askama::MarkupDisplay::from(askama_expr)",
}); });
self.writeln("))?;"); self.writeln("))?;");
@ -644,7 +688,7 @@ impl<'a> Generator<'a> {
Expr::Group(ref inner) => self.visit_group(inner, code), Expr::Group(ref inner) => self.visit_group(inner, code),
Expr::MethodCall(ref obj, method, ref args) => { Expr::MethodCall(ref obj, method, ref args) => {
self.visit_method_call(obj, method, args, code) self.visit_method_call(obj, method, args, code)
}, }
} }
} }
@ -659,11 +703,11 @@ impl<'a> Generator<'a> {
MatchVariant::Name(s) => { MatchVariant::Name(s) => {
code.push_str(s); code.push_str(s);
DisplayWrap::Unwrapped DisplayWrap::Unwrapped
}, }
MatchVariant::Path(ref s) => { MatchVariant::Path(ref s) => {
code.push_str(&s.join("::")); code.push_str(&s.join("::"));
DisplayWrap::Unwrapped DisplayWrap::Unwrapped
}, }
}; };
self.write(&code); self.write(&code);
wrapped wrapped
@ -677,7 +721,7 @@ impl<'a> Generator<'a> {
MatchParameter::Name(s) => { MatchParameter::Name(s) => {
code.push_str(s); code.push_str(s);
DisplayWrap::Unwrapped DisplayWrap::Unwrapped
}, }
}; };
self.write(&code); self.write(&code);
wrapped wrapped
@ -772,8 +816,13 @@ impl<'a> Generator<'a> {
DisplayWrap::Unwrapped DisplayWrap::Unwrapped
} }
fn visit_method_call(&mut self, obj: &Expr, method: &str, args: &[Expr], code: &mut String) fn visit_method_call(
-> DisplayWrap { &mut self,
obj: &Expr,
method: &str,
args: &[Expr],
code: &mut String,
) -> DisplayWrap {
if let Expr::Var("self") = obj { if let Expr::Var("self") = obj {
code.push_str("self"); code.push_str("self");
} else { } else {
@ -792,8 +841,13 @@ impl<'a> Generator<'a> {
DisplayWrap::Unwrapped DisplayWrap::Unwrapped
} }
fn visit_binop(&mut self, op: &str, left: &Expr, right: &Expr, code: &mut String) fn visit_binop(
-> DisplayWrap { &mut self,
op: &str,
left: &Expr,
right: &Expr,
code: &mut String,
) -> DisplayWrap {
self.visit_expr(left, code); self.visit_expr(left, code);
code.push_str(&format!(" {} ", op)); code.push_str(&format!(" {} ", op));
self.visit_expr(right, code); self.visit_expr(right, code);
@ -926,17 +980,29 @@ impl<'a> Generator<'a> {
} }
} }
struct SetChain<'a, T: 'a> where T: cmp::Eq + hash::Hash { struct SetChain<'a, T: 'a>
where
T: cmp::Eq + hash::Hash,
{
parent: Option<&'a SetChain<'a, T>>, parent: Option<&'a SetChain<'a, T>>,
scopes: Vec<HashSet<T>>, scopes: Vec<HashSet<T>>,
} }
impl<'a, T: 'a> SetChain<'a, T> where T: cmp::Eq + hash::Hash { impl<'a, T: 'a> SetChain<'a, T>
where
T: cmp::Eq + hash::Hash,
{
fn new() -> SetChain<'a, T> { fn new() -> SetChain<'a, T> {
SetChain { parent: None, scopes: vec![HashSet::new()] } SetChain {
parent: None,
scopes: vec![HashSet::new()],
}
} }
fn with_parent<'p>(parent: &'p SetChain<T>) -> SetChain<'p, T> { fn with_parent<'p>(parent: &'p SetChain<T>) -> SetChain<'p, T> {
SetChain { parent: Some(parent), scopes: vec![HashSet::new()] } SetChain {
parent: Some(parent),
scopes: vec![HashSet::new()],
}
} }
fn contains(&self, val: T) -> bool { fn contains(&self, val: T) -> bool {
self.scopes.iter().rev().any(|set| set.contains(&val)) || match self.parent { self.scopes.iter().rev().any(|set| set.contains(&val)) || match self.parent {
@ -962,13 +1028,9 @@ fn get_parent_type(ast: &syn::DeriveInput) -> Option<&syn::Type> {
fields: syn::Fields::Named(ref fields), fields: syn::Fields::Named(ref fields),
.. ..
}) => fields.named.iter().filter_map(|f| { }) => fields.named.iter().filter_map(|f| {
f.ident.as_ref().and_then(|name| { f.ident
if name == "_parent" { .as_ref()
Some(&f.ty) .and_then(|name| if name == "_parent" { Some(&f.ty) } else { None })
} else {
None
}
})
}), }),
_ => panic!("derive(Template) only works for struct items"), _ => panic!("derive(Template) only works for struct items"),
}.next() }.next()

View File

@ -4,7 +4,6 @@ use std::path::{Path, PathBuf};
use syn; use syn;
pub struct TemplateInput<'a> { pub struct TemplateInput<'a> {
pub ast: &'a syn::DeriveInput, pub ast: &'a syn::DeriveInput,
pub source: Source, pub source: Source,
@ -20,7 +19,10 @@ impl<'a> TemplateInput<'a> {
.iter() .iter()
.find(|a| a.interpret_meta().unwrap().name() == "template"); .find(|a| a.interpret_meta().unwrap().name() == "template");
if attr.is_none() { if attr.is_none() {
panic!(format!("'template' attribute not found on struct '{}'", ast.ident)); panic!(format!(
"'template' attribute not found on struct '{}'",
ast.ident
));
} }
let attr = attr.unwrap(); let attr = attr.unwrap();
@ -75,18 +77,20 @@ impl<'a> TemplateInput<'a> {
match (&source, ext.is_some()) { match (&source, ext.is_some()) {
(&Source::Path(_), true) => { (&Source::Path(_), true) => {
panic!("'ext' attribute cannot be used with 'path' attribute") panic!("'ext' attribute cannot be used with 'path' attribute")
}, }
(&Source::Source(_), false) => { (&Source::Source(_), false) => {
panic!("must include 'ext' attribute when using 'source' attribute") panic!("must include 'ext' attribute when using 'source' attribute")
}, }
_ => {}, _ => {}
} }
let escaping = match escaping { let escaping = match escaping {
Some(m) => m, Some(m) => m,
None => { None => {
let ext = match source { let ext = match source {
Source::Path(ref p) => Source::Path(ref p) => Path::new(p)
Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or(""), .extension()
.map(|s| s.to_str().unwrap())
.unwrap_or(""),
Source::Source(_) => ext.as_ref().unwrap(), // Already panicked if None Source::Source(_) => ext.as_ref().unwrap(), // Already panicked if None
}; };
if HTML_EXTENSIONS.contains(&ext) { if HTML_EXTENSIONS.contains(&ext) {
@ -94,7 +98,7 @@ impl<'a> TemplateInput<'a> {
} else { } else {
EscapeMode::None EscapeMode::None
} }
}, }
}; };
let path = match source { let path = match source {

View File

@ -7,8 +7,8 @@ extern crate proc_macro2;
extern crate quote; extern crate quote;
extern crate syn; extern crate syn;
mod input;
mod generator; mod generator;
mod input;
mod parser; mod parser;
use input::{Print, Source}; use input::{Print, Source};
@ -36,7 +36,7 @@ fn build_template(ast: &syn::DeriveInput) -> String {
let input = input::TemplateInput::new(ast); let input = input::TemplateInput::new(ast);
let source = match input.source { let source = match input.source {
Source::Source(ref s) => s.clone(), Source::Source(ref s) => s.clone(),
Source::Path(_) => path::get_template_source(&input.path) Source::Path(_) => path::get_template_source(&input.path),
}; };
let nodes = parser::parse(&source); let nodes = parser::parse(&source);

View File

@ -1,5 +1,5 @@
use std::error::Error as ErrorTrait;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::error::{Error as ErrorTrait};
pub type Result<I> = ::std::result::Result<I, Error>; pub type Result<I> = ::std::result::Result<I, Error>;
@ -23,7 +23,7 @@ pub type Result<I> = ::std::result::Result<I, Error>;
/// bring to this crate are small, which is why /// bring to this crate are small, which is why
/// `std::error::Error` was used. /// `std::error::Error` was used.
/// ///
#[derive(Debug, )] #[derive(Debug)]
pub enum Error { pub enum Error {
/// formatting error /// formatting error
Fmt(fmt::Error), Fmt(fmt::Error),
@ -40,13 +40,12 @@ pub enum Error {
} }
impl ErrorTrait for Error { impl ErrorTrait for Error {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
Error::Fmt(ref err) => err.description(), Error::Fmt(ref err) => err.description(),
#[cfg(feature = "serde-json")] #[cfg(feature = "serde-json")]
Error::Json(ref err) => err.description(), Error::Json(ref err) => err.description(),
_ => "unknown error: __Nonexhaustive" _ => "unknown error: __Nonexhaustive",
} }
} }
@ -55,7 +54,7 @@ impl ErrorTrait for Error {
Error::Fmt(ref err) => err.cause(), Error::Fmt(ref err) => err.cause(),
#[cfg(feature = "serde-json")] #[cfg(feature = "serde-json")]
Error::Json(ref err) => err.cause(), Error::Json(ref err) => err.cause(),
_ => None _ => None,
} }
} }
} }
@ -67,7 +66,7 @@ impl Display for Error {
#[cfg(feature = "serde-json")] #[cfg(feature = "serde-json")]
Error::Json(ref err) => write!(formatter, "json conversion error: {}", err), Error::Json(ref err) => write!(formatter, "json conversion error: {}", err),
_ => write!(formatter, "unknown error: __Nonexhaustive") _ => write!(formatter, "unknown error: __Nonexhaustive"),
} }
} }
} }
@ -85,7 +84,6 @@ impl From<::serde_json::Error> for Error {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Error; use super::Error;

View File

@ -1,13 +1,18 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum MarkupDisplay<T> where T: Display { pub enum MarkupDisplay<T>
where
T: Display,
{
Safe(T), Safe(T),
Unsafe(T), Unsafe(T),
} }
impl<T> MarkupDisplay<T> where T: Display { impl<T> MarkupDisplay<T>
where
T: Display,
{
pub fn mark_safe(self) -> MarkupDisplay<T> { pub fn mark_safe(self) -> MarkupDisplay<T> {
match self { match self {
MarkupDisplay::Unsafe(t) => MarkupDisplay::Safe(t), MarkupDisplay::Unsafe(t) => MarkupDisplay::Safe(t),
@ -21,13 +26,19 @@ impl<T> MarkupDisplay<T> where T: Display {
} }
} }
impl<T> From<T> for MarkupDisplay<T> where T: Display { impl<T> From<T> for MarkupDisplay<T>
where
T: Display,
{
fn from(t: T) -> MarkupDisplay<T> { fn from(t: T) -> MarkupDisplay<T> {
MarkupDisplay::Unsafe(t) MarkupDisplay::Unsafe(t)
} }
} }
impl<T> Display for MarkupDisplay<T> where T: Display { impl<T> Display for MarkupDisplay<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self { match *self {
MarkupDisplay::Unsafe(_) => write!(f, "{}", escape(self.unsafe_string())), MarkupDisplay::Unsafe(_) => write!(f, "{}", escape(self.unsafe_string())),
@ -36,7 +47,6 @@ impl<T> Display for MarkupDisplay<T> where T: Display {
} }
} }
fn escapable(b: u8) -> bool { fn escapable(b: u8) -> bool {
match b { match b {
b'<' | b'>' | b'&' | b'"' | b'\'' | b'/' => true, b'<' | b'>' | b'&' | b'"' | b'\'' | b'/' => true,
@ -65,12 +75,24 @@ pub fn escape(s: String) -> String {
} }
start = *idx + 1; start = *idx + 1;
match bytes[*idx] { match bytes[*idx] {
b'<' => { res.extend(b"&lt;"); }, b'<' => {
b'>' => { res.extend(b"&gt;"); }, res.extend(b"&lt;");
b'&' => { res.extend(b"&amp;"); }, }
b'"' => { res.extend(b"&quot;"); }, b'>' => {
b'\'' => { res.extend(b"&#x27;"); }, res.extend(b"&gt;");
b'/' => { res.extend(b"&#x2f;"); }, }
b'&' => {
res.extend(b"&amp;");
}
b'"' => {
res.extend(b"&quot;");
}
b'\'' => {
res.extend(b"&#x27;");
}
b'/' => {
res.extend(b"&#x2f;");
}
_ => panic!("incorrect indexing"), _ => panic!("incorrect indexing"),
} }
} }
@ -81,7 +103,6 @@ pub fn escape(s: String) -> String {
String::from_utf8(res).unwrap() String::from_utf8(res).unwrap()
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1,9 +1,8 @@
use error::{Error, Result};
use serde::Serialize; use serde::Serialize;
use serde_json; use serde_json;
use error::{Error, Result};
use MarkupDisplay; use MarkupDisplay;
/// Serialize to JSON (requires `serde-json` feature) /// Serialize to JSON (requires `serde-json` feature)
/// ///
/// ## Errors /// ## Errors
@ -17,7 +16,6 @@ pub fn json<S: Serialize>(s: &S) -> Result<MarkupDisplay<String>> {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -11,9 +11,8 @@ pub use self::json::json;
use std::fmt; use std::fmt;
use escaping::{self, MarkupDisplay};
use super::Result; use super::Result;
use escaping::{self, MarkupDisplay};
// This is used by the code generator to decide whether a named filter is part of // This is used by the code generator to decide whether a named filter is part of
// Askama or should refer to a local `filters` module. It should contain all the // Askama or should refer to a local `filters` module. It should contain all the
@ -32,11 +31,10 @@ pub const BUILT_IN_FILTERS: [&str; 10] = [
"json", // Optional feature; reserve the name anyway "json", // Optional feature; reserve the name anyway
]; ];
pub fn safe<D, I>(v: I) -> Result<MarkupDisplay<D>> pub fn safe<D, I>(v: I) -> Result<MarkupDisplay<D>>
where where
D: fmt::Display, D: fmt::Display,
MarkupDisplay<D>: From<I> MarkupDisplay<D>: From<I>,
{ {
let res: MarkupDisplay<D> = v.into(); let res: MarkupDisplay<D> = v.into();
Ok(res.mark_safe()) Ok(res.mark_safe())
@ -46,7 +44,7 @@ where
pub fn escape<D, I>(i: I) -> Result<MarkupDisplay<String>> pub fn escape<D, I>(i: I) -> Result<MarkupDisplay<String>>
where where
D: fmt::Display, D: fmt::Display,
MarkupDisplay<D>: From<I> MarkupDisplay<D>: From<I>,
{ {
let md: MarkupDisplay<D> = i.into(); let md: MarkupDisplay<D> = i.into();
Ok(MarkupDisplay::Safe(escaping::escape(md.unsafe_string()))) Ok(MarkupDisplay::Safe(escaping::escape(md.unsafe_string())))
@ -56,7 +54,7 @@ where
pub fn e<D, I>(i: I) -> Result<MarkupDisplay<String>> pub fn e<D, I>(i: I) -> Result<MarkupDisplay<String>>
where where
D: fmt::Display, D: fmt::Display,
MarkupDisplay<D>: From<I> MarkupDisplay<D>: From<I>,
{ {
escape(i) escape(i)
} }
@ -99,9 +97,10 @@ pub fn trim(s: &fmt::Display) -> Result<String> {
/// Joins iterable into a string separated by provided argument /// Joins iterable into a string separated by provided argument
pub fn join<T, I, S>(input: I, separator: S) -> Result<String> pub fn join<T, I, S>(input: I, separator: S) -> Result<String>
where T: fmt::Display, where
T: fmt::Display,
I: Iterator<Item = T>, I: Iterator<Item = T>,
S: AsRef<str> S: AsRef<str>,
{ {
let separator: &str = separator.as_ref(); let separator: &str = separator.as_ref();
@ -118,7 +117,6 @@ pub fn join<T, I, S>(input: I, separator: S) -> Result<String>
Ok(rv) Ok(rv)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -5,8 +5,8 @@ extern crate serde;
#[cfg(feature = "serde-json")] #[cfg(feature = "serde-json")]
extern crate serde_json; extern crate serde_json;
pub use escaping::MarkupDisplay;
pub use error::{Error, Result}; pub use error::{Error, Result};
pub use escaping::MarkupDisplay;
mod error; mod error;
pub mod filters; pub mod filters;
pub mod path; pub mod path;

View File

@ -10,7 +10,7 @@ pub fn get_template_source(tpl_path: &Path) -> String {
Err(_) => { Err(_) => {
let msg = format!("unable to open template file '{}'", &path.to_str().unwrap()); let msg = format!("unable to open template file '{}'", &path.to_str().unwrap());
panic!(msg) panic!(msg)
}, }
Ok(f) => f, Ok(f) => f,
}; };
let mut s = String::new(); let mut s = String::new();
@ -38,7 +38,11 @@ pub fn find_template_from_path(path: &str, start_at: Option<&Path>) -> PathBuf {
if fs_abs_path.exists() { if fs_abs_path.exists() {
path.to_owned() path.to_owned()
} else { } else {
panic!(format!("template {:?} not found at {:?}", path.to_str().unwrap(), fs_abs_path)); panic!(format!(
"template {:?} not found at {:?}",
path.to_str().unwrap(),
fs_abs_path
));
} }
} }
@ -50,8 +54,8 @@ pub fn template_dir() -> PathBuf {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{find_template_from_path, get_template_source};
use super::Path; use super::Path;
use super::{find_template_from_path, get_template_source};
#[test] #[test]
fn get_source() { fn get_source() {

View File

@ -6,7 +6,6 @@ extern crate serde_json;
use askama::Template; use askama::Template;
use serde_json::Value; use serde_json::Value;
#[derive(Template)] #[derive(Template)]
#[template(path = "filters.html")] #[template(path = "filters.html")]
struct TestTemplate { struct TestTemplate {
@ -25,7 +24,6 @@ fn filter_escape() {
); );
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "format.html", escape = "none")] #[template(path = "format.html", escape = "none")]
struct FormatTemplate<'a> { struct FormatTemplate<'a> {
@ -38,7 +36,6 @@ fn filter_format() {
assert_eq!(t.render().unwrap(), "\"formatted\""); assert_eq!(t.render().unwrap(), "\"formatted\"");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{{ s|myfilter }}", ext = "txt")] #[template(source = "{{ s|myfilter }}", ext = "txt")]
struct MyFilterTemplate<'a> { struct MyFilterTemplate<'a> {
@ -62,7 +59,6 @@ fn test_my_filter() {
assert_eq!(t.render().unwrap(), "faa"); assert_eq!(t.render().unwrap(), "faa");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "filters_join.html")] #[template(path = "filters_join.html")]
struct JoinTemplate<'a> { struct JoinTemplate<'a> {
@ -71,7 +67,9 @@ struct JoinTemplate<'a> {
#[test] #[test]
fn test_join() { fn test_join() {
let t = JoinTemplate { s: &["foo", "bar", "bazz"] }; let t = JoinTemplate {
s: &["foo", "bar", "bazz"],
};
assert_eq!(t.render().unwrap(), "foo, bar, bazz"); assert_eq!(t.render().unwrap(), "foo, bar, bazz");
} }
@ -83,11 +81,12 @@ struct VecJoinTemplate {
#[test] #[test]
fn test_vec_join() { fn test_vec_join() {
let t = VecJoinTemplate { s: vec!["foo".into(), "bar".into(), "bazz".into()] }; let t = VecJoinTemplate {
s: vec!["foo".into(), "bar".into(), "bazz".into()],
};
assert_eq!(t.render().unwrap(), "foo, bar, bazz"); assert_eq!(t.render().unwrap(), "foo, bar, bazz");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "json.html")] #[template(path = "json.html")]
struct JsonTemplate<'a> { struct JsonTemplate<'a> {
@ -98,7 +97,10 @@ struct JsonTemplate<'a> {
#[test] #[test]
fn test_json() { fn test_json() {
let val = json!({"arr": [ "one", 2, true, null ]}); let val = json!({"arr": [ "one", 2, true, null ]});
let t = JsonTemplate { foo: "a", bar: &val }; let t = JsonTemplate {
foo: "a",
bar: &val,
};
// Note: the json filter lacks a way to specify initial indentation // Note: the json filter lacks a way to specify initial indentation
assert_eq!( assert_eq!(
t.render().unwrap(), t.render().unwrap(),
@ -116,7 +118,6 @@ fn test_json() {
); );
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{{ x|mytrim|safe }}", ext = "html")] #[template(source = "{{ x|mytrim|safe }}", ext = "html")]
struct NestedFilterTemplate { struct NestedFilterTemplate {
@ -125,11 +126,12 @@ struct NestedFilterTemplate {
#[test] #[test]
fn test_nested_filter_ref() { fn test_nested_filter_ref() {
let t = NestedFilterTemplate { x: " floo & bar".to_string() }; let t = NestedFilterTemplate {
x: " floo & bar".to_string(),
};
assert_eq!(t.render().unwrap(), "floo & bar"); assert_eq!(t.render().unwrap(), "floo & bar");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{% let p = baz.print(foo.as_ref()) %}{{ p|upper }}", ext = "html")] #[template(source = "{% let p = baz.print(foo.as_ref()) %}{{ p|upper }}", ext = "html")]
struct FilterLetFilterTemplate { struct FilterLetFilterTemplate {
@ -147,6 +149,9 @@ impl Baz {
#[test] #[test]
fn test_filter_let_filter() { fn test_filter_let_filter() {
let t = FilterLetFilterTemplate { foo: " bar ".to_owned(), baz: Baz {} }; let t = FilterLetFilterTemplate {
foo: " bar ".to_owned(),
baz: Baz {},
};
assert_eq!(t.render().unwrap(), "BAR"); assert_eq!(t.render().unwrap(), "BAR");
} }

View File

@ -6,7 +6,8 @@ use askama::Template;
#[derive(Template)] // this will generate the code... #[derive(Template)] // this will generate the code...
#[template(path = "hello.html")] // using the template in this path, relative #[template(path = "hello.html")] // using the template in this path, relative
// to the templates dir in the crate root // to the templates dir in the crate root
struct HelloTemplate<'a> { // the name of the struct can be anything struct HelloTemplate<'a> {
// the name of the struct can be anything
name: &'a str, // the field name should match the variable name name: &'a str, // the field name should match the variable name
// in your template // in your template
} }

View File

@ -23,14 +23,15 @@ fn test_use_base_directly() {
#[test] #[test]
fn test_simple_extends() { fn test_simple_extends() {
let t = ChildTemplate { _parent: BaseTemplate { title: "Bar" } }; let t = ChildTemplate {
_parent: BaseTemplate { title: "Bar" },
};
assert_eq!( assert_eq!(
t.render().unwrap(), t.render().unwrap(),
"Bar\n(Bar) Content goes here\nFoo\nCopyright 2017" "Bar\n(Bar) Content goes here\nFoo\nCopyright 2017"
); );
} }
pub mod parent { pub mod parent {
use askama::Template; use askama::Template;
#[derive(Template)] #[derive(Template)]
@ -41,8 +42,8 @@ pub mod parent {
} }
pub mod child { pub mod child {
use askama::Template;
use super::parent::*; use super::parent::*;
use askama::Template;
#[derive(Template)] #[derive(Template)]
#[template(path = "child.html")] #[template(path = "child.html")]
pub struct ChildTemplate<'a> { pub struct ChildTemplate<'a> {
@ -52,15 +53,15 @@ pub mod child {
#[test] #[test]
fn test_different_module() { fn test_different_module() {
let t = child::ChildTemplate { _parent: parent::BaseTemplate { title: "a" } }; let t = child::ChildTemplate {
_parent: parent::BaseTemplate { title: "a" },
};
assert_eq!( assert_eq!(
t.render().unwrap(), t.render().unwrap(),
"a\n(a) Content goes here\nFoo\nCopyright 2017" "a\n(a) Content goes here\nFoo\nCopyright 2017"
); );
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "nested-base.html")] #[template(path = "nested-base.html")]
struct NestedBaseTemplate {} struct NestedBaseTemplate {}
@ -73,6 +74,8 @@ struct NestedChildTemplate {
#[test] #[test]
fn test_nested_blocks() { fn test_nested_blocks() {
let t = NestedChildTemplate { _parent: NestedBaseTemplate {} }; let t = NestedChildTemplate {
_parent: NestedBaseTemplate {},
};
assert_eq!(t.render().unwrap(), "\ndurpy\n"); assert_eq!(t.render().unwrap(), "\ndurpy\n");
} }

View File

@ -11,11 +11,12 @@ struct ForTemplate<'a> {
#[test] #[test]
fn test_for() { fn test_for() {
let s = ForTemplate { strings: vec!["A", "alfa", "1"] }; let s = ForTemplate {
strings: vec!["A", "alfa", "1"],
};
assert_eq!(s.render().unwrap(), "0. A\n1. alfa\n2. 1\n"); assert_eq!(s.render().unwrap(), "0. A\n1. alfa\n2. 1\n");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "nested-for.html")] #[template(path = "nested-for.html")]
struct NestedForTemplate<'a> { struct NestedForTemplate<'a> {
@ -26,6 +27,8 @@ struct NestedForTemplate<'a> {
fn test_nested_for() { fn test_nested_for() {
let alpha = vec!["a", "b", "c"]; let alpha = vec!["a", "b", "c"];
let numbers = vec!["one", "two"]; let numbers = vec!["one", "two"];
let s = NestedForTemplate { seqs: vec![&alpha, &numbers] }; let s = NestedForTemplate {
seqs: vec![&alpha, &numbers],
};
assert_eq!(s.render().unwrap(), "1\n 0a1b2c2\n 0one1two"); assert_eq!(s.render().unwrap(), "1\n 0a1b2c2\n 0one1two");
} }

View File

@ -15,7 +15,6 @@ struct MatchOptRefTemplate<'a> {
item: &'a Option<&'a str>, item: &'a Option<&'a str>,
} }
#[test] #[test]
fn test_match_option() { fn test_match_option() {
let s = MatchOptTemplate { item: Some("foo") }; let s = MatchOptTemplate { item: Some("foo") };
@ -79,7 +78,9 @@ struct MatchCustomEnumTemplate {
#[test] #[test]
fn test_match_custom_enum() { fn test_match_custom_enum() {
let s = MatchCustomEnumTemplate { color: Color::Rgb(160, 0, 255) }; let s = MatchCustomEnumTemplate {
color: Color::Rgb(160, 0, 255),
};
assert_eq!(s.render().unwrap(), "\n\nColorful: #A000FF\n"); assert_eq!(s.render().unwrap(), "\n\nColorful: #A000FF\n");
} }

View File

@ -21,7 +21,6 @@ fn test_self_method() {
assert_eq!(t.render().unwrap(), "foo"); assert_eq!(t.render().unwrap(), "foo");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{{ self.get_s() }} {{ t.get_s() }}", ext = "txt")] #[template(source = "{{ self.get_s() }} {{ t.get_s() }}", ext = "txt")]
struct NestedSelfMethodTemplate<'a> { struct NestedSelfMethodTemplate<'a> {

View File

@ -17,7 +17,6 @@ fn test_compare() {
assert_eq!(t.render().unwrap(), "tf\ntf\ntf\ntf\ntf\ntf"); assert_eq!(t.render().unwrap(), "tf\ntf\ntf\ntf\ntf\ntf");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "operators.html")] #[template(path = "operators.html")]
struct OperatorsTemplate { struct OperatorsTemplate {
@ -32,7 +31,6 @@ fn test_operators() {
assert_eq!(t.render().unwrap(), "muldivmodaddrshlshbandbxorborandor"); assert_eq!(t.render().unwrap(), "muldivmodaddrshlshbandbxorborandor");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "precedence.html")] #[template(path = "precedence.html")]
struct PrecedenceTemplate {} struct PrecedenceTemplate {}

View File

@ -8,8 +8,8 @@ extern crate rocket;
use askama::Template; use askama::Template;
use rocket::local::Client;
use rocket::http::{ContentType, Status}; use rocket::http::{ContentType, Status};
use rocket::local::Client;
#[derive(Template)] #[derive(Template)]
#[template(path = "hello.html")] #[template(path = "hello.html")]

View File

@ -3,7 +3,6 @@ extern crate askama;
use askama::Template; use askama::Template;
#[derive(Template)] #[derive(Template)]
#[template(path = "simple.html")] #[template(path = "simple.html")]
struct VariablesTemplate<'a> { struct VariablesTemplate<'a> {
@ -28,7 +27,6 @@ fn test_variables() {
); );
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "if.html")] #[template(path = "if.html")]
struct IfTemplate { struct IfTemplate {
@ -41,7 +39,6 @@ fn test_if() {
assert_eq!(s.render().unwrap(), "true"); assert_eq!(s.render().unwrap(), "true");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "else.html")] #[template(path = "else.html")]
struct ElseTemplate { struct ElseTemplate {
@ -54,7 +51,6 @@ fn test_else() {
assert_eq!(s.render().unwrap(), "false"); assert_eq!(s.render().unwrap(), "false");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "else-if.html")] #[template(path = "else-if.html")]
struct ElseIfTemplate { struct ElseIfTemplate {
@ -64,11 +60,13 @@ struct ElseIfTemplate {
#[test] #[test]
fn test_else_if() { fn test_else_if() {
let s = ElseIfTemplate { cond: false, check: true }; let s = ElseIfTemplate {
cond: false,
check: true,
};
assert_eq!(s.render().unwrap(), "checked"); assert_eq!(s.render().unwrap(), "checked");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "literals.html")] #[template(path = "literals.html")]
struct LiteralsTemplate {} struct LiteralsTemplate {}
@ -79,7 +77,6 @@ fn test_literals() {
assert_eq!(s.render().unwrap(), "a"); assert_eq!(s.render().unwrap(), "a");
} }
struct Holder { struct Holder {
a: usize, a: usize,
} }
@ -92,7 +89,9 @@ struct AttrTemplate {
#[test] #[test]
fn test_attr() { fn test_attr() {
let t = AttrTemplate { inner: Holder { a: 5 } }; let t = AttrTemplate {
inner: Holder { a: 5 },
};
assert_eq!(t.render().unwrap(), "5"); assert_eq!(t.render().unwrap(), "5");
} }
@ -104,11 +103,12 @@ struct TupleAttrTemplate<'a> {
#[test] #[test]
fn test_tuple_attr() { fn test_tuple_attr() {
let t = TupleAttrTemplate { tuple: ("foo", "bar") }; let t = TupleAttrTemplate {
tuple: ("foo", "bar"),
};
assert_eq!(t.render().unwrap(), "foobar"); assert_eq!(t.render().unwrap(), "foobar");
} }
struct NestedHolder { struct NestedHolder {
holder: Holder, holder: Holder,
} }
@ -121,11 +121,14 @@ struct NestedAttrTemplate {
#[test] #[test]
fn test_nested_attr() { fn test_nested_attr() {
let t = NestedAttrTemplate { inner: NestedHolder { holder: Holder { a: 5 } } }; let t = NestedAttrTemplate {
inner: NestedHolder {
holder: Holder { a: 5 },
},
};
assert_eq!(t.render().unwrap(), "5"); assert_eq!(t.render().unwrap(), "5");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "option.html")] #[template(path = "option.html")]
struct OptionTemplate<'a> { struct OptionTemplate<'a> {
@ -140,11 +143,12 @@ fn test_option() {
assert_eq!(none.render().unwrap(), "none"); assert_eq!(none.render().unwrap(), "none");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "generics.html")] #[template(path = "generics.html")]
struct GenericsTemplate<T: std::fmt::Display, U = u8> struct GenericsTemplate<T: std::fmt::Display, U = u8>
where U: std::fmt::Display { where
U: std::fmt::Display,
{
t: T, t: T,
u: U, u: U,
} }
@ -155,7 +159,6 @@ fn test_generics() {
assert_eq!(t.render().unwrap(), "a42"); assert_eq!(t.render().unwrap(), "a42");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "composition.html")] #[template(path = "composition.html")]
struct CompositionTemplate { struct CompositionTemplate {
@ -164,11 +167,12 @@ struct CompositionTemplate {
#[test] #[test]
fn test_composition() { fn test_composition() {
let t = CompositionTemplate { foo: IfTemplate { cond: true } }; let t = CompositionTemplate {
foo: IfTemplate { cond: true },
};
assert_eq!(t.render().unwrap(), "composed: true"); assert_eq!(t.render().unwrap(), "composed: true");
} }
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
enum Alphabet { enum Alphabet {
Alpha, Alpha,
@ -186,7 +190,6 @@ fn test_path_compare() {
assert_eq!(t.render().unwrap(), "true"); assert_eq!(t.render().unwrap(), "true");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{% for i in [\"a\", \"\"] %}{{ i }}{% endfor %}", ext = "txt")] #[template(source = "{% for i in [\"a\", \"\"] %}{{ i }}{% endfor %}", ext = "txt")]
struct ArrayTemplate {} struct ArrayTemplate {}
@ -197,7 +200,6 @@ fn test_slice_literal() {
assert_eq!(t.render().unwrap(), "a"); assert_eq!(t.render().unwrap(), "a");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = " {# foo -#} ", ext = "txt")] #[template(source = " {# foo -#} ", ext = "txt")]
struct CommentTemplate {} struct CommentTemplate {}
@ -208,7 +210,6 @@ fn test_comment() {
assert_eq!(t.render().unwrap(), " "); assert_eq!(t.render().unwrap(), " ");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{% if !foo %}Hello{% endif %}", ext = "txt")] #[template(source = "{% if !foo %}Hello{% endif %}", ext = "txt")]
struct NegationTemplate { struct NegationTemplate {
@ -221,7 +222,6 @@ fn test_negation() {
assert_eq!(t.render().unwrap(), "Hello"); assert_eq!(t.render().unwrap(), "Hello");
} }
#[derive(Template)] #[derive(Template)]
#[template(source = "{% if foo > -2 %}Hello{% endif %}", ext = "txt")] #[template(source = "{% if foo > -2 %}Hello{% endif %}", ext = "txt")]
struct MinusTemplate { struct MinusTemplate {

View File

@ -15,7 +15,6 @@ fn test_let() {
assert_eq!(t.render().unwrap(), "foo"); assert_eq!(t.render().unwrap(), "foo");
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "let-decl.html")] #[template(path = "let-decl.html")]
struct LetDeclTemplate<'a> { struct LetDeclTemplate<'a> {
@ -25,6 +24,9 @@ struct LetDeclTemplate<'a> {
#[test] #[test]
fn test_let_decl() { fn test_let_decl() {
let t = LetDeclTemplate { cond: false, s: "bar" }; let t = LetDeclTemplate {
cond: false,
s: "bar",
};
assert_eq!(t.render().unwrap(), "bar"); assert_eq!(t.render().unwrap(), "bar");
} }