]>
Commit | Line | Data |
---|---|---|
8faf50e0 | 1 | // const _GRAMMAR: &'static str = include_str!("grammar.pest"); |
83c7162d XL |
2 | |
3 | #[derive(Parser)] | |
4 | #[grammar = "grammar.pest"] | |
5 | pub struct HandlebarsParser; | |
6 | ||
7 | #[cfg(test)] | |
8 | use pest::Parser; | |
9 | ||
10 | #[cfg(test)] | |
11 | macro_rules! assert_rule { | |
8faf50e0 XL |
12 | ($rule:expr, $in:expr) => { |
13 | assert_eq!( | |
14 | HandlebarsParser::parse($rule, $in) | |
15 | .unwrap() | |
16 | .last() | |
17 | .unwrap() | |
18 | .into_span() | |
19 | .end(), | |
83c7162d XL |
20 | $in.len() |
21 | ); | |
8faf50e0 XL |
22 | }; |
23 | } | |
24 | ||
25 | #[cfg(test)] | |
26 | macro_rules! assert_not_rule { | |
27 | ($rule:expr, $in:expr) => { | |
28 | assert!( | |
29 | HandlebarsParser::parse($rule, $in).is_err() | |
30 | || HandlebarsParser::parse($rule, $in) | |
31 | .unwrap() | |
32 | .last() | |
33 | .unwrap() | |
34 | .into_span() | |
35 | .end() != $in.len() | |
36 | ); | |
37 | }; | |
83c7162d | 38 | } |
ea8adc8c | 39 | |
83c7162d XL |
40 | #[cfg(test)] |
41 | macro_rules! assert_rule_match { | |
8faf50e0 | 42 | ($rule:expr, $in:expr) => { |
83c7162d | 43 | assert!(HandlebarsParser::parse($rule, $in).is_ok()); |
8faf50e0 | 44 | }; |
8bb4bdeb XL |
45 | } |
46 | ||
47 | #[test] | |
48 | fn test_raw_text() { | |
ea8adc8c XL |
49 | let s = vec![ |
50 | "<h1> helloworld </h1> ", | |
8faf50e0 XL |
51 | r"hello\{{world}}", |
52 | r"hello\{{#if world}}nice\{{/if}}", | |
53 | r"hello \{{{{raw}}}}hello\{{{{/raw}}}}", | |
ea8adc8c | 54 | ]; |
8bb4bdeb | 55 | for i in s.iter() { |
83c7162d | 56 | assert_rule!(Rule::raw_text, i); |
8bb4bdeb | 57 | } |
8faf50e0 XL |
58 | |
59 | let s_not_escape = vec![r"\\{{hello}}"]; | |
60 | for i in s_not_escape.iter() { | |
61 | assert_not_rule!(Rule::raw_text, i); | |
62 | } | |
8bb4bdeb XL |
63 | } |
64 | ||
65 | #[test] | |
66 | fn test_raw_block_text() { | |
83c7162d XL |
67 | let s = "<h1> {{hello}} </h1>"; |
68 | assert_rule!(Rule::raw_block_text, s); | |
8bb4bdeb XL |
69 | } |
70 | ||
71 | #[test] | |
72 | fn test_reference() { | |
ea8adc8c XL |
73 | let s = vec![ |
74 | "a", | |
75 | "abc", | |
76 | "../a", | |
77 | "a.b", | |
78 | "@abc", | |
79 | "a.[abc]", | |
80 | "aBc.[abc]", | |
81 | "abc.[0].[nice]", | |
82 | "some-name", | |
83 | "this.[0].ok", | |
84 | ]; | |
8bb4bdeb | 85 | for i in s.iter() { |
83c7162d | 86 | assert_rule!(Rule::reference, i); |
8bb4bdeb XL |
87 | } |
88 | } | |
89 | ||
90 | #[test] | |
91 | fn test_name() { | |
92 | let s = vec!["if", "(abc)"]; | |
93 | for i in s.iter() { | |
83c7162d | 94 | assert_rule!(Rule::name, i); |
8bb4bdeb XL |
95 | } |
96 | } | |
97 | ||
98 | #[test] | |
99 | fn test_param() { | |
100 | let s = vec!["hello", "\"json literal\""]; | |
101 | for i in s.iter() { | |
83c7162d | 102 | assert_rule!(Rule::param, i); |
8bb4bdeb XL |
103 | } |
104 | } | |
105 | ||
106 | #[test] | |
107 | fn test_hash() { | |
ea8adc8c XL |
108 | let s = vec![ |
109 | "hello=world", | |
110 | "hello=\"world\"", | |
111 | "hello=(world)", | |
112 | "hello=(world 0)", | |
113 | ]; | |
8bb4bdeb | 114 | for i in s.iter() { |
83c7162d | 115 | assert_rule!(Rule::hash, i); |
8bb4bdeb XL |
116 | } |
117 | } | |
118 | ||
119 | #[test] | |
120 | fn test_json_literal() { | |
ea8adc8c XL |
121 | let s = vec![ |
122 | "\"json string\"", | |
123 | "\"quot: \\\"\"", | |
124 | "[]", | |
125 | "[\"hello\"]", | |
126 | "[1,2,3,4,true]", | |
127 | "{\"hello\": \"world\"}", | |
128 | "{}", | |
129 | "{\"a\":1, \"b\":2 }", | |
130 | ]; | |
8bb4bdeb | 131 | for i in s.iter() { |
83c7162d | 132 | assert_rule!(Rule::literal, i); |
8bb4bdeb XL |
133 | } |
134 | } | |
135 | ||
136 | #[test] | |
137 | fn test_comment() { | |
83c7162d XL |
138 | let s = vec!["{{!-- <hello {{ a-b c-d}} {{d-c}} ok --}}", |
139 | "{{!-- | |
140 | <li><a href=\"{{up-dir nest-count}}{{base-url}}index.html\">{{this.title}}</a></li> | |
141 | --}}"]; | |
8bb4bdeb | 142 | for i in s.iter() { |
83c7162d XL |
143 | assert_rule!(Rule::hbs_comment, i); |
144 | } | |
145 | let s2 = vec!["{{! hello }}", "{{! test me }}"]; | |
146 | for i in s2.iter() { | |
8faf50e0 | 147 | assert_rule!(Rule::hbs_comment_compact, i); |
8bb4bdeb XL |
148 | } |
149 | } | |
150 | ||
151 | #[test] | |
152 | fn test_subexpression() { | |
153 | let s = vec!["(sub)", "(sub 0)", "(sub a=1)"]; | |
154 | for i in s.iter() { | |
83c7162d | 155 | assert_rule!(Rule::subexpression, i); |
8bb4bdeb XL |
156 | } |
157 | } | |
158 | ||
159 | #[test] | |
160 | fn test_expression() { | |
161 | let s = vec!["{{exp}}", "{{(exp)}}", "{{this.name}}", "{{this.[0].name}}"]; | |
162 | for i in s.iter() { | |
83c7162d | 163 | assert_rule!(Rule::expression, i); |
8bb4bdeb XL |
164 | } |
165 | } | |
166 | ||
167 | #[test] | |
168 | fn test_helper_expression() { | |
ea8adc8c XL |
169 | let s = vec![ |
170 | "{{exp 1}}", | |
171 | "{{exp \"literal\"}}", | |
172 | "{{exp ref}}", | |
173 | "{{exp (sub)}}", | |
174 | "{{exp (sub 123)}}", | |
175 | "{{exp []}}", | |
176 | "{{exp {}}}", | |
177 | "{{exp key=1}}", | |
178 | "{{exp key=ref}}", | |
179 | "{{exp key=(sub)}}", | |
180 | "{{exp key=(sub 0)}}", | |
181 | ]; | |
8bb4bdeb | 182 | for i in s.iter() { |
83c7162d | 183 | assert_rule!(Rule::helper_expression, i); |
8bb4bdeb XL |
184 | } |
185 | } | |
186 | ||
8bb4bdeb XL |
187 | #[test] |
188 | fn test_identifier_with_dash() { | |
189 | let s = vec!["{{exp-foo}}"]; | |
190 | for i in s.iter() { | |
83c7162d | 191 | assert_rule!(Rule::expression, i); |
8bb4bdeb XL |
192 | } |
193 | } | |
194 | ||
8bb4bdeb XL |
195 | #[test] |
196 | fn test_html_expression() { | |
197 | let s = vec!["{{{html}}}", "{{{(html)}}}", "{{{(html)}}}"]; | |
198 | for i in s.iter() { | |
83c7162d | 199 | assert_rule!(Rule::html_expression, i); |
8bb4bdeb XL |
200 | } |
201 | } | |
202 | ||
203 | #[test] | |
204 | fn test_helper_start() { | |
ea8adc8c XL |
205 | let s = vec![ |
206 | "{{#if hello}}", | |
207 | "{{#if (hello)}}", | |
208 | "{{#if hello=world}}", | |
209 | "{{#if hello hello=world}}", | |
210 | "{{#if []}}", | |
211 | "{{#if {}}}", | |
212 | "{{#if}}", | |
213 | "{{~#if hello~}}", | |
214 | "{{#each people as |person|}}", | |
215 | "{{#each-obj obj as |key val|}}", | |
83c7162d | 216 | "{{#each assets}}", |
ea8adc8c | 217 | ]; |
8bb4bdeb | 218 | for i in s.iter() { |
83c7162d | 219 | assert_rule!(Rule::helper_block_start, i); |
8bb4bdeb XL |
220 | } |
221 | } | |
222 | ||
223 | #[test] | |
224 | fn test_helper_end() { | |
225 | let s = vec!["{{/if}}", "{{~/if}}", "{{~/if ~}}", "{{/if ~}}"]; | |
226 | for i in s.iter() { | |
83c7162d | 227 | assert_rule!(Rule::helper_block_end, i); |
8bb4bdeb XL |
228 | } |
229 | } | |
230 | ||
231 | #[test] | |
232 | fn test_helper_block() { | |
ea8adc8c XL |
233 | let s = vec![ |
234 | "{{#if hello}}hello{{/if}}", | |
235 | "{{#if true}}hello{{/if}}", | |
236 | "{{#if nice ok=1}}hello{{/if}}", | |
237 | "{{#if}}hello{{else}}world{{/if}}", | |
238 | "{{#if}}hello{{^}}world{{/if}}", | |
239 | "{{#if}}{{#if}}hello{{/if}}{{/if}}", | |
240 | "{{#if}}hello{{~else}}world{{/if}}", | |
241 | "{{#if}}hello{{else~}}world{{/if}}", | |
242 | "{{#if}}hello{{~^~}}world{{/if}}", | |
243 | "{{#if}}{{/if}}", | |
244 | ]; | |
8bb4bdeb | 245 | for i in s.iter() { |
83c7162d | 246 | assert_rule!(Rule::helper_block, i); |
8bb4bdeb XL |
247 | } |
248 | } | |
249 | ||
250 | #[test] | |
251 | fn test_raw_block() { | |
ea8adc8c XL |
252 | let s = vec![ |
253 | "{{{{if hello}}}}good {{hello}}{{{{/if}}}}", | |
254 | "{{{{if hello}}}}{{#if nice}}{{/if}}{{{{/if}}}}", | |
255 | ]; | |
8bb4bdeb | 256 | for i in s.iter() { |
83c7162d | 257 | assert_rule!(Rule::raw_block, i); |
8bb4bdeb XL |
258 | } |
259 | } | |
260 | ||
261 | #[test] | |
262 | fn test_block_param() { | |
263 | let s = vec!["as |person|", "as |key val|"]; | |
264 | for i in s.iter() { | |
83c7162d | 265 | assert_rule!(Rule::block_param, i); |
8bb4bdeb XL |
266 | } |
267 | } | |
268 | ||
269 | #[test] | |
270 | fn test_path() { | |
ea8adc8c XL |
271 | let s = vec![ |
272 | "a", | |
273 | "a.b.c.d", | |
274 | "a.[0].[1].[2]", | |
275 | "a.[abc]", | |
276 | "a/v/c.d.s", | |
277 | "a.[0]/b/c/../d", | |
278 | "a.[bb c]/b/c/../d", | |
279 | "a.[0].[#hello]", | |
280 | "../a/b.[0].[1]", | |
281 | "./this.[0]/[1]/this/../a", | |
282 | "./this_name", | |
283 | "./goo/[/bar]", | |
284 | "a.[你好]", | |
285 | "a.[10].[#comment]", | |
286 | "a.[]", // empty key | |
287 | "././[/foo]", | |
288 | "[foo]", | |
289 | ]; | |
8bb4bdeb | 290 | for i in s.iter() { |
83c7162d | 291 | assert_rule_match!(Rule::path, i); |
8bb4bdeb XL |
292 | } |
293 | } | |
294 | ||
295 | #[test] | |
296 | fn test_directive_expression() { | |
297 | let s = vec!["{{* ssh}}", "{{~* ssh}}"]; | |
298 | for i in s.iter() { | |
83c7162d | 299 | assert_rule!(Rule::directive_expression, i); |
8bb4bdeb XL |
300 | } |
301 | } | |
302 | ||
303 | #[test] | |
304 | fn test_directive_block() { | |
ea8adc8c XL |
305 | let s = vec![ |
306 | "{{#* inline}}something{{/inline}}", | |
307 | "{{~#* inline}}hello{{/inline}}", | |
308 | "{{#* inline \"partialname\"}}something{{/inline}}", | |
309 | ]; | |
8bb4bdeb | 310 | for i in s.iter() { |
83c7162d | 311 | assert_rule!(Rule::directive_block, i); |
8bb4bdeb XL |
312 | } |
313 | } | |
314 | ||
315 | #[test] | |
316 | fn test_partial_expression() { | |
ea8adc8c XL |
317 | let s = vec![ |
318 | "{{> hello}}", | |
319 | "{{> (hello)}}", | |
320 | "{{~> hello a}}", | |
321 | "{{> hello a=1}}", | |
322 | ]; | |
8bb4bdeb | 323 | for i in s.iter() { |
83c7162d | 324 | assert_rule!(Rule::partial_expression, i); |
8bb4bdeb XL |
325 | } |
326 | } | |
327 | ||
328 | #[test] | |
329 | fn test_partial_block() { | |
330 | let s = vec!["{{#> hello}}nice{{/hello}}"]; | |
331 | for i in s.iter() { | |
83c7162d | 332 | assert_rule!(Rule::partial_block, i); |
8bb4bdeb XL |
333 | } |
334 | } |