module Asciidoctor

def self.load(input, options = {}, &block)

returns the Asciidoctor::Document

block - a callback block for handling include::[] directives
see Asciidoctor::Document#initialize for details
options - a Hash of options to control processing (default: {})
input - the AsciiDoc source as a IO, String or Array.

Document object.
input is a File, information about the file is stored in attributes on the
Accepts input as an IO (or StringIO), String or String Array object. If the

Public: Parse the AsciiDoc source input into an Asciidoctor::Document
def self.load(input, options = {}, &block)
  lines = nil
  if input.is_a?(File)
    options[:attributes] ||= {}
    attrs = options[:attributes]
    lines = input.readlines
    input_mtime = input.mtime
    input_path = File.expand_path(input.path)
    # hold off on setting infile and indir until we get a better sense of their purpose
    attrs['docfile'] = input_path
    attrs['docdir'] = File.dirname(input_path)
    attrs['docname'] = File.basename(input_path, File.extname(input_path))
    attrs['docdate'] = input_mtime.strftime('%Y-%m-%d')
    attrs['doctime'] = input_mtime.strftime('%H:%M:%S %Z')
    attrs['docdatetime'] = [attrs['docdate'], attrs['doctime']] * ' '
  elsif input.respond_to?(:readlines)
    input.rewind rescue nil
    lines = input.readlines
  elsif input.is_a?(String)
    lines = input.lines.entries
  elsif input.is_a?(Array)
    lines = input.dup
  else
    raise "Unsupported input type: #{input.class}"
  end
  Document.new(lines, options, &block) 
end

def self.load_file(filename, options = {}, &block)

returns the Asciidoctor::Document

block - a callback block for handling include::[] directives
see Asciidoctor::Document#initialize for details
options - a Hash of options to control processing (default: {})
input - the String AsciiDoc source filename

attributes on the Document.
input is a File, information about the file is stored in
Accepts input as an IO, String or String Array object. If the

Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document
def self.load_file(filename, options = {}, &block)
  Asciidoctor.load(File.new(filename), options, &block)
end

def self.render(input, options = {}, &block)

otherwise the rendered output String is returned
returns nothing if the rendered output String is written to a file,

block - a callback block for handling include::[] directives
see Asciidoctor::Document#initialize for details
options - a Hash of options to control processing (default: {})
input - the String AsciiDoc source filename

default and the rendered output is returned.
standalone document). Otherwise, the header and footer are not rendered by
rendered unless specified otherwise (writing to a file implies creating a
If the output is going to be written to a file, the header and footer are

outside of the Document#base_dir in safe mode, an IOError is raised.
written because the target directory does not exist, or because it falls
created unless the :mkdirs option is set to true. If the file cannot be
Document#base_dir. If the target directory does not exist, it will not be
path, it is resolved relative to :to_dir, if given, otherwise the
specified, the file is written to that file. If :to_file is not an absolute
corresponds to the backend format. Otherwise, if the :to_file option is
written to a file adjacent to the input file, having an extension that
If the :in_place option is true, and the input is a File, the output is

attributes on the Document.
input is a File, information about the file is stored in
Accepts input as an IO, String or String Array object. If the

to the specified backend format
Public: Parse the AsciiDoc source input into an Asciidoctor::Document and render it
def self.render(input, options = {}, &block)
  in_place = options.delete(:in_place) || false
  to_file = options.delete(:to_file)
  to_dir = options.delete(:to_dir)
  mkdirs = options.delete(:mkdirs) || false
  write_in_place = in_place && input.is_a?(File)
  write_to_target = to_file || to_dir
  raise ArgumentError, ':in_place with input file must not accompany :to_dir or :to_file' if write_in_place && write_to_target
  if !options.has_key?(:header_footer) && (write_in_place || write_to_target)
    options[:header_footer] = true
  end
  doc = Asciidoctor.load(input, options, &block)
  if write_in_place
    to_file = File.join(File.dirname(input.path), "#{doc.attributes['docname']}#{doc.attributes['outfilesuffix']}")
  elsif write_to_target
    if to_dir
      to_dir = doc.normalize_asset_path(to_dir, 'to_dir', false)
      if to_file
        # normalize again, to_file could have dirty bits
        to_file = doc.normalize_asset_path(File.expand_path(to_file, to_dir), 'to_file', false)
        # reestablish to_dir as the final target directory (in the case to_file had directory segments)
        to_dir = File.dirname(to_file)
      else
        to_file = File.join(to_dir, "#{doc.attributes['docname']}#{doc.attributes['outfilesuffix']}")
      end
    elsif to_file
      to_file = doc.normalize_asset_path(to_file, 'to_file', false)
      to_dir = File.dirname(to_file)
    end
    if !File.directory? to_dir
      if mkdirs
        Helpers.require_library 'fileutils'
        FileUtils.mkdir_p to_dir
      else
        raise IOError, "target directory does not exist: #{to_dir}"
      end
    end
  end
  if to_file
    File.open(to_file, 'w') {|file| file.write doc.render }
    nil
  else
    doc.render
  end
end

def self.render_file(filename, options = {}, &block)

otherwise the rendered output String is returned
returns nothing if the rendered output String is written to a file,

block - a callback block for handling include::[] directives
see Asciidoctor::Document#initialize for details
options - a Hash of options to control processing (default: {})
input - the String AsciiDoc source filename

and render it to the specified backend format
Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document
def self.render_file(filename, options = {}, &block)
  Asciidoctor.render(File.new(filename), options, &block)
end