class AnsibleDocGenerator::DocGenerator::RoleDocExtractor

Constants

META_KEYWORDS

Attributes

lang[R]
md_output[RW]
parsed_content[RW]
yml_path[R]

Public Class Methods

new(yml_path, lang) click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 13
def initialize yml_path, lang
  @yml_path = yml_path
  @lang = lang
  @parsed_content = {'meta' => []}
  @md_output = []
end

Public Instance Methods

call() click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 20
def call
  joined_output
end

Private Instance Methods

clean_line(keyword, line) click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 129
def clean_line(keyword, line)
  return nil unless line

  no_keyword_line = line.gsub(/@#{keyword}_#{lang}|@#{keyword}/, '')
  if %w(input output).include?(keyword)
    no_keyword_line
  else
    no_keyword_line.strip
  end
end
extract_from(keyword, lines) click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 87
def extract_from keyword, lines
  line = lines.find{|line| selectable_line?(keyword, line) }
  clean_line(keyword, line)
end
extract_multiline_from(keyword, lines, separator: ' ') click to toggle source
  • a comment, for instance, can be in several lines and only the first one will have the keyword.

  • if a new “@comment” appear, it's a new comment

  • this method always return an array, but some keywords like input or output will only use one item

# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 95
def extract_multiline_from keyword, lines, separator: ' '
  collection = []     # collection of @keyword with maybe several lines
  current_item = []   # current @keyword that will change through the loop
  current_keyword = nil

  lines.each do |line|
    # It's the beginning of a comment
    if selectable_line?(keyword, line)
      current_keyword = keyword
      # we save the previous comment before parsing the new one
      if current_item.any?
        collection << join_elements(current_item, separator)
        current_item = []
      end
      current_item << clean_line(current_keyword, line)
    # If it's another keyword but not relevant, we store current comment. But we keep the loop in case there are others
    elsif line.start_with?("@") && !selectable_line?(keyword, line) && current_item.any?
      collection << join_elements(current_item, separator)
      current_item = []
    # It's the second/third... line of a comment
    elsif current_item.any? && !line.start_with?('@')
      current_item << clean_line(current_keyword, line)
    end
  end

  collection << join_elements(current_item, separator) if current_item.any?

  collection
end
generate_md_with(task_name, params) click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 75
def generate_md_with task_name, params
  temp_md = []
  temp_md.push("### #{params[:title]}") if params[:title]
  params.fetch(:comments, []).each{|comment| temp_md << comment }
  temp_md << "```\n#{params.fetch(:input, []).join("\n")}\n```" if params[:input].length > 0
  temp_md << "Expected output: \n\n```\n#{params[:output]}\n```" if params[:output].length > 0

  non_interpolated_output = join_elements(temp_md, "\n\n")
  task = tasks.find{|task| task['name'] == task_name}
  Interpolator.new(non_interpolated_output, task, yml_path).call
end
generate_meta_content() click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 54
def generate_meta_content
  return if parsed_content['meta'] == []
  metatitle = extract_from(:metatitle, parsed_content['meta'])
  return if metatitle.nil?

  md_output << "## #{metatitle}"
end
generate_tasks_content() click to toggle source

Parse previously extracted lines and separated them by keyword

# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 63
def generate_tasks_content
  parsed_content.each do |task_name, lines|
    title = extract_from(:title, lines)

    output = extract_multiline_from(:output, lines, separator: "\n")
    input = extract_multiline_from(:input, lines, separator: "\n")
    comments = extract_multiline_from(:comment, lines)

    md_output << generate_md_with(task_name, title: title, comments: comments, output: output, input: input)
  end
end
join_elements(elements, separator) click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 140
def join_elements elements, separator
  elements.reject{|line| line.strip == '' || line.nil? }.join(separator)
end
joined_output() click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 26
def joined_output
  @joined_output ||= begin
    parse_file_comments
    generate_meta_content
    generate_tasks_content

    join_elements(md_output, "\n\n")
  end
end
parse_file_comments() click to toggle source

Extract relevant lines from the file and group them by task

# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 37
def parse_file_comments
  file = File.open(yml_path)
  current_comments = []
  file.each do |line|
    if line.start_with?('#') && META_KEYWORDS.any?{|keyword| line.start_with?("# @#{keyword}") }
      parsed_content['meta'] << line.gsub('# ', '').strip
    elsif line.start_with?('#')
      current_comments << line.gsub(/\A#\s{1}/, '')
    elsif line.start_with?('- name:')
      task_name = line.gsub('- name:','').strip
      parsed_content[task_name] = current_comments
      current_comments = []
    end
  end and nil
  file.close
end
selectable_line?(keyword, line) click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 125
def selectable_line?(keyword, line)
  line.start_with?("@#{keyword}_#{lang}") || (line.start_with?("@#{keyword}") && !line.start_with?("@#{keyword}_"))
end
tasks() click to toggle source
# File lib/ansible_doc_generator/doc_generator/role_doc_extractor.rb, line 144
def tasks
  @tasks = YAML.load_file(yml_path)
end