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