# File lib/asciidoctor/parser.rb, line 1805
  def self.parse_header_metadata(reader, document = nil)
    # NOTE this will discard away any comment lines, but not skip blank lines
    process_attribute_entries(reader, document)

    metadata = {}
    implicit_author = nil
    implicit_authors = nil

    if reader.has_more_lines? && !reader.next_line_empty?
      author_metadata = process_authors reader.read_line

      unless author_metadata.empty?
        if document
          # apply header subs and assign to document
          author_metadata.each do |key, val|
            unless document.attributes.has_key? key
              document.attributes[key] = ((val.is_a? ::String) ? document.apply_header_subs(val) : val)
            end
          end

          implicit_author = document.attributes['author']
          implicit_authors = document.attributes['authors']
        end

        metadata = author_metadata
      end

      # NOTE this will discard any comment lines, but not skip blank lines
      process_attribute_entries(reader, document)

      rev_metadata = {}

      if reader.has_more_lines? && !reader.next_line_empty?
        rev_line = reader.read_line
        if (match = RevisionInfoLineRx.match(rev_line))
          rev_metadata['revnumber'] = match[1].rstrip if match[1]
          unless (component = match[2].strip) == ''
            # version must begin with 'v' if date is absent
            if !match[1] && (component.start_with? 'v')
              rev_metadata['revnumber'] = component[1..-1]
            else
              rev_metadata['revdate'] = component
            end
          end
          rev_metadata['revremark'] = match[3].rstrip if match[3]
        else
          # throw it back
          reader.unshift_line rev_line
        end
      end

      unless rev_metadata.empty?
        if document
          # apply header subs and assign to document
          rev_metadata.each do |key, val|
            unless document.attributes.has_key? key
              document.attributes[key] = document.apply_header_subs(val)
            end
          end
        end

        metadata.update rev_metadata
      end

      # NOTE this will discard any comment lines, but not skip blank lines
      process_attribute_entries(reader, document)

      reader.skip_blank_lines
    end

    if document
      # process author attribute entries that override (or stand in for) the implicit author line
      author_metadata = nil
      if document.attributes.has_key?('author') &&
          (author_line = document.attributes['author']) != implicit_author
        # do not allow multiple, process as names only
        author_metadata = process_authors author_line, true, false
      elsif document.attributes.has_key?('authors') &&
          (author_line = document.attributes['authors']) != implicit_authors
        # allow multiple, process as names only
        author_metadata = process_authors author_line, true
      else
        authors = []
        author_key = %(author_#{authors.size + 1})
        while document.attributes.has_key? author_key
          authors << document.attributes[author_key]
          author_key = %(author_#{authors.size + 1})
        end
        if authors.size == 1
          # do not allow multiple, process as names only
          author_metadata = process_authors authors[0], true, false
        elsif authors.size > 1
          # allow multiple, process as names only
          author_metadata = process_authors authors.join('; '), true
        end
      end

      if author_metadata
        document.attributes.update author_metadata

        # special case
        if !document.attributes.has_key?('email') && document.attributes.has_key?('email_1')
          document.attributes['email'] = document.attributes['email_1']
        end
      end
    end

    metadata
  end