|
| 1 | +module Docs |
| 2 | + class Zsh |
| 3 | + class EntriesFilter < Docs::EntriesFilter |
| 4 | + def get_name |
| 5 | + extract_header_text(at_css('h1.chapter').content) |
| 6 | + end |
| 7 | + |
| 8 | + def additional_entries |
| 9 | + entries = [] |
| 10 | + used_fns = [] |
| 11 | + |
| 12 | + css('h2.section').each do |node| |
| 13 | + type = get_type |
| 14 | + # Linkable anchor sits above <h2>. |
| 15 | + a = node.xpath('preceding-sibling::a').last |
| 16 | + header_text = extract_header_text(node.content) |
| 17 | + |
| 18 | + case type |
| 19 | + when 'Zsh Modules' |
| 20 | + module_name = header_text.match(/The (zsh\/.* Module)/)&.captures&.first |
| 21 | + header_text = module_name if module_name.present? |
| 22 | + when 'Calendar Function System' |
| 23 | + header_text << ' (Calendar)' |
| 24 | + end |
| 25 | + |
| 26 | + entries << [header_text, a['name'], type] unless header_text.start_with?('Description') |
| 27 | + end |
| 28 | + |
| 29 | + # Functions are documented within <dl> elements. |
| 30 | + # Names are wrapped in <dt>, details within <dd>. |
| 31 | + # <dd> can also contain anchors for the next function. |
| 32 | + doc.css('> dl').each do |node| |
| 33 | + type = get_type |
| 34 | + fn_names = node.css('> dt') |
| 35 | + node.css('dd a[name]').each_with_index do |anchor, i| |
| 36 | + if fn_names[i].present? && anchor['name'].present? |
| 37 | + fn_names[i]['id'] = anchor['name'] |
| 38 | + |
| 39 | + # Groups of functions are sometimes comma-delimited. |
| 40 | + # Strip arguments, flags, etc. from function name. |
| 41 | + # Skip flag-only headers. |
| 42 | + fn_names[i].inner_html.split(', ').each do |fn| |
| 43 | + fn.gsub!(/<(?:tt|var)>(.+?)<\/(?:tt|var)>/, '\1') |
| 44 | + fn = fn.split(' ').first |
| 45 | + fn.gsub!(/(?:[\[\(]).*(?:[\]\)]).*$/, '') |
| 46 | + |
| 47 | + # Add context for operators. |
| 48 | + fn << " (#{type})" if fn.length == 1 |
| 49 | + |
| 50 | + if fn.present? && !fn.match?(/^[\-\[]/) && !used_fns.include?(fn) |
| 51 | + used_fns << fn |
| 52 | + entries << [fn, anchor['name'], type] |
| 53 | + end |
| 54 | + end |
| 55 | + end |
| 56 | + end |
| 57 | + end |
| 58 | + |
| 59 | + entries |
| 60 | + end |
| 61 | + |
| 62 | + def get_type |
| 63 | + extract_header_text(at_css('h1.chapter').content) |
| 64 | + end |
| 65 | + |
| 66 | + private |
| 67 | + |
| 68 | + # Extracts text from a string, dropping indices preceding it. |
| 69 | + def extract_header_text(str) |
| 70 | + str.match(/^[\d\.]* (.*)$/)&.captures&.first |
| 71 | + end |
| 72 | + end |
| 73 | + end |
| 74 | +end |
0 commit comments