tmpl: fix doubling templates folder path and enhancements (#9029)
parent
15896beace
commit
506041a15b
|
@ -80,14 +80,15 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
|
||||||
}
|
}
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
spos := p.tok.position()
|
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 {
|
if !is_html {
|
||||||
p.check(.string)
|
p.check(.string)
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
// $embed_file('/path/to/file')
|
// $embed_file('/path/to/file')
|
||||||
if is_embed_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.
|
// Validate that the epath exists, and that it is actually a file.
|
||||||
if epath == '' {
|
if epath == '' {
|
||||||
p.error_with_pos('supply a valid relative or absolute file path to the file to embed',
|
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
|
scope: 0
|
||||||
is_embed: true
|
is_embed: true
|
||||||
embed_file: ast.EmbeddedFile{
|
embed_file: ast.EmbeddedFile{
|
||||||
rpath: s
|
rpath: literal_string_param
|
||||||
apath: epath
|
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
|
// Compile vweb html template to V code, parse that V code and embed the resulting V function
|
||||||
// that returns an html string.
|
// that returns an html string.
|
||||||
fn_path := p.cur_fn_name.split('_')
|
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
|
// Looking next to the vweb program
|
||||||
dir := os.dir(p.scanner.file_path.replace('/', os.path_separator))
|
dir := os.dir(compiled_vfile_path)
|
||||||
mut path := os.join_path(dir, fn_path.join(os.path_separator))
|
mut path := os.join_path(dir, fn_path_joined)
|
||||||
path += '.html'
|
path += '.html'
|
||||||
path = os.real_path(path)
|
path = os.real_path(path)
|
||||||
if !is_html {
|
if !is_html {
|
||||||
|
@ -139,7 +142,7 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
|
||||||
if !os.exists(path) {
|
if !os.exists(path) {
|
||||||
// can be in `templates/`
|
// can be in `templates/`
|
||||||
if is_html {
|
if is_html {
|
||||||
path = os.join_path(dir, 'templates', fn_path.join('/'))
|
path = os.join_path(dir, 'templates', fn_path_joined)
|
||||||
path += '.html'
|
path += '.html'
|
||||||
}
|
}
|
||||||
if !os.exists(path) {
|
if !os.exists(path) {
|
||||||
|
@ -152,10 +155,10 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
|
||||||
}
|
}
|
||||||
// println('path is now "$path"')
|
// println('path is now "$path"')
|
||||||
}
|
}
|
||||||
if p.pref.is_verbose {
|
|
||||||
println('>>> compiling comptime template file "$path"')
|
|
||||||
}
|
|
||||||
tmp_fn_name := p.cur_fn_name.replace('.', '__')
|
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)
|
v_code := tmpl.compile_file(path, tmp_fn_name)
|
||||||
$if print_vweb_template_expansions ? {
|
$if print_vweb_template_expansions ? {
|
||||||
lines := v_code.split('\n')
|
lines := v_code.split('\n')
|
||||||
|
@ -167,12 +170,12 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
|
||||||
start_pos: 0
|
start_pos: 0
|
||||||
parent: p.global_scope
|
parent: p.global_scope
|
||||||
}
|
}
|
||||||
if p.pref.is_verbose {
|
$if trace_comptime ? {
|
||||||
println('\n\n')
|
println('')
|
||||||
println('>>> vweb template for $path:')
|
println('>>> vweb template for $path:')
|
||||||
println(v_code)
|
println(v_code)
|
||||||
println('>>> end of vweb template END')
|
println('>>> end of vweb template END')
|
||||||
println('\n\n')
|
println('')
|
||||||
}
|
}
|
||||||
mut file := parse_comptime(v_code, p.table, p.pref, scope, p.global_scope)
|
mut file := parse_comptime(v_code, p.table, p.pref, scope, p.global_scope)
|
||||||
file = ast.File{
|
file = ast.File{
|
||||||
|
@ -207,7 +210,7 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
|
||||||
is_vweb: true
|
is_vweb: true
|
||||||
vweb_tmpl: file
|
vweb_tmpl: file
|
||||||
method_name: n
|
method_name: n
|
||||||
args_var: s
|
args_var: literal_string_param
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
name: @name
|
name: @name
|
||||||
|
|
||||||
age: @age
|
age: @age
|
||||||
|
|
||||||
numbers: @numbers
|
numbers: @numbers
|
||||||
|
|
||||||
@for number in numbers
|
@for number in numbers
|
||||||
@number
|
@number
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@include 'inner.txt'
|
|
@ -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
|
|
@ -2,40 +2,84 @@ fn one() string {
|
||||||
name := 'Peter'
|
name := 'Peter'
|
||||||
age := 25
|
age := 25
|
||||||
numbers := [1, 2, 3]
|
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() {
|
fn test_tmpl() {
|
||||||
assert one().trim_space() == 'name: Peter
|
assert one().trim_space() == "name: Peter
|
||||||
|
|
||||||
age: 25
|
age: 25
|
||||||
|
|
||||||
numbers: [1, 2, 3]
|
numbers: [1, 2, 3]
|
||||||
|
|
||||||
|
|
||||||
1
|
1
|
||||||
|
|
||||||
2
|
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() {
|
fn test_tmpl_in_anon_fn() {
|
||||||
anon := fn (name string, age int, numbers []int) string {
|
anon := fn (name string, age int, numbers []int, downloads map[string]string, ignored bool) string {
|
||||||
return $tmpl('tmpl/1.txt')
|
|
||||||
|
return $tmpl('tmpl/base.txt')
|
||||||
}
|
}
|
||||||
|
|
||||||
println(anon('Peter', 25, [1, 2, 3]))
|
assert anon('Peter', 25, [1, 2, 3], map{
|
||||||
assert anon('Peter', 25, [1, 2, 3]).trim_space() == 'name: Peter
|
'vlang/ui': '3201'
|
||||||
|
'vlang/vtl': '123'
|
||||||
|
}, true).trim_space() == "name: Peter
|
||||||
age: 25
|
age: 25
|
||||||
|
|
||||||
numbers: [1, 2, 3]
|
numbers: [1, 2, 3]
|
||||||
|
|
||||||
|
|
||||||
1
|
1
|
||||||
|
|
||||||
2
|
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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,16 +30,16 @@ pub fn compile_template(basepath string, html_ string, fn_name string) string {
|
||||||
mut html := html_.trim_space()
|
mut html := html_.trim_space()
|
||||||
mut header := ''
|
mut header := ''
|
||||||
mut footer := ''
|
mut footer := ''
|
||||||
if os.exists('templates/header.html') && html.contains('@header') {
|
if os.exists(os.join_path(basepath, 'header.html')) && html.contains('@header') {
|
||||||
h := os.read_file('templates/header.html') or {
|
h := os.read_file(os.join_path(basepath, 'header.html')) or {
|
||||||
panic('reading file templates/header.html failed')
|
panic('reading file ${os.join_path(basepath, 'header.html')} failed')
|
||||||
}
|
}
|
||||||
header = h.trim_space().replace("'", '"')
|
header = h.trim_space().replace("'", '"')
|
||||||
html = header + html
|
html = header + html
|
||||||
}
|
}
|
||||||
if os.exists('templates/footer.html') && html.contains('@footer') {
|
if os.exists(os.join_path(basepath, 'footer.html')) && html.contains('@footer') {
|
||||||
f := os.read_file('templates/footer.html') or {
|
f := os.read_file(os.join_path(basepath, 'footer.html')) or {
|
||||||
panic('reading file templates/footer.html failed')
|
panic('reading file ${os.join_path(basepath, 'footer.html')} failed')
|
||||||
}
|
}
|
||||||
footer = f.trim_space().replace("'", '"')
|
footer = f.trim_space().replace("'", '"')
|
||||||
html += footer
|
html += footer
|
||||||
|
@ -82,22 +82,18 @@ _ = footer
|
||||||
file_ext = '.html'
|
file_ext = '.html'
|
||||||
}
|
}
|
||||||
file_name = file_name.replace(file_ext, '')
|
file_name = file_name.replace(file_ext, '')
|
||||||
mut templates_folder := os.join_path(basepath, 'templates')
|
// relative path, starting with the current folder
|
||||||
if file_name.contains('/') {
|
mut templates_folder := os.real_path(basepath)
|
||||||
if file_name.starts_with('/') {
|
if file_name.contains('/') && file_name.starts_with('/') {
|
||||||
// absolute path
|
// an absolute path
|
||||||
templates_folder = ''
|
templates_folder = ''
|
||||||
} else {
|
|
||||||
// relative path, starting with the current folder
|
|
||||||
templates_folder = os.real_path(basepath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
file_path := os.real_path(os.join_path(templates_folder, '$file_name$file_ext'))
|
file_path := os.real_path(os.join_path(templates_folder, '$file_name$file_ext'))
|
||||||
$if trace_tmpl ? {
|
$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"')
|
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 {
|
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()
|
file_splitted := file_content.split_into_lines().reverse()
|
||||||
for f in file_splitted {
|
for f in file_splitted {
|
||||||
|
@ -120,10 +116,16 @@ _ = footer
|
||||||
s.writeln('if ' + line[pos + 4..] + '{')
|
s.writeln('if ' + line[pos + 4..] + '{')
|
||||||
s.writeln(tmpl.str_start)
|
s.writeln(tmpl.str_start)
|
||||||
} else if line.contains('@end') {
|
} else if line.contains('@end') {
|
||||||
|
// Remove new line byte
|
||||||
|
s.go_back(1)
|
||||||
|
|
||||||
s.writeln(tmpl.str_end)
|
s.writeln(tmpl.str_end)
|
||||||
s.writeln('}')
|
s.writeln('}')
|
||||||
s.writeln(tmpl.str_start)
|
s.writeln(tmpl.str_start)
|
||||||
} else if line.contains('@else') {
|
} else if line.contains('@else') {
|
||||||
|
// Remove new line byte
|
||||||
|
s.go_back(1)
|
||||||
|
|
||||||
s.writeln(tmpl.str_end)
|
s.writeln(tmpl.str_end)
|
||||||
s.writeln(' } else { ')
|
s.writeln(' } else { ')
|
||||||
s.writeln(tmpl.str_start)
|
s.writeln(tmpl.str_start)
|
||||||
|
@ -155,7 +157,7 @@ _ = footer
|
||||||
} else {
|
} else {
|
||||||
// HTML, may include `@var`
|
// HTML, may include `@var`
|
||||||
// escaped by cgen, unless it's a `vweb.RawHtml` string
|
// 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)
|
s.writeln(tmpl.str_end)
|
||||||
|
|
Loading…
Reference in New Issue