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)
 | 
			
		||||
	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
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
name: @name
 | 
			
		||||
 | 
			
		||||
age: @age
 | 
			
		||||
 | 
			
		||||
numbers: @numbers
 | 
			
		||||
 | 
			
		||||
@for number in numbers
 | 
			
		||||
@number
 | 
			
		||||
@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'
 | 
			
		||||
	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"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue