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 {` => `` - class := line.find_between('span.', '{').trim_space() - source.writeln('') - in_span = true - } else if state == .html && line.trim_space().starts_with('.') && line.ends_with('{') { - // `.header {` => `
` - class := line.find_between('.', '{').trim_space() - trimmed := line.trim_space() - source.write_string(strings.repeat(`\t`, line.len - trimmed.len)) // add the necessary indent to keep
code clean - source.writeln('
') - } else if state == .html && line.starts_with('#') && line.ends_with('{') { - // `#header {` => `