Skip to content

Commit 7790e9d

Browse files
authored
parser: fix @@ escape before complex at-expressions in templates (#27701)
1 parent 2fe3145 commit 7790e9d

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

vlib/v/parser/tmpl.v

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff 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
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@@get('/x') @@post('/save')

vlib/v/tests/tmpl_escape_test.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff 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+
}

0 commit comments

Comments
 (0)