module Infoboxer::Navigation::Sections::Container

This module is included in {Tree::Document Document}, allowing you to navigate through document's logical sections (and also included in each {Sections::Section} instance, allowing to navigate recursively).

See also {Sections parent module} docs.

Public Instance Methods

intro() click to toggle source

All container's paragraph-level nodes before first heading.

@return {Tree::Nodes}

# File lib/infoboxer/navigation/sections.rb, line 38
def intro
  children
    .take_while { |n| !n.is_a?(Tree::Heading) }
    .select { |n| n.is_a?(Tree::BaseParagraph) }
end
lookup_children(*arg) click to toggle source
Calls superclass method
# File lib/infoboxer/navigation/sections.rb, line 97
def lookup_children(*arg)
  if arg.include?(:Section)
    sections.find(*(arg - [:Section]))
  else
    super
  end
end
sections(*names) click to toggle source

List of sections inside current container.

Examples of usage:

“`ruby document.sections # all top-level sections document.sections('Culture') # only “Culture” section document.sections(/^List of/) # all sections with heading matching pattern

document.

sections('Culture').            # long way of recieve nested section
  sections('Music')             # (Culture / Music)

document.

sections('Culture', 'Music')    # the same as above

document.

sections('Culture' => 'Music')  # pretty-looking version for 2 levels of nesting

“`

@return {Tree::Nodes<Section>}

# File lib/infoboxer/navigation/sections.rb, line 65
def sections(*names)
  @sections ||= make_sections

  if names.first.is_a?(Hash)
    h = names.shift
    h.count == 1 or fail(ArgumentError, "Undefined behavior with #{h}")
    names.unshift(h.keys.first, h.values.first)
  end

  case names.count
  when 0
    @sections
  when 1
    @sections.select { |s| names.first === s.heading.text_ }
  else
    @sections.select { |s| names.first === s.heading.text_ }.sections(*names[1..])
  end
end
subsections(*names) click to toggle source
# File lib/infoboxer/navigation/sections.rb, line 84
def subsections(*names)
  sections = names.map { |name|
    heading = lookup_children(:Heading, text_: name).first
    next unless heading

    body = heading.next_siblings
                  .take_while { |n| !n.is_a?(Tree::Heading) || n.level > heading.level }

    Section.new(heading, body)
  }.compact
  Tree::Nodes.new(sections)
end

Private Instance Methods

make_sections() click to toggle source
# File lib/infoboxer/navigation/sections.rb, line 107
def make_sections
  res = Tree::Nodes[]
  return res if headings.empty?

  level = headings.first.level

  children
    .chunk { |n| n.matches?(Tree::Heading, level: level) }
    .drop_while { |is_heading, _nodes| !is_heading }
    .each do |is_heading, nodes|
      if is_heading
        nodes.each do |node|
          res << Section.new(node)
        end
      else
        res.last.push_children(*nodes)
      end
    end

  res
end