def self.next_section(reader, parent, attributes = {})
preamble = false
if parent.is_a?(Document) && parent.blocks.empty? &&
(parent.has_header? || attributes.delete('invalid-header') || !is_next_line_section?(reader, attributes))
if parent.has_header?
preamble = Block.new(parent, :preamble)
parent << preamble
end
section = parent
current_level = 0
if parent.attributes.has_key? 'fragment'
expected_next_levels = nil
elsif parent.doctype == 'book'
expected_next_levels = [0, 1]
else
expected_next_levels = [1]
end
else
section = initialize_section(reader, parent, attributes)
attributes = attributes.delete_if {|k, v| k != 'title'}
current_level = section.level
if current_level == 0 && section.special &&
section.document.doctype == 'book' && ['preface', 'appendix'].include?(section.sectname)
expected_next_levels = [current_level + 2]
else
expected_next_levels = [current_level + 1]
end
end
reader.skip_blank_lines
while reader.has_more_lines?
parse_block_metadata_lines(reader, section, attributes)
next_level = is_next_line_section? reader, attributes
if next_level
next_level += section.document.attr('leveloffset', 0).to_i
doctype = parent.document.doctype
if next_level > current_level || (section.is_a?(Document) && next_level == 0)
if next_level == 0 && doctype != 'book'
puts "asciidoctor: ERROR: line #{reader.lineno + 1}: only book doctypes can contain level 0 sections"
elsif !expected_next_levels.nil? && !expected_next_levels.include?(next_level)
puts "asciidoctor: WARNING: line #{reader.lineno + 1}: section title out of sequence: " +
"expected #{expected_next_levels.size > 1 ? 'levels' : 'level'} #{expected_next_levels * ' or '}, " +
"got level #{next_level}"
end
new_section, attributes = next_section(reader, section, attributes)
section << new_section
else
if next_level == 0 && doctype != 'book'
puts "asciidoctor: ERROR: line #{reader.lineno + 1}: only book doctypes can contain level 0 sections"
end
break
end
else
new_block = next_block(reader, (preamble || section), attributes, :parse_metadata => false)
if !new_block.nil?
(preamble || section) << new_block
attributes = {}
else
end
end
reader.skip_blank_lines
end
if preamble && !preamble.blocks?
section.delete_at(0)
end
[section != parent ? section : nil, attributes.dup]
end