rusty_handlebars_parser/
lib.rs1mod error;
49mod expression;
50mod expression_tokenizer;
51mod compiler;
52mod block;
53pub mod build_helper;
54
55pub use compiler::*;
56pub use block::*;
57pub use error::*;
58pub use expression::*;
59pub use expression_tokenizer::*;
60
61#[cfg(test)]
62mod tests {
63 use core::str;
64
65 use block::add_builtins;
66 use compiler::{BlockMap, Compiler, Options};
67
68 use crate::*;
69
70 static OPTIONS: Options = Options{
71 root_var_name: Some("self"),
72 write_var_name: "f"
73 };
74
75 fn make_map() -> BlockMap{
76 let mut map = BlockMap::new();
77 add_builtins(&mut map);
78 map
79 }
80
81 fn compile(src: &str) -> String{
82 Compiler::new(OPTIONS, make_map()).compile(src).unwrap().code
83 }
84
85 #[test]
86 fn it_works() {
87 assert_eq!(
88 compile("Hello {{{name}}}!"),
89 "write!(f, \"Hello {}!\", self.name.as_display())?;"
90 );
91 }
92
93 #[test]
94 fn test_if(){
95 let rust = compile("{{#if some}}Hello{{/if}}");
96 assert_eq!(rust, "if self.some.as_bool(){write!(f, \"Hello\")?;}");
97 }
98
99 #[test]
100 fn test_else(){
101 let rust = compile("{{#if some}}Hello{{else}}World{{/if}}");
102 assert_eq!(rust, "if self.some.as_bool(){write!(f, \"Hello\")?;}else{write!(f, \"World\")?;}");
103 }
104
105 #[test]
106 fn test_unless(){
107 let rust = compile("{{#unless some}}Hello{{/unless}}");
108 assert_eq!(rust, "if !self.some.as_bool(){write!(f, \"Hello\")?;}");
109 }
110
111 #[test]
112 fn test_each(){
113 let rust = compile("{{#each some}}Hello {{this}}{{/each}}");
114 assert_eq!(rust, "for this_1 in self.some{write!(f, \"Hello {}\", this_1.as_display_html())?;}");
115 }
116
117 #[test]
118 fn test_with(){
119 let rust = compile("{{#with some}}Hello {{name}}{{/with}}");
120 assert_eq!(rust, "{let this_1 = self.some;write!(f, \"Hello {}\", this_1.name.as_display_html())?;}");
121 }
122
123 #[test]
124 fn test_nesting(){
125 let rust = compile("{{#if some}}{{#each some}}Hello {{this}}{{/each}}{{/if}}");
126 assert_eq!(rust, "if self.some.as_bool(){for this_2 in self.some{write!(f, \"Hello {}\", this_2.as_display_html())?;}}");
127 }
128
129 #[test]
130 fn test_as(){
131 let rust = compile("{{#if some}}{{#each some as thing}}Hello {{thing}} {{thing.name}}{{/each}}{{/if}}");
132 assert_eq!(rust, "if self.some.as_bool(){for thing_2 in self.some{write!(f, \"Hello {} {}\", thing_2.as_display_html(), thing_2.name.as_display_html())?;}}");
133 }
134
135 #[test]
136 fn test_comment(){
137 let rust = compile("Note: {{! This is a comment }} and {{!-- {{so is this}} --}}\\{{{{}}");
138 assert_eq!(rust, "write!(f, \"Note: and {{{{\")?;");
139 }
140
141 #[test]
142 fn test_scoping(){
143 let rust = compile("{{#with some}}{{#with other}}Hello {{name}} {{../company}} {{/with}}{{/with}}");
144 assert_eq!(rust, "{let this_1 = self.some;{let this_2 = this_1.other;write!(f, \"Hello {} {} \", this_2.name.as_display_html(), this_1.company.as_display_html())?;}}");
145 }
146
147 #[test]
148 fn test_trimming(){
149 let rust = compile(" {{~#if some ~}} Hello{{~/if~}}");
150 assert_eq!(rust, "if self.some.as_bool(){write!(f, \"Hello\")?;}");
151 }
152
153 #[test]
154 fn test_indexer(){
155 let rust = compile("{{#each things}}Hello{{{@index}}}{{#each things}}{{{lookup other @../index}}}{{{@index}}}{{/each}}{{/each}}");
156 assert_eq!(rust, "let mut i_1 = 0;for this_1 in self.things{write!(f, \"Hello{}\", i_1.as_display())?;let mut i_2 = 0;for this_2 in this_1.things{write!(f, \"{}{}\", this_2.other[i_1].as_display(), i_2.as_display())?;i_2+=1;}i_1+=1;}");
157 }
158
159 #[test]
160 fn test_map(){
161 let rust = compile("{{#each things}}Hello{{{@key}}}{{#each @value}}{{#if_some (try_lookup other @../key)}}{{{this}}}{{/if_some}}{{{@value}}}{{/each}}{{/each}}");
162 assert_eq!(rust, "for this_1 in self.things{write!(f, \"Hello{}\", this_1.0.as_display())?;for this_2 in this_1.1{if let Some(this_3) = this_2.other.get(this_1.0){write!(f, \"{}\", this_3.as_display())?;}write!(f, \"{}\", this_2.1.as_display())?;}}");
163 }
164
165 #[test]
166 fn test_literals(){
167 let rust = compile("{{#if_some (try_lookup thing \"test\")}}{{this}}{{/if_some}} {{#if_some (try_lookup other_thing 123)}}{{this}}{{/if_some}}");
168 assert_eq!(rust, "if let Some(this_1) = self.thing.get(\"test\"){write!(f, \"{}\", this_1.as_display_html())?;}write!(f, \" \")?;if let Some(this_1) = self.other_thing.get(123){write!(f, \"{}\", this_1.as_display_html())?;}");
169 }
170
171 #[test]
172 fn test_subexpression(){
173 let rust = compile("{{#each things}}{{#with (lookup ../other @index) as |other|}}{{{../name}}}: {{{other}}}{{/with}}{{/each}}");
174 assert_eq!(rust, "let mut i_1 = 0;for this_1 in self.things{{let other_2 = self.other[i_1];write!(f, \"{}: {}\", this_1.name.as_display(), other_2.as_display())?;}i_1+=1;}");
175 }
176
177 #[test]
178 fn test_selfless(){
179 let rust = Compiler::new(Options{
180 root_var_name: None,
181 write_var_name: "f"
182 }, make_map()).compile("{{#each things}}{{#with (lookup ../other @index) as |other|}}{{{../name}}}: {{{other}}}{{/with}}{{/each}}").unwrap();
183 assert_eq!(rust.uses("rusty_handlebars").to_string(), "use rusty_handlebars::AsDisplay");
184 assert_eq!(rust.code, "let mut i_1 = 0;for this_1 in things{{let other_2 = other[i_1];write!(f, \"{}: {}\", this_1.name.as_display(), other_2.as_display())?;}i_1+=1;}");
185 }
186
187 #[test]
188 fn javascript(){
189 let rust = Compiler::new(OPTIONS, make_map()).compile("<script>if (location.href.contains(\"localhost\")){ console.log(\"\\{{{{}}}}\") }</script>").unwrap();
190 assert_eq!(rust.uses("rusty_handlebars").to_string(), "");
191 assert_eq!(rust.code, "write!(f, \"<script>if (location.href.contains(\\\"localhost\\\")){{ console.log(\\\"{{{{}}}}\\\") }}</script>\")?;");
192 }
193
194 #[test]
195 fn if_some(){
196 let rust = compile("{{#if_some some}}Hello {{name}}{{else}}Oh dear{{/if_some}}{{#if some}}{{#if_some_ref ../some as |other|}}Hello {{other.name}}{{/if_some}}{{/if}}");
197 assert_eq!(rust, "if let Some(this_1) = self.some{write!(f, \"Hello {}\", this_1.name.as_display_html())?;}else{write!(f, \"Oh dear\")?;}if self.some.as_bool(){if let Some(other_2) = &self.some{write!(f, \"Hello {}\", other_2.name.as_display_html())?;}}");
198 }
199
200 #[test]
201 fn test_escaped(){
202 let rust = compile("{{{{skip}}}}wang doodle {{{{/dandy}}}}{{{{/skip}}}}");
203 assert_eq!(rust, "write!(f, \"wang doodle {{{{{{{{/dandy}}}}}}}}\")?;");
204 }
205
206 #[test]
207 fn test_format_number(){
208 let rust = compile("Price: ${{format \"{:.2}\" price}}");
209 assert_eq!(rust, "write!(f, \"Price: ${:.2}\", self.price)?;");
210 }
211
212 }