diff --git a/cmd/tools/vdoc/html.v b/cmd/tools/vdoc/html.v index 96515c2e49e2ef..dd0de3aa26dfd8 100644 --- a/cmd/tools/vdoc/html.v +++ b/cmd/tools/vdoc/html.v @@ -506,43 +506,12 @@ fn html_highlight(code string, tb &ast.Table) string { fn doc_node_html(dn doc.DocNode, link string, head bool, include_examples bool, tb &ast.Table) string { mut dnw := strings.new_builder(200) head_tag := if head { 'h1' } else { 'h2' } - // Allow README.md to go through unescaped except for script tags - escaped_html := if head && is_module_readme(dn) { - readme_lines := dn.comments[0].text.split_into_lines() - mut merged_lines := []string{} - mut is_codeblock := false - for i := 0; i < readme_lines.len; i++ { - l := readme_lines[i] - nl := readme_lines[i + 1] or { - merged_lines << l - break - } - l_trimmed := l.trim_left('\x01').trim_space() - if l_trimmed.starts_with('```') { - is_codeblock = !is_codeblock - } - // -> if l_trimmed.len > 1 && (is_ul || is_ol) - is_list := l_trimmed.len > 1 && ((l_trimmed[1] == ` ` && l_trimmed[0] in [`*`, `-`]) - || (l_trimmed.len > 2 && l_trimmed[2] == ` ` && l_trimmed[1] == `.` - && l_trimmed[0].is_digit())) - if !is_codeblock && l != '' && nl != '' && !is_list - && !nl.trim_left('\x01').trim_space().starts_with('```') { - merged_lines << '${l} ${nl}' - i++ - continue - } - merged_lines << l - } - merged_lines.join_lines() - } else { - dn.merge_comments_without_examples() - } mut renderer := markdown.HtmlRenderer{ transformer: &MdHtmlCodeHighlighter{ table: tb } } - md_content := markdown.render(escaped_html, mut renderer) or { '' } + md_content := markdown.render(dn.merge_comments_without_examples(), mut renderer) or { '' } highlighted_code := html_highlight(dn.content, tb) node_class := if dn.kind == .const_group { ' const' } else { '' } sym_name := get_sym_name(dn) diff --git a/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi b/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi index cf17e0d2c590a5..8fce2eb5ef3554 100644 --- a/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi +++ b/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi @@ -137,17 +137,17 @@ List point 3 import os fn main() { - dump(os.args) - dump(os.args.len) - assert os.args.len > 0 + dump(os.args) + dump(os.args.len) + assert os.args.len > 0 - // Test escape characters like for `&` and `<` - mut arr := [1, 2, 3] - mut ref := &arr - arr << 4 + // Test escape characters like for `&` and `<` + mut arr := [1, 2, 3] + mut ref := &arr + arr << 4 - ch := chan bool{cap: 1} - ch <- true + ch := chan bool{cap: 1} + ch <- true } ``` @@ -161,42 +161,42 @@ List point 3 import time struct JwtHeader { - alg string - typ string + alg string + typ string } struct JwtPayload { - sub string - name string - iat int + sub string + name string + iat int } fn main() { - sw := time.new_stopwatch() - secret := 'your-256-bit-secret' - token := make_token(secret) - ok := auth_verify(secret, token) - dt := sw.elapsed().microseconds() - println('token: ${token}') - println('auth_verify(secret, token): ${ok}') - println('Elapsed time: ${dt} uS') + sw := time.new_stopwatch() + secret := 'your-256-bit-secret' + token := make_token(secret) + ok := auth_verify(secret, token) + dt := sw.elapsed().microseconds() + println('token: ${token}') + println('auth_verify(secret, token): ${ok}') + println('Elapsed time: ${dt} uS') } fn make_token(secret string) string { - header := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes()) - payload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes()) - signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(), - sha256.sum, sha256.block_size)) - jwt := '${header}.${payload}.${signature}' - return jwt + header := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes()) + payload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes()) + signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(), + sha256.sum, sha256.block_size)) + jwt := '${header}.${payload}.${signature}' + return jwt } fn auth_verify(secret string, token string) bool { - token_split := token.split('.') - signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(), - sha256.sum, sha256.block_size) - signature_from_token := base64.url_decode(token_split[2]) - return hmac.equal(signature_from_token, signature_mirror) + token_split := token.split('.') + signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(), + sha256.sum, sha256.block_size) + signature_from_token := base64.url_decode(token_split[2]) + return hmac.equal(signature_from_token, signature_mirror) } ``` @@ -207,12 +207,12 @@ List point 3 #include std::map my_map { - {"KEY_1", 0}, - {"KEY_2", 10}, + {"KEY_1", 0}, + {"KEY_2", 10}, }; for (const auto &[key, value] : my_map) { - std::cout << key << ": " << value << ", "; + std::cout << key << ": " << value << ", "; } std::cout << "\n"; ``` @@ -227,27 +227,27 @@ List point 3 ```v const html = ' - - - - -

Your App Content!

- - - + + + + +

Your App Content!

+ + + ' ``` @@ -255,7 +255,10 @@ List point 3 - List point 2 - List point 3 - 1. Numbered markdown list point 1 2. List point 2 3. List point 3 + 1. Numbered markdown list point 1 + 2. List point 2 + 3. List point 3 + const omega = 3 // should be first const alpha = 5 // should be in the middle diff --git a/cmd/tools/vdoc/tests/testdata/output_formats/main.text b/cmd/tools/vdoc/tests/testdata/output_formats/main.text index 01ef2829c311df..7a3927c36505ad 100644 --- a/cmd/tools/vdoc/tests/testdata/output_formats/main.text +++ b/cmd/tools/vdoc/tests/testdata/output_formats/main.text @@ -17,17 +17,17 @@ module main import os fn main() { - dump(os.args) - dump(os.args.len) - assert os.args.len > 0 + dump(os.args) + dump(os.args.len) + assert os.args.len > 0 - // Test escape characters like for `&` and `<` - mut arr := [1, 2, 3] - mut ref := &arr - arr << 4 + // Test escape characters like for `&` and `<` + mut arr := [1, 2, 3] + mut ref := &arr + arr << 4 - ch := chan bool{cap: 1} - ch <- true + ch := chan bool{cap: 1} + ch <- true } ``` @@ -41,42 +41,42 @@ module main import time struct JwtHeader { - alg string - typ string + alg string + typ string } struct JwtPayload { - sub string - name string - iat int + sub string + name string + iat int } fn main() { - sw := time.new_stopwatch() - secret := 'your-256-bit-secret' - token := make_token(secret) - ok := auth_verify(secret, token) - dt := sw.elapsed().microseconds() - println('token: ${token}') - println('auth_verify(secret, token): ${ok}') - println('Elapsed time: ${dt} uS') + sw := time.new_stopwatch() + secret := 'your-256-bit-secret' + token := make_token(secret) + ok := auth_verify(secret, token) + dt := sw.elapsed().microseconds() + println('token: ${token}') + println('auth_verify(secret, token): ${ok}') + println('Elapsed time: ${dt} uS') } fn make_token(secret string) string { - header := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes()) - payload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes()) - signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(), - sha256.sum, sha256.block_size)) - jwt := '${header}.${payload}.${signature}' - return jwt + header := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes()) + payload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes()) + signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(), + sha256.sum, sha256.block_size)) + jwt := '${header}.${payload}.${signature}' + return jwt } fn auth_verify(secret string, token string) bool { - token_split := token.split('.') - signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(), - sha256.sum, sha256.block_size) - signature_from_token := base64.url_decode(token_split[2]) - return hmac.equal(signature_from_token, signature_mirror) + token_split := token.split('.') + signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(), + sha256.sum, sha256.block_size) + signature_from_token := base64.url_decode(token_split[2]) + return hmac.equal(signature_from_token, signature_mirror) } ``` @@ -87,12 +87,12 @@ module main #include std::map my_map { - {"KEY_1", 0}, - {"KEY_2", 10}, + {"KEY_1", 0}, + {"KEY_2", 10}, }; for (const auto &[key, value] : my_map) { - std::cout << key << ": " << value << ", "; + std::cout << key << ": " << value << ", "; } std::cout << "\n"; ``` @@ -107,27 +107,27 @@ module main ```v const html = ' - - - - -

Your App Content!

- - - + + + + +

Your App Content!

+ + + ' ``` @@ -135,7 +135,10 @@ module main - List point 2 - List point 3 - 1. Numbered markdown list point 1 2. List point 2 3. List point 3 + 1. Numbered markdown list point 1 + 2. List point 2 + 3. List point 3 + const omega = 3 // should be first const alpha = 5 // should be in the middle diff --git a/vlib/v/doc/utils.v b/vlib/v/doc/utils.v index 3c50e6ffba5b64..68a5c043c869fd 100644 --- a/vlib/v/doc/utils.v +++ b/vlib/v/doc/utils.v @@ -63,9 +63,11 @@ pub fn merge_doc_comments(comments []DocComment) string { mut comment := '' mut next_on_newline := true mut is_codeblock := false + mut trimmed_indent := '' for cmt in doc_comments.reverse() { line_loop: for line in cmt.split_into_lines() { - l := line.trim_left('\x01').trim_space() + l_normalized := line.trim_left('\x01') + l := l_normalized.trim_space() last_ends_with_lb := comment.ends_with('\n') if l == '' { comment += if last_ends_with_lb { '\n' } else { '\n\n' } @@ -74,7 +76,7 @@ pub fn merge_doc_comments(comments []DocComment) string { } has_codeblock_quote := l.starts_with('```') if is_codeblock { - comment += l + '\n' + comment += l_normalized.trim_string_left(trimmed_indent) + '\n' if has_codeblock_quote { is_codeblock = !is_codeblock } @@ -86,11 +88,14 @@ pub fn merge_doc_comments(comments []DocComment) string { } comment += l + '\n' is_codeblock = !is_codeblock + trimmed_indent = l_normalized.all_before(l) next_on_newline = true continue } + is_list := l.len > 1 && ((l[1] == ` ` && l[0] in [`-`, `*`, `+`]) + || (l.len > 2 && l[2] == ` ` && l[1] == `.` && l[0].is_digit())) line_before_spaces := l.before(' ') - if (l.starts_with('|') && l.ends_with('|')) || l.starts_with('- ') + if is_list || (l.starts_with('|') && l.ends_with('|')) || (l.starts_with('#') && line_before_spaces.count('#') == line_before_spaces.len) { comment += l + '\n' next_on_newline = true