diff options
author | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-08-04 13:19:30 +0200 |
---|---|---|
committer | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-08-04 13:21:55 +0200 |
commit | 51eee57b84adf7fe72b7aa9b23e3ef974baad5a4 (patch) | |
tree | 5a4e70a1a1fc73f95dc21bfef6ffb6a6f296c06a | |
parent | 02e0f783f93d6336015736d4adfd2cebca275b00 (diff) | |
download | askama-51eee57b84adf7fe72b7aa9b23e3ef974baad5a4.tar.gz askama-51eee57b84adf7fe72b7aa9b23e3ef974baad5a4.tar.bz2 askama-51eee57b84adf7fe72b7aa9b23e3ef974baad5a4.zip |
Add support for include blocks (see #25)
-rw-r--r-- | askama_derive/src/generator.rs | 30 | ||||
-rw-r--r-- | askama_derive/src/parser.rs | 22 |
2 files changed, 47 insertions, 5 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index f055cb7..570ab06 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -1,4 +1,4 @@ -use parser::{Cond, Expr, Node, Target, WS}; +use parser::{self, Cond, Expr, Node, Target, WS}; use std::str; use std::collections::HashSet; use syn; @@ -27,17 +27,25 @@ struct Generator<'a> { impl<'a> Generator<'a> { - fn new() -> Generator<'a> { + fn new(locals: HashSet<String>, indent: u8) -> Generator<'a> { Generator { buf: String::new(), - indent: 0, + indent: indent, start: true, - locals: HashSet::new(), + locals: locals, next_ws: None, skip_ws: false, } } + fn default() -> Generator<'a> { + Self::new(HashSet::new(), 0) + } + + fn child(&self) -> Generator<'a> { + Self::new(self.locals.clone(), self.indent) + } + fn indent(&mut self) { self.indent += 1; } @@ -282,6 +290,15 @@ impl<'a> Generator<'a> { self.writeln("}"); } + fn handle_include(&mut self, ws: &WS, src: &str) { + self.prepare_ws(ws); + let nodes = parser::parse(&src); + let mut gen = self.child(); + gen.handle(&nodes); + self.buf.push_str(&gen.result()); + self.flush_ws(ws); + } + fn handle(&mut self, nodes: &'a [Node]) { for n in nodes { match *n { @@ -300,6 +317,9 @@ impl<'a> Generator<'a> { Node::BlockDef(ref ws1, name, ref block_nodes, ref ws2) => { self.write_block_def(ws1, name, block_nodes, ws2); } + Node::Include(ref ws, ref src) => { + self.handle_include(ws, src); + }, Node::Extends(_) => { panic!("no extends or block definition allowed in content"); }, @@ -446,7 +466,7 @@ pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> Str } } - let mut gen = Generator::new(); + let mut gen = Generator::default(); if !blocks.is_empty() { if base.is_none() { gen.define_trait(path, &block_names); diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs index 61ccb09..6a182d5 100644 --- a/askama_derive/src/parser.rs +++ b/askama_derive/src/parser.rs @@ -1,4 +1,5 @@ use nom::{self, IResult}; +use path; use std::str; #[derive(Debug)] @@ -31,6 +32,7 @@ pub enum Node<'a> { Extends(Expr<'a>), BlockDef(WS, &'a str, Vec<Node<'a>>, WS), Block(WS, &'a str, WS), + Include(WS, String), } pub type Cond<'a> = (WS, Option<Expr<'a>>, Vec<Node<'a>>); @@ -324,6 +326,25 @@ named!(block_block<Node>, do_parse!( WS(pws2.is_some(), pws2.is_some()))) )); +named!(block_include<Node>, do_parse!( + tag_s!("{%") >> + pws: opt!(tag_s!("-")) >> + ws!(tag_s!("include")) >> + name: ws!(expr_str_lit) >> + nws: opt!(tag_s!("-")) >> + tag_s!("%}") >> + ({ + let mut src = match name { + Expr::StrLit(s) => path::get_template_source(s), + _ => panic!("include path must be a string literal"), + }; + if src.ends_with('\n') { + let _ = src.pop(); + } + Node::Include(WS(pws.is_some(), nws.is_some()), src) + }) +)); + named!(block_comment<Node>, do_parse!( tag_s!("{#") >> take_until_s!("#}") >> @@ -338,6 +359,7 @@ named!(parse_template<Vec<Node<'a>>>, many0!(alt!( block_if | block_for | block_extends | + block_include | block_block ))); |