Skip to content

Commit

Permalink
x.vweb: fix $vweb.html() integration in cgen for the newer x.vweb
Browse files Browse the repository at this point in the history
… module (fix #20204)
  • Loading branch information
spytheman committed Dec 30, 2023
1 parent fa81188 commit 923b410
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 9 deletions.
4 changes: 1 addition & 3 deletions examples/xvweb/todo/main.v
Expand Up @@ -39,9 +39,7 @@ pub fn (app &App) index(mut ctx Context) vweb.Result {
todos := sql app.db {
select from Todo
} or { return ctx.server_error('could not fetch todos from database!') }

// TODO: use $vweb.html()
return ctx.html($tmpl('templates/index.html'))
return $vweb.html()
}

// This method will only handle POST requests to the index page
Expand Down
1 change: 1 addition & 0 deletions vlib/v/gen/c/cgen.v
Expand Up @@ -246,6 +246,7 @@ mut:
has_reflection bool
reflection_strings &map[string]int
defer_return_tmp_var string
vweb_filter_fn_name string // vweb__filter or x__vweb__filter, used by $vweb.html() for escaping strings in the templates, depending on which `vweb` import is used
}

// global or const variable definition string
Expand Down
28 changes: 23 additions & 5 deletions vlib/v/gen/c/comptime.v
Expand Up @@ -59,25 +59,43 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
cur_line = g.go_before_last_stmt()
}

ret_sym := g.table.sym(g.fn_decl.return_type)
fn_name := g.fn_decl.name.replace('.', '__') + node.pos.pos.str()
is_x_vweb := ret_sym.cname == 'x__vweb__Result'

for stmt in node.vweb_tmpl.stmts {
if stmt is ast.FnDecl {
// insert stmts from vweb_tmpl fn
if stmt.name.starts_with('main.vweb_tmpl') {
if is_html {
g.inside_vweb_tmpl = true
if is_x_vweb {
g.vweb_filter_fn_name = 'x__vweb__filter'
} else {
g.vweb_filter_fn_name = 'vweb__filter'
}
}
// insert stmts from vweb_tmpl fn
g.stmts(stmt.stmts.filter(it !is ast.Return))
//
g.inside_vweb_tmpl = false
g.vweb_filter_fn_name = ''
break
}
}
}

fn_name := g.fn_decl.name.replace('.', '__') + node.pos.pos.str()
if is_html {
// return vweb html template
app_name := g.fn_decl.params[0].name
g.writeln('vweb__Context_html(&${app_name}->Context, _tmpl_res_${fn_name}); strings__Builder_free(&sb_${fn_name}); string_free(&_tmpl_res_${fn_name});')
// return a vweb or x.vweb html template
if is_x_vweb {
ctx_name := g.fn_decl.params[1].name
g.writeln('x__vweb__Context_html(${ctx_name}, _tmpl_res_${fn_name});')
} else {
// old vweb:
app_name := g.fn_decl.params[0].name
g.writeln('vweb__Context_html(&${app_name}->Context, _tmpl_res_${fn_name});')
}
g.writeln('strings__Builder_free(&sb_${fn_name});')
g.writeln('string_free(&_tmpl_res_${fn_name});')
} else {
// return $tmpl string
g.write(cur_line)
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/str_intp.v
Expand Up @@ -168,7 +168,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {
typ_sym := g.table.sym(typ)
if typ == ast.string_type && g.comptime.comptime_for_method.len == 0 {
if g.inside_vweb_tmpl {
g.write('vweb__filter(')
g.write('${g.vweb_filter_fn_name}(')
if expr.is_auto_deref_var() && fmt != `p` {
g.write('*')
}
Expand Down
11 changes: 11 additions & 0 deletions vlib/x/vweb/escape_html_strings_in_templates.v
@@ -0,0 +1,11 @@
module vweb

import encoding.html

// Do not delete.
// Calls to this function are generated by `fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {` in vlib/v/gen/c/str_intp.v,
// for string interpolation inside vweb templates.
// TODO: move it to template render
fn filter(s string) string {
return html.escape(s)
}

0 comments on commit 923b410

Please sign in to comment.