diff --git a/vlib/v/parser/tmpl.v b/vlib/v/parser/tmpl.v
index 6d786f86fd..ab66450415 100644
--- a/vlib/v/parser/tmpl.v
+++ b/vlib/v/parser/tmpl.v
@@ -9,12 +9,29 @@ import os
import strings
enum State {
- html
+ simple // default - no special interpretation of tags, *at all*!
+ // That is suitable for the general case of text template interpolation,
+ // for example for interpolating arbitrary source code (even V source) templates.
+ //
+ html // default, only when the template extension is .html
css // ' {
+ state = .html
+ } else if is_html_open_tag('script', line) {
+ state = .js
+ } else if trimmed_line == '' {
+ state = .html
+ }
+}
+
const tmpl_str_end = "')\n"
// check HTML open tag ``
@@ -79,7 +96,7 @@ pub fn (mut p Parser) compile_template_file(template_file string, fn_name string
}
basepath := os.dir(template_file)
lstartlength := lines.len * 30
- tmpl_str_start := "sb_${fn_name}.write_string('"
+ tmpl_str_start := "\tsb_${fn_name}.write_string('"
mut source := strings.new_builder(1000)
source.writeln('
import strings
@@ -89,25 +106,24 @@ fn vweb_tmpl_${fn_name}() string {
')
source.write_string(tmpl_str_start)
- mut state := State.html
+ //
+ mut state := State.simple
+ template_ext := os.file_ext(template_file)
+ if template_ext.to_lower() == '.html' {
+ state = .html
+ }
+ //
mut in_span := false
mut end_of_line_pos := 0
mut start_of_line_pos := 0
mut tline_number := -1 // keep the original line numbers, even after insert/delete ops on lines; `i` changes
for i := 0; i < lines.len; i++ {
line := lines[i]
- trimmed_line := line.trim_space()
tline_number++
start_of_line_pos = end_of_line_pos
end_of_line_pos += line.len + 1
- if is_html_open_tag('style', line) {
- state = .css
- } else if trimmed_line == '' {
- state = .html
- } else if is_html_open_tag('script', line) {
- state = .js
- } else if trimmed_line == '' {
- state = .html
+ if state != .simple {
+ state.update(line)
}
$if trace_tmpl ? {
eprintln('>>> tfile: $template_file, spos: ${start_of_line_pos:6}, epos:${end_of_line_pos:6}, fi: ${tline_number:5}, i: ${i:5}, state: ${state:10}, line: $line')
@@ -125,7 +141,9 @@ fn vweb_tmpl_${fn_name}() string {
}
reporter: .parser
})
- } else if line.contains('@footer') {
+ continue
+ }
+ if line.contains('@footer') {
position := line.index('@footer') or { 0 }
p.error_with_error(errors.Error{
message: "Please use @include 'footer' instead of @footer (deprecated)"
@@ -138,6 +156,7 @@ fn vweb_tmpl_${fn_name}() string {
}
reporter: .parser
})
+ continue
}
if line.contains('@include ') {
lines.delete(i)
@@ -179,83 +198,131 @@ fn vweb_tmpl_${fn_name}() string {
lines.insert(i, f)
}
i--
- } else if line.contains('@js ') {
- pos := line.index('@js') or { continue }
- source.write_string('')
- } else if line.contains('@css ') {
- pos := line.index('@css') or { continue }
- source.write_string('')
- } else if line.contains('@if ') {
+ continue
+ }
+ if line.contains('@if ') {
source.writeln(parser.tmpl_str_end)
pos := line.index('@if') or { continue }
source.writeln('if ' + line[pos + 4..] + '{')
source.writeln(tmpl_str_start)
- } else if line.contains('@end') {
+ continue
+ }
+ if line.contains('@end') {
// Remove new line byte
source.go_back(1)
source.writeln(parser.tmpl_str_end)
source.writeln('}')
source.writeln(tmpl_str_start)
- } else if line.contains('@else') {
+ continue
+ }
+ if line.contains('@else') {
// Remove new line byte
source.go_back(1)
source.writeln(parser.tmpl_str_end)
source.writeln(' } else { ')
source.writeln(tmpl_str_start)
- } else if line.contains('@for') {
+ continue
+ }
+ if line.contains('@for') {
source.writeln(parser.tmpl_str_end)
pos := line.index('@for') or { continue }
source.writeln('for ' + line[pos + 4..] + '{')
source.writeln(tmpl_str_start)
- } else if state == .html && line.starts_with('span.') && line.ends_with('{') {
- // `span.header {` => `