File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -205,7 +205,19 @@ fn rewrite_complex_template_at_expressions(line string) string {
205205 continue
206206 }
207207 next := line[i + 1 ]
208- if next == `@` || next == `{` {
208+ // `@@` is the documented escape for a literal `@` (see vlib/v/TEMPLATES.md).
209+ // Write BOTH characters and consume them fully (i += 2): otherwise the
210+ // second `@` is re-parsed below as the start of a complex at-expression,
211+ // turning `@@get('/x')` into `@{get('/x')}`. The final `@@` -> `@` collapse
212+ // is performed later in insert_template_code.
213+ if next == `@` {
214+ b.write_string ('@@' )
215+ i + = 2
216+ continue
217+ }
218+ // `@{expr}` is an interpolation; leave it untouched, insert_template_code
219+ // turns `@{` into `${`.
220+ if next == `{` {
209221 b.write_u8 (`@` )
210222 i++
211223 continue
Original file line number Diff line number Diff line change 1+ @@get('/x') @@post('/save')
Original file line number Diff line number Diff line change @@ -16,3 +16,13 @@ fn test_keeps_at_in_html_urls() {
1616 assert res.contains ('https://unpkg.com/hyperscript.org@0.8.1' )
1717 assert res.contains ('<div>template ok</div>' )
1818}
19+
20+ fn test_escape_double_at_before_complex_at_expression () {
21+ res := $tmpl ('tmpl/at_before_complex.txt' )
22+ // @@ before ident(...) must yield the literal `@ident(...)`, not `@{ident(...)}`.
23+ // Regression for `@@get('/x')` being rewritten to `@{get('/x')}`.
24+ assert res.contains ("@get('/x')" )
25+ assert res.contains ("@post('/save')" )
26+ assert ! res.contains ('@{get(' )
27+ assert ! res.contains ('@{post(' )
28+ }
You can’t perform that action at this time.
0 commit comments