class Ronn::Document

extracted from the document’s name section.
generated documentation unless overridden by the information
“<name>.<section>.ronn”. The <name> and <section> are used in
Ronn files may optionally follow the naming convention:
HTML.
and to convert a ronn document into other formats, like roff or
The Document class can be used to load and inspect a ronn document

def basename(type=nil)

defined in the document.
the source file path but falls back on the name and section
for the given file extension. Uses the name and section from
Generate a file basename of the form ".
."
def basename(type=nil)
  type = nil if ['', 'roff'].include?(type.to_s)
  [path_name || @name, path_section || @section, type].
  compact.join('.')
end

def convert(format)

return the result as a string.
Convert the document to :roff, :html, or :html_fragment and
def convert(format)
  send "to_#{format}"
end

def date

the current time.
this is the file's modified time or, if no file is given,
The date the man page was published. If not set explicitly,
def date
  return @date if @date
  return File.mtime(path) if File.exist?(path)
  Time.now
end

def html

A Hpricot::Document for the manual content fragment.
def html
  @html ||= process_html!
end

def html_filter_angle_quotes

Perform angle quote () post filtering.
def html_filter_angle_quotes
  # convert all angle quote vars nested in code blocks
  # back to the original text
  @html.search('code').search('text()').each do |node|
    next unless node.to_html.include?('var&gt;')
    new =
      node.to_html.
        gsub('&lt;var&gt;', '&lt;').
        gsub("&lt;/var&gt;", '>')
    node.swap(new)
  end
end

def html_filter_annotate_bare_links

whose text labels are the same as their href URLs.
Add a 'data-bare-link' attribute to hyperlinks
def html_filter_annotate_bare_links
  @html.search('a[@href]').each do |node|
    href = node.attributes['href']
    text = node.inner_text
    if href == text  ||
       href[0] == ?# ||
       CGI.unescapeHTML(href) == "mailto:#{CGI.unescapeHTML(text)}"
    then
      node.set_attribute('data-bare-link', 'true')
    end
  end
end

def html_filter_definition_lists

Convert special format unordered lists to definition lists.
def html_filter_definition_lists
  # process all unordered lists depth-first
  @html.search('ul').to_a.reverse.each do |ul|
    items = ul.search('li')
    next if items.any? { |item| item.inner_text.split("\n", 2).first !~ /:$/ }
    ul.name = 'dl'
    items.each do |item|
      if child = item.at('p')
        wrap = '<p></p>'
        container = child
      else
        wrap = '<dd></dd>'
        container = item
      end
      term, definition = container.inner_html.split(":\n", 2)
      dt = item.before("<dt>#{term}</dt>").first
      dt.attributes['class'] = 'flush' if dt.inner_text.length <= 7
      item.name = 'dd'
      container.swap(wrap.sub(/></, ">#{definition}<"))
    end
  end
end

def html_filter_heading_anchors

Add URL anchors to all HTML heading elements.
def html_filter_heading_anchors
  @html.search('h2|h3|h4|h5|h6').not('[@id]').each do |heading|
    heading.set_attribute('id', heading.inner_text.gsub(/\W+/, '-'))
  end
end

def html_filter_inject_name_section

def html_filter_inject_name_section
  markup =
    if title?
      "<h1>#{title}</h1>"
    elsif name
      "<h2>NAME</h2>\n" +
      "<p class='man-name'>\n  <code>#{name}</code>" +
      (tagline ? " - <span class='man-whatis'>#{tagline}</span>\n" : "\n") +
      "</p>\n"
    end
  if markup
    if @html.children
      @html.at("*").before(markup)
    else
      @html = Hpricot(markup)
    end
  end
end

def html_filter_manual_reference_links

