tmpl: fix doubling templates folder path and enhancements (#9029)

pull/9036/head
Anton Zavodchikov 2021-03-01 14:15:59 +05:00 committed by GitHub
parent 15896beace
commit 506041a15b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 113 additions and 47 deletions

View File

@ -80,14 +80,15 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
}
p.check(.lpar)
spos := p.tok.position()
s := if is_html { '' } else { p.tok.lit }
literal_string_param := if is_html { '' } else { p.tok.lit }
path_of_literal_string_param := literal_string_param.replace('/', os.path_separator)
if !is_html {
p.check(.string)
}
p.check(.rpar)
// $embed_file('/path/to/file')
if is_embed_file {
mut epath := s
mut epath := path_of_literal_string_param
// Validate that the epath exists, and that it is actually a file.
if epath == '' {
p.error_with_pos('supply a valid relative or absolute file path to the file to embed',
@ -119,7 +120,7 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
scope: 0
is_embed: true
embed_file: ast.EmbeddedFile{
rpath: s
rpath: literal_string_param
apath: epath
}
}
@ -127,10 +128,12 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
// Compile vweb html template to V code, parse that V code and embed the resulting V function
// that returns an html string.
fn_path := p.cur_fn_name.split('_')
tmpl_path := if is_html { '${fn_path.last()}.html' } else { s }
fn_path_joined := fn_path.join(os.path_separator)
compiled_vfile_path := os.real_path(p.scanner.file_path.replace('/', os.path_separator))
tmpl_path := if is_html { '${fn_path.last()}.html' } else { path_of_literal_string_param }
// Looking next to the vweb program
dir := os.dir(p.scanner.file_path.replace('/', os.path_separator))
mut path := os.join_path(dir, fn_path.join(os.path_separator))
dir := os.dir(compiled_vfile_path)
mut path := os.join_path(dir, fn_path_joined)
path += '.html'
path = os.real_path(path)
if !is_html {
@ -139,7 +142,7 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
if !os.exists(path) {
// can be in `templates/`
if is_html {
path = os.join_path(dir, 'templates', fn_path.join('/'))
path = os.join_path(dir, 'templates', fn_path_joined)
path += '.html'
}
if !os.exists(path) {
@ -152,10 +155,10 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
}
// println('path is now "$path"')
}
if p.pref.is_verbose {
println('>>> compiling comptime template file "$path"')
}
tmp_fn_name := p.cur_fn_name.replace('.', '__')
$if trace_comptime ? {
println('>>> compiling comptime template file "$path" for $tmp_fn_name')
}
v_code := tmpl.compile_file(path, tmp_fn_name)
$if print_vweb_template_expansions ? {
lines := v_code.split('\n')
@ -167,12 +170,12 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
start_pos: 0
parent: p.global_scope
}
if p.pref.is_verbose {
println('\n\n')
$if trace_comptime ? {
println('')
println('>>> vweb template for $path:')
println(v_code)
println('>>> end of vweb template END')
println('\n\n')
println('')
}
mut file := parse_comptime(v_code, p.table, p.pref, scope, p.global_scope)
file = ast.File{
@ -207,7 +210,7 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
is_vweb: true
vweb_tmpl: file
method_name: n
args_var: s
args_var: literal_string_param
}
}

View File

@ -1,9 +1,9 @@
name: @name
age: @age
numbers: @numbers
@for number in numbers
@number
@end
@include 'inner.txt'

View File

@ -0,0 +1,17 @@
@for i in 0..10
${i*2} - $i
@end
@for key, val in downloads
${key}, downloaded $val times.
@end
@if !ignored
this is ignored
@else
this is not ignored
@end
@if true
so, it's basically true
@end

View File

@ -2,40 +2,84 @@ fn one() string {
name := 'Peter'
age := 25
numbers := [1, 2, 3]
return $tmpl('tmpl/1.txt')
downloads := map{
'vlang/ui': '3201'
'vlang/vtl': '123'
}
ignored := true
return $tmpl('tmpl/base.txt')
}
fn test_tmpl() {
assert one().trim_space() == 'name: Peter
assert one().trim_space() == "name: Peter
age: 25
numbers: [1, 2, 3]
1
2
3
3'
0 - 0
2 - 1
4 - 2
6 - 3
8 - 4
10 - 5
12 - 6
14 - 7
16 - 8
18 - 9
vlang/ui, downloaded 3201 times.
vlang/vtl, downloaded 123 times.
this is not ignored
so, it's basically true"
}
fn test_tmpl_in_anon_fn() {
anon := fn (name string, age int, numbers []int) string {
return $tmpl('tmpl/1.txt')
anon := fn (name string, age int, numbers []int, downloads map[string]string, ignored bool) string {
return $tmpl('tmpl/base.txt')
}
println(anon('Peter', 25, [1, 2, 3]))
assert anon('Peter', 25, [1, 2, 3]).trim_space() == 'name: Peter
assert anon('Peter', 25, [1, 2, 3], map{
'vlang/ui': '3201'
'vlang/vtl': '123'
}, true).trim_space() == "name: Peter
age: 25
numbers: [1, 2, 3]
1
2
3
3'
0 - 0
2 - 1
4 - 2
6 - 3
8 - 4
10 - 5
12 - 6
14 - 7
16 - 8
18 - 9
vlang/ui, downloaded 3201 times.
vlang/vtl, downloaded 123 times.
this is not ignored
so, it's basically true"
}

View File

@ -30,16 +30,16 @@ pub fn compile_template(basepath string, html_ string, fn_name string) string {
mut html := html_.trim_space()
mut header := ''
mut footer := ''
if os.exists('templates/header.html') && html.contains('@header') {
h := os.read_file('templates/header.html') or {
panic('reading file templates/header.html failed')
if os.exists(os.join_path(basepath, 'header.html')) && html.contains('@header') {
h := os.read_file(os.join_path(basepath, 'header.html')) or {
panic('reading file ${os.join_path(basepath, 'header.html')} failed')
}
header = h.trim_space().replace("'", '"')
html = header + html
}
if os.exists('templates/footer.html') && html.contains('@footer') {
f := os.read_file('templates/footer.html') or {
panic('reading file templates/footer.html failed')
if os.exists(os.join_path(basepath, 'footer.html')) && html.contains('@footer') {
f := os.read_file(os.join_path(basepath, 'footer.html')) or {
panic('reading file ${os.join_path(basepath, 'footer.html')} failed')
}
footer = f.trim_space().replace("'", '"')
html += footer
@ -82,22 +82,18 @@ _ = footer
file_ext = '.html'
}
file_name = file_name.replace(file_ext, '')
mut templates_folder := os.join_path(basepath, 'templates')
if file_name.contains('/') {
if file_name.starts_with('/') {
// absolute path
templates_folder = ''
} else {
// relative path, starting with the current folder
templates_folder = os.real_path(basepath)
}
// relative path, starting with the current folder
mut templates_folder := os.real_path(basepath)
if file_name.contains('/') && file_name.starts_with('/') {
// an absolute path
templates_folder = ''
}
file_path := os.real_path(os.join_path(templates_folder, '$file_name$file_ext'))
$if trace_tmpl ? {
eprintln('>>> basepath: "$basepath" , fn_name: "$fn_name" , @include line: "$line" , file_name: "$file_name" , file_ext: "$file_ext" , templates_folder: "$templates_folder" , file_path: "$file_path"')
}
file_content := os.read_file(file_path) or {
panic('Vweb: Reading file $file_name failed.')
panic('Vweb: reading file $file_name from path: $file_path failed.')
}
file_splitted := file_content.split_into_lines().reverse()
for f in file_splitted {
@ -120,10 +116,16 @@ _ = footer
s.writeln('if ' + line[pos + 4..] + '{')
s.writeln(tmpl.str_start)
} else if line.contains('@end') {
// Remove new line byte
s.go_back(1)
s.writeln(tmpl.str_end)
s.writeln('}')
s.writeln(tmpl.str_start)
} else if line.contains('@else') {
// Remove new line byte
s.go_back(1)
s.writeln(tmpl.str_end)
s.writeln(' } else { ')
s.writeln(tmpl.str_start)
@ -155,7 +157,7 @@ _ = footer
} else {
// HTML, may include `@var`
// escaped by cgen, unless it's a `vweb.RawHtml` string
s.writeln(line.replace('@', '$').replace("'", '"'))
s.writeln(line.replace('@', '$').replace('$$', '@').replace("'", "\\'"))
}
}
s.writeln(tmpl.str_end)