class Object

Public Instance Methods

_load_document(path) click to toggle source

Internal

# File lib/document.rb, line 138
def _load_document(path)

  # Remote document
  if path.start_with?('http')
    return Net::HTTP.get(URI(path))

  # Local document
  else
    return File.read(path)
  end

end
_parse_document(contents) click to toggle source
# File lib/document.rb, line 152
def _parse_document(contents)
  elements = []
  codeblock = ''
  capture = false

  # Parse file lines
  for line in contents.strip().split("\n")

    # Heading
    if line.start_with?('#')
      heading = line.strip().tr('#', '')
      level = line.length - line.tr('#', '').length
      if (!elements.empty? &&
          elements[-1]['type'] == 'heading' &&
          elements[-1]['level'] == level)
        next
      end
      elements.push({
        'type' => 'heading',
        'value' => heading,
        'level' => level,
      })
    end

    # Codeblock
    if line.start_with?('```ruby')
      if line.include?('goodread')
        capture = true
      end
      codeblock = ''
      next
    end
    if line.start_with?('```')
      if capture
        elements.push({
          'type' => 'codeblock',
          'value' => codeblock,
        })
      end
      capture = false
    end
    if capture && !line.empty?
      codeblock += line + "\n"
      next
    end

  end

  return elements
end
_validate_document(elements, exit_first:false) click to toggle source
# File lib/document.rb, line 204
def _validate_document(elements, exit_first:false)
  scope = binding()
  passed = 0
  failed = 0
  skipped = 0
  title = nil
  exception = nil

  # Test elements
  for element in elements

    # Heading
    if element['type'] == 'heading'
      print_message(element['value'], 'heading', level:element['level'])
      if title == nil
        title = element['value']
        print_message(nil, 'separator')
      end

    # Codeblock
    elsif element['type'] == 'codeblock'
      exception, exception_line = run_codeblock(element['value'], scope)
      lines = element['value'].strip().split("\n")
      for line, index in lines.each_with_index
        line_number = index + 1
        if line_number < exception_line
          print_message(line, 'success')
          passed += 1
        elsif line_number == exception_line
          print_message(line, 'failure', exception:exception)
          if exit_first
            print_message(scope, 'scope')
            raise exception
          end
          failed += 1
        elsif line_number > exception_line
          print_message(line, 'skipped')
          skipped += 1
        end
      end
    end

  end

  # Print summary
  if title != nil
    print_message(title, 'summary', passed:passed, failed:failed, skipped:skipped)
  end

  return {
    'valid' => exception == nil,
    'passed' => passed,
    'failed' => failed,
    'skipped' => skipped,
  }
end
print_message(message, type, level: nil, exception: nil, passed: nil, failed: nil, skipped: nil) click to toggle source
read_config() click to toggle source

Module API

# File lib/helpers.rb, line 9
def read_config()
  config = {'documents' => ['README.md']}
  if File.file?('goodread.yml')
    config = YAML.load(File.read('goodread.yml'))
    for document, index in config['documents'].each_with_index
      if document.is_a?(Hash)
        if !document.include?('main')
          raise Exception.new('Document requires "main" property')
        end
      end
      if document.is_a?(String)
        config['documents'][index] = {'main' => document}
      end
    end
  end
  return config
end
run_codeblock(codeblock, scope) click to toggle source
# File lib/helpers.rb, line 28
def run_codeblock(codeblock, scope)
  lines = []
  for line in codeblock.strip().split("\n")
    if line.include?(' # ')
      left, right = line.split(' # ')
      left = left.strip()
      right = right.strip()
      if left && right
        message = "#{left} != #{right}"
        line = "raise '#{message}' unless #{left} == #{right}"
      end
    end
    lines.push(line)
  end
  exception_line = 1000 # infiinity
  exception = nil
  begin
    eval(lines.join("\n"), scope)
  rescue Exception => exc
    exception = exc
    exception_line = 1
  end
  return [exception, exception_line]
end