obtaiend from the index.
Convert text of the form "name(section)" to a hyperlink. The URL is
def html_filter_manual_reference_links
  return if index.nil?
  @html.search('text()').each do |node|
    next if !node.content.include?(')')
    next if %w[pre code h1 h2 h3].include?(node.parent.name)
    next if child_of?(node, 'a')
    node.swap(
      node.content.gsub(/([0-9A-Za-z_:.+=@~-]+)(\(\d+\w*\))/) {
        name, sect = $1, $2
        if ref = index["#{name}#{sect}"]
          "<a class='man-ref' href='#{ref.url}'>#{name}<span class='s'>#{sect}</span></a>"
        else
          # warn "warn: manual reference not defined: '#{name}#{sect}'"
          "<span class='man-ref'>#{name}<span class='s'>#{sect}</span></span>"
        end
      }
    )
  end
end

def initialize(path=nil, attributes={}, &block)

for any writeable attributes defined on this class.
the intialize method returns. The attributes hash may contain values
calling the block. The document is loaded and preprocessed before
Create a Ronn::Document given a path or with the data returned by
def initialize(path=nil, attributes={}, &block)
  @path = path
  @basename = path.to_s =~ /^-?$/ ? nil : File.basename(path)
  @reader = block ||
    lambda do |f|
      if ['-', nil].include?(f)
        STDIN.read
      else
        File.read(f)
      end
    end
  @data = @reader.call(path)
  @name, @section, @tagline = sniff
  @styles = %w[man]
  @manual, @organization, @date = nil
  @markdown, @input_html, @html = nil
  @index = Ronn::Index[path || '.']
  @index.add_manual(self) if path && name
  attributes.each { |attr_name,value| send("#{attr_name}=", value) }
end

def input_html

def input_html
  @input_html ||= strip_heading(Markdown.new(markdown).to_html)
end

def markdown

Preprocessed markdown input text.
def markdown
  @markdown ||= process_markdown!
end

def markdown_filter_angle_quotes(markdown)

