diff options
author | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-02-08 13:30:57 +0100 |
---|---|---|
committer | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-02-08 13:30:57 +0100 |
commit | e54b8c898ec634234eef4e12125577596e9d42d7 (patch) | |
tree | 8b7c2754ceca31d67fd61bad9265689158352348 | |
parent | b1dc4d5057198330551879c48cb1b4dceb9f381e (diff) | |
download | askama-e54b8c898ec634234eef4e12125577596e9d42d7.tar.gz askama-e54b8c898ec634234eef4e12125577596e9d42d7.tar.bz2 askama-e54b8c898ec634234eef4e12125577596e9d42d7.zip |
Add support for whitespace handling markers to parser
-rw-r--r-- | askama/src/generator.rs | 16 | ||||
-rw-r--r-- | askama/src/parser.rs | 53 |
2 files changed, 47 insertions, 22 deletions
diff --git a/askama/src/generator.rs b/askama/src/generator.rs index 32d7c71..8ff5836 100644 --- a/askama/src/generator.rs +++ b/askama/src/generator.rs @@ -131,7 +131,7 @@ impl Generator { } fn write_cond(&mut self, conds: &[Cond]) { - for (i, &(ref cond, ref nodes)) in conds.iter().enumerate() { + for (i, &(_, ref cond, ref nodes)) in conds.iter().enumerate() { match *cond { Some(ref expr) => { if i == 0 { @@ -195,13 +195,13 @@ impl Generator { self.write_lit(val); self.write_lit(rws); }, - Node::Expr(ref val) => { self.write_expr(val); }, - Node::Cond(ref conds) => { self.write_cond(conds); }, - Node::Loop(ref var, ref iter, ref body) => { + Node::Expr(_, ref val) => { self.write_expr(val); }, + Node::Cond(ref conds, _) => { self.write_cond(conds); }, + Node::Loop(_, ref var, ref iter, ref body, _) => { self.write_loop(var, iter, body); }, - Node::Block(name) => { self.write_block(name) }, - Node::BlockDef(name, ref block_nodes) => { + Node::Block(_, name, _) => { self.write_block(name) }, + Node::BlockDef(_, name, ref block_nodes, _) => { self.write_block_def(name, block_nodes); } Node::Extends(_) => { @@ -301,9 +301,9 @@ pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> Str None => { base = Some(path); }, } }, - Node::BlockDef(name, _) => { + Node::BlockDef(ws1, name, _, ws2) => { blocks.push(n); - content.push(Node::Block(name)); + content.push(Node::Block(ws1, name, ws2)); }, _ => { content.push(n); }, } diff --git a/askama/src/parser.rs b/askama/src/parser.rs index f6a8726..0242356 100644 --- a/askama/src/parser.rs +++ b/askama/src/parser.rs @@ -12,17 +12,20 @@ pub enum Target<'a> { Name(&'a [u8]), } +#[derive(Clone, Copy)] +pub struct WS(bool, bool); + pub enum Node<'a> { Lit(&'a [u8], &'a [u8], &'a [u8]), - Expr(Expr<'a>), - Cond(Vec<(Option<Expr<'a>>, Vec<Node<'a>>)>), - Loop(Target<'a>, Expr<'a>, Vec<Node<'a>>), + Expr(WS, Expr<'a>), + Cond(Vec<(WS, Option<Expr<'a>>, Vec<Node<'a>>)>, WS), + Loop(WS, Target<'a>, Expr<'a>, Vec<Node<'a>>, WS), Extends(Expr<'a>), - BlockDef(&'a str, Vec<Node<'a>>), - Block(&'a str), + BlockDef(WS, &'a str, Vec<Node<'a>>, WS), + Block(WS, &'a str, WS), } -pub type Cond<'a> = (Option<Expr<'a>>, Vec<Node<'a>>); +pub type Cond<'a> = (WS, Option<Expr<'a>>, Vec<Node<'a>>); fn split_ws_parts(s: &[u8]) -> Node { if s.is_empty() { @@ -110,9 +113,13 @@ named!(expr_any<Expr>, alt!( expr_str_lit )); -named!(expr_node<Node>, map!( - delimited!(tag_s!("{{"), ws!(expr_any), tag_s!("}}")), - Node::Expr +named!(expr_node<Node>, do_parse!( + tag_s!("{{") >> + pws: opt!(tag_s!("-")) >> + expr: ws!(expr_any) >> + nws: opt!(tag_s!("-")) >> + tag_s!("}}") >> + (Node::Expr(WS(pws.is_some(), nws.is_some()), expr)) )); named!(cond_if<Expr>, do_parse!( @@ -123,42 +130,54 @@ named!(cond_if<Expr>, do_parse!( named!(cond_block<Cond>, do_parse!( tag_s!("{%") >> + pws: opt!(tag_s!("-")) >> ws!(tag_s!("else")) >> cond: opt!(cond_if) >> + nws: opt!(tag_s!("-")) >> tag_s!("%}") >> block: parse_template >> - (cond, block) + (WS(pws.is_some(), nws.is_some()), cond, block) )); named!(block_if<Node>, do_parse!( tag_s!("{%") >> + pws1: opt!(tag_s!("-")) >> cond: ws!(cond_if) >> + nws1: opt!(tag_s!("-")) >> tag_s!("%}") >> block: parse_template >> elifs: many0!(cond_block) >> tag_s!("{%") >> + pws2: opt!(tag_s!("-")) >> ws!(tag_s!("endif")) >> + nws2: opt!(tag_s!("-")) >> tag_s!("%}") >> ({ let mut res = Vec::new(); - res.push((Some(cond), block)); + res.push((WS(pws1.is_some(), nws1.is_some()), Some(cond), block)); res.extend(elifs); - Node::Cond(res) + Node::Cond(res, WS(pws2.is_some(), nws2.is_some())) }) )); named!(block_for<Node>, do_parse!( tag_s!("{%") >> + pws1: opt!(tag_s!("-")) >> ws!(tag_s!("for")) >> var: ws!(target_single) >> ws!(tag_s!("in")) >> iter: ws!(expr_any) >> + nws1: opt!(tag_s!("-")) >> tag_s!("%}") >> block: parse_template >> tag_s!("{%") >> + pws2: opt!(tag_s!("-")) >> ws!(tag_s!("endfor")) >> + nws2: opt!(tag_s!("-")) >> tag_s!("%}") >> - (Node::Loop(var, iter, block)) + (Node::Loop(WS(pws1.is_some(), nws1.is_some()), + var, iter, block, + WS(pws2.is_some(), pws2.is_some()))) )); named!(block_extends<Node>, do_parse!( @@ -171,14 +190,20 @@ named!(block_extends<Node>, do_parse!( named!(block_block<Node>, do_parse!( tag_s!("{%") >> + pws1: opt!(tag_s!("-")) >> ws!(tag_s!("block")) >> name: ws!(nom::alphanumeric) >> + nws1: opt!(tag_s!("-")) >> tag_s!("%}") >> contents: parse_template >> tag_s!("{%") >> + pws2: opt!(tag_s!("-")) >> ws!(tag_s!("endblock")) >> + nws2: opt!(tag_s!("-")) >> tag_s!("%}") >> - (Node::BlockDef(str::from_utf8(name).unwrap(), contents)) + (Node::BlockDef(WS(pws1.is_some(), nws1.is_some()), + str::from_utf8(name).unwrap(), contents, + WS(pws2.is_some(), pws2.is_some()))) )); named!(parse_template<Vec<Node<'a>>>, many0!(alt!( |