# File lib/asciidoctor/parser.rb, line 1760
  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, implicit_authors = {}, nil, nil

    if reader.has_more_lines? && !reader.next_line_empty?
      unless (author_metadata = process_authors reader.read_line).empty?
        if document
          # apply header subs and assign to document
          author_metadata.each do |key, val|
            unless document.attributes.key? key
              document.attributes[key] = ::String === val ? (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).empty?
            # 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.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

    # process author attribute entries that override (or stand in for) the implicit author line
    if document
      if document.attributes.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.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_idx, author_key, explicit, sparse = [], 1, 'author_1', false, false
        while document.attributes.key? author_key
          # only use indexed author attribute if value is different
          # leaves corner case if line matches with underscores converted to spaces; use double space to force
          if (author_override = document.attributes[author_key]) == author_metadata[author_key]
            authors << nil
            sparse = true
          else
            authors << author_override
            explicit = true
          end
          author_key = %(author_#{author_idx += 1})
        end
        if explicit
          # rebuild implicit author names to reparse
          authors.each_with_index do |author, idx|
            unless author
              authors[idx] = [
                author_metadata[%(firstname_#{name_idx = idx + 1})],
                author_metadata[%(middlename_#{name_idx})],
                author_metadata[%(lastname_#{name_idx})]
              ].compact.map {|it| it.tr ' ', '_' } * ' '
            end
          end if sparse
          # process as names only
          author_metadata = process_authors authors, true, false
        else
          author_metadata = {}
        end
      end

      unless author_metadata.empty?
        document.attributes.update author_metadata

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

    metadata
  end