Skip to content

Commit bbba337

Browse files
author
Johann Hofmann
committed
Merge pull request #22 from tcsc/capture
Adds capture block
2 parents 1e22f3a + 744bcbf commit bbba337

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ extern crate regex;
3131

3232
use std::collections::HashMap;
3333
use lexer::Element;
34-
use tags::{assign_tag, comment_block, raw_block, for_block, if_block};
34+
use tags::{assign_tag, comment_block, raw_block, for_block, if_block, capture_block};
3535
use std::default::Default;
3636
use error::Result;
3737

@@ -156,6 +156,7 @@ pub fn parse(text: &str, options: LiquidOptions) -> Result<Template> {
156156
options.register_block("if", Box::new(if_block));
157157
options.register_block("for", Box::new(for_block));
158158
options.register_block("comment", Box::new(comment_block));
159+
options.register_block("capture", Box::new(capture_block));
159160

160161
parser::parse(&tokens, &options).map(Template::new)
161162
}

src/tags/capture_block.rs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use context::Context;
2+
use error::{Error, Result};
3+
use lexer::Element;
4+
use LiquidOptions;
5+
use Renderable;
6+
use template::Template;
7+
use token::Token::{self, Identifier};
8+
use value::Value;
9+
use parser::parse;
10+
11+
struct Capture {
12+
id: String,
13+
template: Template
14+
}
15+
16+
impl Renderable for Capture {
17+
fn render(&self, context: &mut Context) -> Result<Option<String>> {
18+
let output = match self.template.render(context) {
19+
Ok(Some(s)) => s.clone(),
20+
Ok(None) => "".to_owned(),
21+
Err(x) => return Err(x)
22+
};
23+
24+
context.set_val(&self.id, Value::Str(output));
25+
Ok(None)
26+
}
27+
}
28+
29+
pub fn capture_block(_tag_name: &str,
30+
arguments: &[Token],
31+
tokens: Vec<Element>,
32+
options: &LiquidOptions)
33+
-> Result<Box<Renderable>> {
34+
let mut args = arguments.iter();
35+
let id = match args.next() {
36+
Some(&Identifier(ref x)) => x.clone(),
37+
x @ Some(_) | x @ None => {
38+
return Error::parser("Identifier", x)
39+
}
40+
};
41+
42+
// there should be no trailing tokens after this
43+
if let t @ Some(_) = args.next() {
44+
return Error::parser("%}", t)
45+
};
46+
47+
let t = Template::new(try!(parse(&tokens, options)));
48+
49+
Ok(Box::new(Capture {
50+
id: id,
51+
template: t
52+
}))
53+
}
54+
55+
#[cfg(test)]
56+
mod test {
57+
use parse;
58+
use LiquidOptions;
59+
use Renderable;
60+
use value::Value;
61+
use std::default::Default;
62+
use context::Context;
63+
64+
#[test]
65+
fn test_capture() {
66+
let text = concat!(
67+
"{% capture attribute_name %}",
68+
"{{ item | upcase }}-{{ i }}-color",
69+
"{% endcapture %}" );
70+
let template = parse(text, LiquidOptions::default()).unwrap();
71+
72+
let mut ctx = Context::new();
73+
ctx.set_val("item", Value::str("potato"));
74+
ctx.set_val("i", Value::Num(42f32));
75+
76+
let output = template.render(&mut ctx);
77+
assert_eq!(output.unwrap(), Some("".to_owned()));
78+
assert_eq!(ctx.get_val("attribute_name"),
79+
Some(&Value::str("POTATO-42-color")));
80+
}
81+
82+
#[test]
83+
fn trailing_tokens_are_an_error() {
84+
let text = concat!(
85+
"{% capture foo bar baz %}",
86+
"We should never see this",
87+
"{% endcapture %}" );
88+
assert!(parse(text, LiquidOptions::default()).is_err());
89+
}
90+
}

src/tags/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
mod assign_tag;
2+
mod capture_block;
23
mod if_block;
34
mod for_block;
45
mod raw_block;
56
mod comment_block;
67

78
pub use self::assign_tag::assign_tag;
9+
pub use self::capture_block::capture_block;
810
pub use self::comment_block::comment_block;
911
pub use self::raw_block::raw_block;
1012
pub use self::for_block::for_block;

0 commit comments

Comments
 (0)