| 1 | module document |
| 2 | |
| 3 | import os |
| 4 | |
| 5 | pub const should_sort = os.getenv_opt('VDOC_SORT') or { 'true' }.bool() |
| 6 | |
| 7 | pub fn (nodes []DocNode) find(symname string) !DocNode { |
| 8 | for node in nodes { |
| 9 | if node.name == symname { |
| 10 | return node |
| 11 | } |
| 12 | } |
| 13 | return error('symbol not found') |
| 14 | } |
| 15 | |
| 16 | // arrange sorts the DocNodes based on their symbols and names. |
| 17 | pub fn (mut nodes []DocNode) arrange() { |
| 18 | if !should_sort { |
| 19 | return |
| 20 | } |
| 21 | mut kinds := []SymbolKind{} |
| 22 | for v in nodes { |
| 23 | if v.kind !in kinds { |
| 24 | kinds << v.kind |
| 25 | } |
| 26 | } |
| 27 | kinds.sort_with_compare(compare_sym_kinds) |
| 28 | mut res := []DocNode{} |
| 29 | for k in kinds { |
| 30 | mut kind_nodes := nodes.filter(it.kind == k) |
| 31 | kind_nodes.sort(a.name < b.name) |
| 32 | res << kind_nodes |
| 33 | } |
| 34 | nodes = res.clone() |
| 35 | } |
| 36 | |
| 37 | fn compare_sym_kinds(a &SymbolKind, b &SymbolKind) int { |
| 38 | ak := int(*a) |
| 39 | bk := int(*b) |
| 40 | return match true { |
| 41 | ak < bk { -1 } |
| 42 | ak > bk { 1 } |
| 43 | else { 0 } |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | // arr() converts the map into an array of `DocNode`. |
| 48 | pub fn (cnts map[string]DocNode) arr() []DocNode { |
| 49 | mut contents := cnts.values() |
| 50 | contents.arrange() |
| 51 | return contents |
| 52 | } |
| 53 | |
| 54 | // merge_comments returns a `string` with the combined contents of `DocNode.comments`. |
| 55 | pub fn (dc DocNode) merge_comments() string { |
| 56 | return merge_doc_comments(dc.comments) |
| 57 | } |
| 58 | |
| 59 | // merge_comments_without_examples returns a `string` with the |
| 60 | // combined contents of `DocNode.comments` - excluding any examples. |
| 61 | pub fn (dc DocNode) merge_comments_without_examples() string { |
| 62 | mut sans_examples := []DocComment{cap: dc.comments.len} |
| 63 | for i := 0; i < dc.comments.len; i++ { |
| 64 | if dc.comments[i].is_example() { |
| 65 | continue |
| 66 | } |
| 67 | if dc.comments[i].is_multi_line_example() { |
| 68 | i++ |
| 69 | if i == dc.comments.len || !dc.comments[i].has_triple_backtick() { |
| 70 | eprintln('${dc.file_path}:${dc.pos.line_nr}: warning: expected code block after empty example line:') |
| 71 | eprintln('// ```') |
| 72 | if i < dc.comments.len { |
| 73 | eprintln('Found:') |
| 74 | eprintln('//' + dc.comments[i].text[1..]) |
| 75 | } |
| 76 | } |
| 77 | i++ |
| 78 | for i < dc.comments.len && !dc.comments[i].has_triple_backtick() { |
| 79 | i++ |
| 80 | } |
| 81 | } else { |
| 82 | sans_examples << dc.comments[i] |
| 83 | } |
| 84 | } |
| 85 | return merge_doc_comments(sans_examples) |
| 86 | } |
| 87 | |
| 88 | // examples returns a `[]string` containing examples parsed from `DocNode.comments`. |
| 89 | pub fn (dn DocNode) examples() []string { |
| 90 | mut output := []string{} |
| 91 | for i := 0; i < dn.comments.len; i++ { |
| 92 | comment := dn.comments[i] |
| 93 | if comment.is_example() { |
| 94 | output << comment.example() |
| 95 | } else if comment.is_multi_line_example() { |
| 96 | i++ |
| 97 | if i + 2 < dn.comments.len && dn.comments[i].has_triple_backtick() { |
| 98 | i++ |
| 99 | mut ml_ex := '' |
| 100 | for i < dn.comments.len && !dn.comments[i].has_triple_backtick() { |
| 101 | if ml_ex.len > 0 { |
| 102 | ml_ex += '\n' |
| 103 | } |
| 104 | s := dn.comments[i].text |
| 105 | if s.len > 2 { |
| 106 | ml_ex += s[2..] |
| 107 | } |
| 108 | i++ |
| 109 | } |
| 110 | output << ml_ex |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | return output |
| 115 | } |
| 116 | |