Repository: cobalt-org/liquid-rust (rust)

Issue:
Support whitespace control
Not sure when they added that but we should support this: https://shopify.github.io/liquid/basics/whitespace/

Pull request description:
whitespace control
resolves #67

Unit tests added. Shouldn't affect anything outside the lexer. Please confirm / check this.

Patch:
diff --git a/src/lexer.rs b/src/lexer.rs
index 31ca610..0b1443a 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -18,7 +18,11 @@ pub enum Element {
 }
 
 lazy_static! {
-    static ref MARKUP: Regex = Regex::new("\\{%.*?%\\}|\\{\\{.*?\\}\\}").unwrap();
+    static ref MARKUP: Regex = {
+        let t = "(?:[[:space:]]*\\{\\{-|\\{\\{).*?(?:-\\}\\}[[:space:]]*|\\}\\})";
+        let e = "(?:[[:space:]]*\\{%-|\\{%).*?(?:-%\\}[[:space:]]*|%\\})";
+        Regex::new(&format!("{}|{}", t, e)).unwrap()
+    };
 }
 
 fn split_blocks(text: &str) -> Vec<&str> {
@@ -42,8 +46,14 @@ fn split_blocks(text: &str) -> Vec<&str> {
 }
 
 lazy_static! {
-    static ref EXPRESSION: Regex = Regex::new("\\{\\{(.*?)\\}\\}").unwrap();
-    static ref TAG: Regex = Regex::new("\\{%(.*?)%\\}").unwrap();
+    static ref EXPRESSION: Regex = {
+        let t = "(?:[[:space:]]*\\{\\{-|\\{\\{)(.*?)(?:-\\}\\}[[:space:]]*|\\}\\})";
+        Regex::new(t).unwrap()
+    };
+    static ref TAG: Regex = {
+        let e = "(?:[[:space:]]*\\{%-|\\{%)(.*?)(?:-%\\}[[:space:]]*|%\\})";
+        Regex::new(e).unwrap()
+    };
 }
 
 pub fn tokenize(text: &str) -> Result<Vec<Element>> {
@@ -150,6 +160,21 @@ fn test_split_blocks() {
     assert_eq!(split_blocks("asdlkjfn\n{%askdljfbalkjsdbf%} asdjlfb"),
                vec!["asdlkjfn\n", "{%askdljfbalkjsdbf%}", " asdjlfb"]);
 }
+#[test]
+fn test_whitespace_control() {
+    assert_eq!(split_blocks("foo {{ bar }} 2000"),
+               vec!["foo ", "{{ bar }}", " 2000"]);
+    assert_eq!(split_blocks("foo {{- bar -}} 2000"),
+               vec!["foo", " {{- bar -}} ", "2000"]);
+    assert_eq!(split_blocks("foo \n{{- bar }} 2000"),
+               vec!["foo", " \n{{- bar }}", " 2000"]);
+    assert_eq!(split_blocks("foo {% bar %} 2000"),
+               vec!["foo ", "{% bar %}", " 2000"]);
+    assert_eq!(split_blocks("foo {%- bar -%} 2000"),
+               vec!["foo", " {%- bar -%} ", "2000"]);
+    assert_eq!(split_blocks("foo \n{%- bar %} 2000"),
+               vec!["foo", " \n{%- bar %}", " 2000"]);
+}
 
 #[test]
 fn test_split_atom() {
@@ -182,6 +207,12 @@ fn test_tokenize() {
                                     StringLiteral("world".to_owned())],
                                "{{hello 'world'}}".to_owned()),
                     Raw(" test".to_owned())]);
+    assert_eq!(tokenize("wat \n {{-hello 'world'-}} test").unwrap(),
+               vec![Raw("wat".to_owned()),
+                    Expression(vec![Identifier("hello".to_owned()),
+                                    StringLiteral("world".to_owned())],
+                               " \n {{-hello 'world'-}} ".to_owned()),
+                    Raw("test".to_owned())]);
 }
 
 #[test]


Test patch:
diff --git a/tests/whitespace_control.rs b/tests/whitespace_control.rs
new file mode 100644
index 0000000..fb36473
--- /dev/null
+++ b/tests/whitespace_control.rs
@@ -0,0 +1,66 @@
+extern crate liquid;
+
+use liquid::LiquidOptions;
+use liquid::Renderable;
+use liquid::Context;
+use liquid::parse;
+use std::default::Default;
+
+macro_rules! compare {
+    ($input:expr, $output:expr) => {
+        let input = $input.replace("…", " ");
+        let expected = $output.replace("…", " ");
+        let options: LiquidOptions = Default::default();
+        let template = parse(&input, options).unwrap();
+
+        let mut data = Context::new();
+        let output = template.render(&mut data);
+        assert_eq!(output.unwrap(), Some(expected));
+    }
+}
+
+#[test]
+pub fn no_whitespace_control() {
+    compare!("
+topic1
+……{% assign foo = \"bar\" %}
+……{% if foo %}
+…………-……{{ foo }}
+……{% endif %}
+",
+             "
+topic1
+……
+……
+…………-……bar
+……
+");
+}
+
+#[test]
+pub fn simple_whitespace_control() {
+    compare!("
+topic1
+……{% assign foo = \"bar\" -%}
+……{% if foo -%}
+…………-……{{- foo }}
+……{%- endif %}
+",
+             "
+topic1
+……-bar
+");
+}
+
+#[test]
+pub fn double_sided_whitespace_control() {
+    compare!("
+topic1
+……{%- assign foo = \"bar\" -%}
+……-……{{- foo -}}……
+
+",
+             "
+topic1-bar\
+");
+}