Convert to WORD but only if WORD isn't an HTML tag.
def markdown_filter_angle_quotes(markdown)
  markdown.gsub(/\<([^:.\/]+?)\>/) do |match|
    contents = $1
    tag, attrs = contents.split(' ', 2)
    if attrs =~ /\/=/ || html_element?(tag.sub(/^\//, '')) ||
       data.include?("</#{tag}>")
      match.to_s
    else
      "<var>#{contents}</var>"
    end
  end
end

def markdown_filter_heading_anchors(markdown)

This lets us use the [SECTION-REF][] syntax
Add [id]: #ANCHOR elements to the markdown source text for all sections.
def markdown_filter_heading_anchors(markdown)
  first = true
  markdown.split("\n").grep(/^[#]{2,5} +[\w '-]+[# ]*$/).each do |line|
    markdown << "\n\n" if first
    first = false
    title = line.gsub(/[^\w -]/, '').strip
    anchor = title.gsub(/\W+/, '-').gsub(/(^-+|-+$)/, '')
    markdown << "[#{title}]: ##{anchor} \"#{title}\"\n"
  end
  markdown
end

def markdown_filter_link_index(markdown)

links. This lets us use [foo(3)][] syntax to link to index entries.
Appends all index links to the end of the document as Markdown reference
def markdown_filter_link_index(markdown)
  return markdown if index.nil? || index.empty?
  markdown << "\n\n"
  index.each { |ref| markdown << "[#{ref.name}]: #{ref.url}\n" }
end

def name

contents and then on the path name.
Returns the manual page name based first on the document's
def name
  @name || path_name
end

def name?

of the document.
Truthful when the name was extracted from the name section
def name?
  !@name.nil?
end

def path_for(type=nil)

appends it to the dirname of the source document.
Document#basename method to generate the basename part and
Construct a path for a file near the source file. Uses the
def path_for(type=nil)
  if @basename
    File.join(File.dirname(path), basename(type))
  else
    basename(type)
  end
end

def path_name

file contents do not include a name section.
available. This is used as the manual page name when the
Returns the part of the path, or nil when no path is
def path_name
  @basename[/^[^.]+/] if @basename
end

def path_section

no path is available.
Returns the
part of the path, or nil when
def path_section
  $1 if @basename.to_s =~ /\.(\d\w*)\./
end

def preprocess!

contents. This is called while the object is being initialized.
Parse the document and extract the name, section, and tagline from its
def preprocess!
  input_html
  nil
end

def process_html!

def process_html!
  @html = Hpricot(input_html)
  html_filter_angle_quotes
  html_filter_definition_lists
  html_filter_inject_name_section
  html_filter_heading_anchors
  html_filter_annotate_bare_links
  html_filter_manual_reference_links
  @html
end

def process_markdown!

def process_markdown!
  markdown = markdown_filter_heading_anchors(self.data)
  markdown_filter_link_index(markdown)
  markdown_filter_angle_quotes(markdown)
end

def reference_name

The name used to reference this manual.
def reference_name
  name + (section && "(#{section})").to_s
end

def section

contents and then on the path name.
Returns the manual page section based first on the document's
def section
  @section || path_section
end

def section?

section of the document.
True when the section number was extracted from the name
def section?
  !@section.nil?
end

def sniff

is represented by nil and any element may be missing.
tuple of the form: [name, section, description], where missing information
Sniff the document header and extract basic document metadata. Return a
def sniff
  html = Markdown.new(data[0, 512]).to_html
  heading, html = html.split("</h1>\n", 2)
  return [nil, nil, nil] if html.nil?
  case heading
  when /([\w_.\[\]~+=@:-]+)\s*\((\d\w*)\)\s*-+\s*(.*)/
    # name(section) -- description
    [$1, $2, $3]
  when /([\w_.\[\]~+=@:-]+)\s+-+\s+(.*)/
    # name -- description
    [$1, nil, $2]
  else
    # description
    [nil, nil, heading.sub('<h1>', '')]
  end
end

def strip_heading(html)

def strip_heading(html)
  heading, html = html.split("</h1>\n", 2)
  html || heading
end

def styles=(styles)

string module names or file paths.
Styles to insert in the generated HTML output. This is a simple Array of
def styles=(styles)
  @styles = (%w[man] + styles).uniq
end

def title

exists, this value is nil.
The document's title when no name section was defined. When a name section
def title
  @tagline if !name?
end

def title?

of custom title.
the "() -- " convention. We assume this is some kind
Truthful when the document started with an h1 but did not follow
def title?
  !name? && tagline
end

def to_h

def to_h
  %w[name section tagline manual organization date styles toc].
  inject({}) { |hash, name| hash[name] = send(name); hash }
end

def to_html

Convert the document to HTML and return the result as a string.
def to_html
  if layout = ENV['RONN_LAYOUT']
    if !File.exist?(layout_path = File.expand_path(layout))
      warn "warn: can't find #{layout}, using default layout."
      layout_path = nil
    end
  end
  template = Ronn::Template.new(self)
  template.context.push :html => to_html_fragment(wrap_class=nil)
  template.render(layout_path || 'default')
end

def to_html_fragment(wrap_class='mp')

or

def to_json

def to_json
  require 'json'
  to_h.merge('date' => date.iso8601).to_json
end

def to_markdown

def to_markdown
  markdown
end

def to_roff

Convert the document to roff and return the result as a string.
def to_roff
  RoffFilter.new(
    to_html_fragment(wrap_class=nil),
    name, section, tagline,
    manual, organization, date
  ).to_s
end

def to_yaml

def to_yaml
  require 'yaml'
  to_h.to_yaml
end

def toc

id and +text+ is the inner text of the heading element.
as an array of +[id, text]+ tuples, where +id+ is the element's generated
Retrieve a list of top-level section headings in the document and return
def toc
  @toc ||=
    html.search('h2[@id]').map { |h2| [h2.attributes['id'], h2.inner_text] }
end