From e780506c615ba1f4d817fe1e9574534df0d05918 Mon Sep 17 00:00:00 2001 From: Steve Hoffman Date: Wed, 8 Jun 2016 08:42:42 -0500 Subject: [PATCH] implement split filter --- src/filters.rs | 33 +++++++++++++++++++++++++++++++++ src/template.rs | 2 ++ tests/filters.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/filters.rs b/src/filters.rs index b950db488..5a7166451 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -244,6 +244,31 @@ pub fn last(input: &Value, _args: &[Value]) -> FilterResult { } } +pub fn split(input: &Value, args: &[Value]) -> FilterResult { + // Make sure there is only 1 argument to split + if args.len() != 1 { + return Err(InvalidArgumentCount(format!("expected 1, {} given", args.len()))); + } + + + match *input { + Str(ref string_to_split) => { + // the input String is in fact a String + match args.first() { // Check the first (and only) argument + Some(&Str(ref split_string)) => { + // The split string argument is also in fact a String + // Split and construct resulting Array + Ok(Array(string_to_split.split(split_string) + .map(|x| Str(String::from(x))) + .collect())) + } + _ => Err(InvalidArgument(0, "expected String argument to split".to_owned())), + } + } + _ => Err(InvalidType("String expected".to_owned())), + } +} + #[cfg(test)] mod tests { @@ -402,4 +427,12 @@ mod tests { tos!("last")); assert_eq!(unit!(last, Array(vec![])), tos!("")); } + + #[test] + fn unit_split() { + assert_eq!(unit!(split, tos!("a, b, c"), &[tos!(", ")]), + Array(vec![tos!("a"), tos!("b"), tos!("c")])); + assert_eq!(unit!(split, tos!("a~b"), &[tos!("~")]), + Array(vec![tos!("a"), tos!("b")])); + } } diff --git a/src/template.rs b/src/template.rs index f5e20cf37..16be61696 100644 --- a/src/template.rs +++ b/src/template.rs @@ -2,6 +2,7 @@ use Renderable; use context::Context; use filters::{size, upcase, downcase, capitalize, minus, plus, times, divided_by, ceil, floor, round, prepend, append, first, last, pluralize, replace}; +use filters::split; use error::Result; pub struct Template { @@ -28,6 +29,7 @@ impl Renderable for Template { context.add_filter("append", Box::new(append)); context.add_filter("replace", Box::new(replace)); context.add_filter("pluralize", Box::new(pluralize)); + context.add_filter("split", Box::new(split)); let mut buf = String::new(); for el in &self.elements { diff --git a/tests/filters.rs b/tests/filters.rs index 0cc62376c..221eb5603 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -211,3 +211,31 @@ pub fn append() { let output = template.render(&mut data); assert_eq!(output.unwrap(), Some("roobarblifo".to_string())); } + +#[test] +// Got this test from example at https://shopify.github.io/liquid/filters/split/ +// This is an additional test to verify the comma/space parsing is also working +// from https://github.com/cobalt-org/liquid-rust/issues/41 +pub fn split_with_comma() { + let text = "{% assign beatles = \"John, Paul, George, Ringo\" | split: \", \" %}{% for member in beatles %}{{ member }}\n{% endfor %}"; + let options : LiquidOptions = Default::default(); + let template = parse(&text, options).unwrap(); + + let mut data = Context::new(); + + let output = template.render(&mut data); + assert_eq!(output.unwrap(), Some("John\nPaul\nGeorge\nRingo\n".to_string())); +} + +#[test] +// This test verifies that issue https://github.com/cobalt-org/liquid-rust/issues/40 is fixed (that split works) +pub fn split_no_comma() { + let text = "{% assign letters = \"a~b~c\" | split:\"~\" %}{% for letter in letters %}LETTER: {{ letter }}\n{% endfor %}"; + let options : LiquidOptions = Default::default(); + let template = parse(&text, options).unwrap(); + + let mut data = Context::new(); + + let output = template.render(&mut data); + assert_eq!(output.unwrap(), Some("LETTER: a\nLETTER: b\nLETTER: c\n".to_string())); +}