class Asciidoctor::Parser

def self.parse_document_header(reader, document)

returns the Hash of orphan block attributes captured above the header

which are automatically removed by the reader.
This method assumes that there are no blank lines at the start of the document,

after parsing is complete.
attributes are then saved to establish a save point to which to rollback
the header (document title, document attributes, etc). The document
header is reached. The Document object is populated with information from
Reads the AsciiDoc source from the Reader until the end of the document

Public: Parses the document header of the AsciiDoc source read from the Reader
def self.parse_document_header(reader, document)
  # capture lines of block-level metadata and plow away comment lines that precede first block
  block_attrs = parse_block_metadata_lines reader, document
  doc_attrs = document.attributes
  # special case, block title is not allowed above document title,
  # carry attributes over to the document body
  if (implicit_doctitle = is_next_line_doctitle? reader, block_attrs, doc_attrs['leveloffset']) && block_attrs['title']
    return document.finalize_header block_attrs, false
  end
  # yep, document title logic in AsciiDoc is just insanity
  # definitely an area for spec refinement
  unless (val = doc_attrs['doctitle']).nil_or_empty?
    document.title = doctitle_attr_val = val
  end
  # if the first line is the document title, add a header to the document and parse the header metadata
  if implicit_doctitle
    source_location = reader.cursor if document.sourcemap
    document.id, _, l0_section_title, _, atx = parse_section_title reader, document
    if doctitle_attr_val
      # NOTE doctitle attribute (set above or below implicit doctitle) overrides implicit doctitle
      l0_section_title = nil
    else
      document.title = l0_section_title
      doc_attrs['doctitle'] = doctitle_attr_val = document.apply_header_subs l0_section_title
    end
    document.header.source_location = source_location if source_location
    # default to compat-mode if document has setext doctitle
    doc_attrs['compat-mode'] = '' unless atx || (document.attribute_locked? 'compat-mode')
    if (separator = block_attrs['separator'])
      doc_attrs['title-separator'] = separator unless document.attribute_locked? 'title-separator'
    end
    if (doc_id = block_attrs['id'])
      document.id = doc_id
    else
      doc_id = document.id
    end
    if (role = block_attrs['role'])
      doc_attrs['role'] = role
    end
    if (reftext = block_attrs['reftext'])
      doc_attrs['reftext'] = reftext
    end
    block_attrs.clear
    (modified_attrs = document.instance_variable_get :@attributes_modified).delete 'doctitle'
    parse_header_metadata reader, document
    if modified_attrs.include? 'doctitle'
      if (val = doc_attrs['doctitle']).nil_or_empty? || val == doctitle_attr_val
        doc_attrs['doctitle'] = doctitle_attr_val
      else
        document.title = val
      end
    elsif !l0_section_title
      modified_attrs << 'doctitle'
    end
    document.register :refs, [doc_id, document] if doc_id
  end
  # parse title and consume name section of manpage document
  parse_manpage_header reader, document, block_attrs if document.doctype == 'manpage'
  # NOTE block_attrs are the block-level attributes (not document attributes) that
  # precede the first line of content (document title, first section or first block)
  document.finalize_header block_attrs
end