module Asciidoctor

Public: Methods for parsing AsciiDoc input files and converting documents using eRuby templates.

AsciiDoc documents comprise a header followed by zero or more sections. Sections are composed of blocks of content. For example:

= Doc Title

== Section 1

This is a paragraph block in the first section.

== Section 2

This section has a paragraph block and an olist block.

. Item 1
. Item 2

Examples:

Use built-in converter:

Asciidoctor.convert_file 'sample.adoc'

Use custom (Tilt-supported) templates:

Asciidoctor.convert_file 'sample.adoc', :template_dir => 'path/to/templates'

Constants

ADMONITION_STYLES
ASCIIDOC_EXTENSIONS

Set of file extensions recognized as AsciiDoc documents (stored as a truth hash)

AdmonitionParagraphRx

Matches an admonition label at the start of a paragraph.

Examples

NOTE: Just a little note.
TIP: Don't forget!
AnyListRx

Detects the start of any list item.

NOTE we only have to check as far as the blank character because we know it means non-whitespace follows.

AttributeEntryPassMacroRx

Matches the pass inline macro allowed in value of attribute assignment.

Examples

pass:[text]
AttributeEntryRx

Matches a document attribute entry.

Examples

:foo: bar
:First Name: Dan
:sectnums!:
:!toc:
:long-entry: Attribute value lines ending in ' +'
             are joined together as a single value,
             collapsing the line breaks and indentation to
             a single space.
AttributeReferenceRx

Matches an inline attribute reference.

Examples

{foo}
{counter:pcount:1}
{set:foo:bar}
{set:name!}
AtxSectionRx

Matches a single-line (Atx-style) section title.

Examples

== Foo
# ^ a level 1 (h2) section title

== Foo ==
# ^ also a level 1 (h2) section title

match is the delimiter, whose length determines the level match is the title itself match is an inline anchor, which becomes the section id

AuthorInfoLineRx

Matches the author info line immediately following the document title.

Examples

Doc Writer <doc@example.com>
Mary_Sue Brontë
BACKEND_ALIASES

Pointers to the preferred version for a given backend.

BLOCK_MATH_DELIMITERS
BOM_BYTES_UTF_16BE
BOM_BYTES_UTF_16LE
BOM_BYTES_UTF_8

Byte arrays for UTF-* Byte Order Marks hex escape sequence used for Ruby 1.8 compatibility

BlankLineRx

Matches a blank line.

NOTE allows for empty space in line as it could be left by the template engine

BlockAnchorRx

Matches an anchor (i.e., id + optional reference text) on a line above a block.

Examples

[[idname]]
[[idname,Reference Text]]
BlockAttributeLineRx

A combined pattern that matches either a block anchor or a block attribute list.

TODO this one gets hit a lot, should be optimized as much as possible

BlockAttributeListRx

Matches an attribute list above a block element.

Examples

# strictly positional
[quote, Adam Smith, Wealth of Nations]

# name/value pairs
[NOTE, caption="Good to know"]

# as attribute reference
[{lead}]
BlockTitleRx

Matches a title above a block.

Examples

.Title goes here
CC_ALL
CC_ALNUM
CC_ALPHA
CC_EOL
CC_WORD

NOTE Ruby 1.8 cannot match word characters beyond the ASCII range; if you need this feature, upgrade!

CG_ALNUM
CG_ALPHA
CG_BLANK
CG_GRAPH
CG_WORD
COERCE_ENCODING

Flag to indicate whether encoding can be coerced to UTF-8 All input data must be force encoded to UTF-8 if Encoding.default_external is not UTF-8 Addresses failures performing string operations that are reported as “invalid byte sequence in US-ASCII” Ruby 1.8 doesn't seem to experience this problem (perhaps because it isn't validating the encodings)

CalloutExtractRx

Matches a callout reference inside literal text.

Examples

<1> (optionally prefixed by //, #, -- or ;; line comment chars)
<1> <2> (multiple callouts on one line)
<!--1--> (for XML-based languages)

NOTE extract regexps are applied line-by-line, so we can use $ as end-of-line char

CalloutExtractRxt
CalloutListRx

Matches a callout list item.

Examples

<1> Foo

NOTE we know trailing (.*) will match at least one character because we strip trailing spaces

CalloutQuickScanRx

NOTE special characters have not been replaced when scanning

CalloutSourceRx

NOTE special characters have already been replaced when converting to an SGML format

CalloutSourceRxt
CellSpecEndRx
CellSpecStartRx

Parses the start and end of a cell spec (i.e., cellspec) for a table.

Examples

2.3+<.>m

FIXME use step-wise scan (or treetop) rather than this mega-regexp

ColumnSpecRx

Parses the column spec (i.e., colspec) for a table.

Examples

1*h,2*,^3e
CommentBlockRx

Matches a comment block.

Examples

////
This is a block comment.
It can span one or more lines.
////
CommentLineRx

Matches a comment line.

Examples

// an then whatever
ConditionalDirectiveRx

Matches a conditional preprocessor directive (e.g., ifdef, ifndef, ifeval and endif).

Examples

ifdef::basebackend-html[]
ifndef::theme[]
ifeval::["{asciidoctor-version}" >= "0.1.0"]
ifdef::asciidoctor[Asciidoctor!]
endif::theme[]
endif::basebackend-html[]
endif::[]
DATA_PATH

The absolute data path of the Asciidoctor RubyGem

DEFAULT_BACKEND

The backend determines the format of the converted output, default to html5

DEFAULT_DOCTYPE

The default document type Can influence markup generated by the converters

DEFAULT_EXTENSIONS

Default extensions for the respective base backends

DEFAULT_PAGE_WIDTHS

Default page widths for calculating absolute widths

DEFAULT_STYLESHEET_KEYS
DEFAULT_STYLESHEET_NAME
DELIMITED_BLOCKS
DELIMITED_BLOCK_LEADERS
DataDelimiterRx

Matches a comma or semi-colon delimiter.

Examples

one,two
three;four
DescriptionListRx

Matches a description list entry.

Examples

foo::
foo:::
foo::::
foo;;

# the term can be followed by a description on the same line...

foo:: That which precedes 'bar' (see also, <<bar>>)

# ...or on a separate line (optionally indented)

foo::
  That which precedes 'bar' (see also, <<bar>>)

# the term or description may be an attribute reference

{foo_term}:: {foo_def}

NOTE negative match for comment line is intentional since that isn't handled when looking for next list item TODO check for line comment when scanning lines instead of in regex

DescriptionListSiblingRx

Matches a sibling description list item (which does not include the type in the key).

DoubleQuotedMultiRx

Matches multiple lines of text enclosed in double quotes, capturing the quote char and text.

Examples

"I am a run-on sentence and I like
to take up multiple lines and I
still want to be matched."
DoubleQuotedRx

Matches a single-line of text enclosed in double quotes, capturing the quote char and text.

Examples

"Who goes there?"
EOL

The endline character used for output; stored in constant table as an optimization

EmailInlineMacroRx

Matches an inline e-mail address.

doc.writer@example.com
EscapedSpaceRx

Matches a space escaped by a backslash.

Examples

one\ two\ three
EvalExpressionRx

Matches a restricted (read as safe) eval expression.

Examples

"{asciidoctor-version}" >= "0.1.0"
FLEXIBLE_ATTRIBUTES

attributes which be changed within the content of the document (but not header) because it has semantic meaning; ex. sectnums

FORCE_ENCODING

Flag to indicate whether encoding of external strings needs to be forced to UTF-8

FORCE_UNICODE_LINE_LENGTH

Flag to indicate that line length should be calculated using a unicode mode hint

FloatingTitleStyleRx

Matches the block style used to designate a section title as a floating title.

Examples

[float]
= Floating Title
FootnoteInlineMacroRx

Matches an inline footnote macro, which is allowed to span multiple lines.

Examples

footnote:[text]
footnoteref:[id,text]
footnoteref:[id]
GenericBlockMacroRx

Matches the general block macro pattern.

Examples

gist::123456[]
INLINE_MATH_DELIMITERS
INTRINSIC_ATTRIBUTES

StripLineWise = /A(?:s*n)?(#{CC_ALL}*?)s*z/m end

ImageInlineMacroRx

Matches an image or icon inline macro.

Examples

image:filename.png[Alt Text]
image:http://example.com/images/filename.png[Alt Text]
image:filename.png[More [Alt\] Text] (alt text becomes "More [Alt] Text")
icon:github[large]
IncludeDirectiveRx

Matches an include preprocessor directive.

Examples

include::chapter1.ad[]
include::example.txt[lines=1;2;5..10]
IndextermInlineMacroRx

Matches an indexterm inline macro, which may span multiple lines.

Examples

indexterm:[Tigers,Big cats]
(((Tigers,Big cats)))
indexterm2:[Tigers]
((Tigers))
InlineAnchorRx

Matches an anchor (i.e., id + optional reference text) in the flow of text.

Examples

[[idname]]
[[idname,Reference Text]]
anchor:idname[]
anchor:idname[Reference Text]
InlineBiblioAnchorRx

Matches a bibliography anchor anywhere inline.

Examples

[[[Foo]]]
InlineSectionAnchorRx

Matches an anchor (i.e., id + optional reference text) inside a section title.

Examples

Section Title [[idname]]
Section Title [[idname,Reference Text]]
InvalidAttributeNameCharsRx

Matches invalid characters in an attribute name.

InvalidSectionIdCharsRx

Matches invalid characters in a section id.

KbdBtnInlineMacroRx

Matches either the kbd or btn inline macro.

Examples

kbd:[F3]
kbd:[Ctrl+Shift+T]
kbd:[Ctrl+\]]
kbd:[Ctrl,T]
btn:[Save]
KbdDelimiterRx

Matches the delimiter used for kbd value.

Examples

Ctrl + Alt+T
Ctrl,T
LAYOUT_BREAK_LINES
LIB_PATH

The absolute lib path of the Asciidoctor RubyGem

LINE_BREAK

NOTE AsciiDoc Python recognizes both a preceding TAB and a space

LINE_CONTINUATION
LINE_CONTINUATION_LEGACY
LIST_CONTINUATION
LayoutBreakLinePlusRx

Matches an AsciiDoc or Markdown horizontal rule or AsciiDoc page break.

Examples

''' or ' ' ' (horizontal rule)
--- or - - - (horizontal rule)
*** or * * * (horizontal rule)
<<< (page break)
LayoutBreakLineRx

Matches an AsciiDoc horizontal rule or AsciiDoc page break.

Examples

''' (horizontal rule)
<<< (page break)
LineBreakRx

NOTE JavaScript only treats ^ and $ as line boundaries in multiline regexp; . won't match newlines

LinkInlineMacroRx

Match a link or e-mail inline macro.

Examples

link:path[label]
mailto:doc.writer@example.com[]
LinkInlineRx

Matches an implicit link and some of the link inline macro.

Examples

http://github.com
http://github.com[GitHub]

FIXME revisit! the main issue is we need different rules for implicit vs explicit

ListRxMap

A Hash of regexps for lists used for dynamic access.

LiteralParagraphRx

Matches a literal paragraph, which is a line of text preceded by at least one space.

Examples

<SPACE>Foo
<TAB>Foo
ManpageNamePurposeRx

Matches the name and purpose in the manpage doctype.

Examples

asciidoctor - converts AsciiDoc source files to HTML, DocBook and other formats
ManpageTitleVolnumRx

Matches the title and volnum in the manpage doctype.

Examples

= asciidoctor ( 1 )
MediaBlockMacroRx

Matches an image, video or audio block macro.

Examples

image::filename.png[Caption]
video::http://youtube.com/12345[Cats vs Dogs]

Matches a menu inline macro.

Examples

menu:File[New...]
menu:View[Page Style > No Style]
menu:View[Page Style, No Style]

Matches an implicit menu inline macro.

Examples

"File > New..."
NESTABLE_LIST_CONTEXTS

LIST_CONTEXTS = [:ulist, :olist, :dlist, :colist]

NULL

The null character to use for splitting attribute values

ORDERED_LIST_KEYWORDS
ORDERED_LIST_STYLES

TODO validate use of explicit style name above ordered list (this list is for selecting an implicit style)

OrderedListMarkerRxMap

Matches the ordinals for each type of ordered list.

OrderedListRx

Matches an ordered list item (explicit numbering or up to 5 consecutive dots).

Examples

. Foo
.. Foo
1. Foo (arabic, default)
a. Foo (loweralpha)
A. Foo (upperalpha)
i. Foo (lowerroman)
I. Foo (upperroman)

NOTE leading space match is not always necessary, but is used for list reader NOTE we know trailing (.*) will match at least one character because we strip trailing spaces

PARAGRAPH_STYLES
PassInlineMacroRx

Matches several variants of the passthrough inline macro, which may span multiple lines.

Examples

+++text+++
$$text$$
pass:quotes[text]
PassInlineRx

Matches an inline passthrough value, which may span multiple lines.

Examples

+text+
`text` (compat)

NOTE we always capture the attributes so we know when to use compatible (i.e., legacy) behavior

QUOTE_SUBS
REPLACEMENTS

NOTE in Ruby 1.8.7, [^\] does not match start of line, so we need to match it explicitly order is significant

ROOT_PATH

The absolute root path of the Asciidoctor RubyGem

RUBY_ENGINE

alias the RUBY_ENGINE constant inside the Asciidoctor namespace

RevisionInfoLineRx

Matches the revision info line, which appears immediately following the author info line beneath the document title.

Examples

v1.0
2013-01-01
v1.0, 2013-01-01: Ring in the new year release
1.0, Jan 01, 2013
SECTION_LEVELS
SUPPORTS_GSUB_RESULT_HASH

Flag to indicate whether gsub can use a Hash to map matches to replacements

SetextSectionLineRx

Matches the underline in a two-line (Setext-style) section title.

Examples

======  || ------ || ~~~~~~ || ^^^^^^ || ++++++
SetextSectionTitleRx

Matches the restricted section name for a two-line (Setext-style) section title. The name cannot begin with a dot and has at least one alphanumeric character.

SpaceDelimiterRx

Matches a space delimiter that's not escaped.

Examples

one two three   four
StemInlineMacroRx

Matches a stem (and alternatives, asciimath and latexmath) inline macro, which may span multiple lines.

Examples

stem:[x != 0]
asciimath:[x != 0]
latexmath:[\sqrt{4} = 2]
SubModifierSniffRx

Matches a + or - modifier in a subs list

TAB

String for matching tab character

TagDirectiveRx

Matches a trailing tag directive in an include file.

Examples

// tag::try-catch[]
try {
  someMethod();
catch (Exception e) {
  log(e);
}
// end::try-catch[]
TocBlockMacroRx

Matches the TOC block macro.

Examples

toc::[]
toc::[levels=2]
TrailingDigitsRx

Matches one or more consecutive digits at the end of a line.

Examples

docbook45
html5
USER_HOME
UnicodeCharScanRx

Matches any character with multibyte support explicitly enabled (length of multibyte char = 1)

NOTE If necessary to hide use of the language modifier (u) from JavaScript, use (Regexp.new '.', false, 'u')

UnorderedListRx

Matches an unordered list item (one level for hyphens, up to 5 levels for asterisks).

Examples

* Foo
- Foo

NOTE we know trailing (.*) will match at least one character because we strip trailing spaces NOTE I want to use (-|([*u2022])2{0,4}) but breaks the parser since it relies on fixed match positions

UriSniffRx

Detects strings that resemble URIs.

Examples

http://domain
https://domain
file:///path
data:info

not c:/sample.adoc or c:\sample.adoc
UriTerminator

Detects the end of an implicit URI in the text

Examples

(http://google.com)
&gt;http://google.com&lt;
(See http://google.com):
VERBATIM_STYLES
VERSION
XmlSanitizeRx

Detects XML tags

XrefInlineMacroRx

Matches an xref (i.e., cross-reference) inline macro, which may span multiple lines.

Examples

<<id,reftext>>
xref:id[reftext]

NOTE special characters have already been escaped, hence the entity references

Public Class Methods

convert(input, options = {}) click to toggle source

Public: Parse the AsciiDoc source input into an Asciidoctor::Document and convert it to the specified backend format.

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

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

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

input - the String AsciiDoc source filename options - a String, Array or Hash of options to control processing (default: {})

String and Array values are converted into a Hash.
See Asciidoctor::Document#initialize for details about options.

Returns the Document object if the converted String is written to a file, otherwise the converted String

# File lib/asciidoctor.rb, line 1415
def convert input, options = {}
  options = options.dup
  options.delete(:parse)
  to_file = options.delete(:to_file)
  to_dir = options.delete(:to_dir)
  mkdirs = options.delete(:mkdirs) || false
  timings = options[:timings]

  case to_file
  when true, nil
    write_to_same_dir = !to_dir && ::File === input
    stream_output = false
    write_to_target = to_dir
    to_file = nil
  when false
    write_to_same_dir = false
    stream_output = false
    write_to_target = false
    to_file = nil
  when '/dev/null'
    return self.load input, options
  else
    write_to_same_dir = false
    stream_output = to_file.respond_to? :write
    write_to_target = stream_output ? false : to_file
  end

  unless options.key? :header_footer
    options[:header_footer] = true if write_to_same_dir || write_to_target
  end

  # NOTE at least make intended target directory available, if there is one
  if write_to_same_dir
    input_path = ::File.expand_path input.path
    options[:to_dir] = (outdir = ::File.dirname input_path)
  elsif write_to_target
    if to_dir
      if to_file
        options[:to_dir] = ::File.dirname ::File.expand_path(::File.join to_dir, to_file)
      else
        options[:to_dir] = ::File.expand_path to_dir
      end
    elsif to_file
      options[:to_dir] = ::File.dirname ::File.expand_path to_file
    end
  else
    options[:to_dir] = nil
  end

  doc = self.load input, options

  if write_to_same_dir
    outfile = ::File.join outdir, %Q(#{doc.attributes['docname']}#{doc.outfilesuffix})
    if outfile == input_path
      raise ::IOError, %Q(input file and output file cannot be the same: #{outfile})
    end
  elsif write_to_target
    working_dir = options.has_key?(:base_dir) ? ::File.expand_path(options[:base_dir]) : ::File.expand_path(::Dir.pwd)
    # QUESTION should the jail be the working_dir or doc.base_dir???
    jail = doc.safe >= SafeMode::SAFE ? working_dir : nil
    if to_dir
      outdir = doc.normalize_system_path(to_dir, working_dir, jail, :target_name => 'to_dir', :recover => false)
      if to_file
        outfile = doc.normalize_system_path(to_file, outdir, nil, :target_name => 'to_dir', :recover => false)
        # reestablish outdir as the final target directory (in the case to_file had directory segments)
        outdir = ::File.dirname outfile
      else
        outfile = ::File.join outdir, %Q(#{doc.attributes['docname']}#{doc.outfilesuffix})
      end
    elsif to_file
      outfile = doc.normalize_system_path(to_file, working_dir, jail, :target_name => 'to_dir', :recover => false)
      # establish outdir as the final target directory (in the case to_file had directory segments)
      outdir = ::File.dirname outfile
    end

    unless ::File.directory? outdir
      if mkdirs
        Helpers.mkdir_p outdir
      else
        # NOTE we intentionally refer to the directory as it was passed to the API
        raise ::IOError, %Q(target directory does not exist: #{to_dir})
      end
    end
  else
    outfile = to_file
    outdir = nil
  end

  timings.start :convert if timings
  opts = outfile && !stream_output ? { 'outfile' => outfile, 'outdir' => outdir } : {}
  output = doc.convert opts
  timings.record :convert if timings

  if outfile
    timings.start :write if timings
    doc.write output, outfile
    timings.record :write if timings

    # NOTE document cannot control this behavior if safe >= SafeMode::SERVER
    # NOTE skip if stylesdir is a URI
    if !stream_output && doc.safe < SafeMode::SECURE && (doc.attr? 'linkcss') &&
        (doc.attr? 'copycss') && (doc.attr? 'basebackend-html') &&
        !((stylesdir = (doc.attr 'stylesdir')) && (Helpers.uriish? stylesdir))
      copy_asciidoctor_stylesheet = false
      copy_user_stylesheet = false
      if (stylesheet = (doc.attr 'stylesheet'))
        if DEFAULT_STYLESHEET_KEYS.include? stylesheet
          copy_asciidoctor_stylesheet = true
        elsif !(Helpers.uriish? stylesheet)
          copy_user_stylesheet = true
        end
      end
      copy_coderay_stylesheet = (doc.attr? 'source-highlighter', 'coderay') && (doc.attr 'coderay-css', 'class') == 'class'
      copy_pygments_stylesheet = (doc.attr? 'source-highlighter', 'pygments') && (doc.attr 'pygments-css', 'class') == 'class'
      if copy_asciidoctor_stylesheet || copy_user_stylesheet || copy_coderay_stylesheet || copy_pygments_stylesheet
        stylesoutdir = doc.normalize_system_path(stylesdir, outdir, doc.safe >= SafeMode::SAFE ? outdir : nil)
        Helpers.mkdir_p stylesoutdir if mkdirs

        if copy_asciidoctor_stylesheet
          Stylesheets.instance.write_primary_stylesheet stylesoutdir
        # FIXME should Stylesheets also handle the user stylesheet?
        elsif copy_user_stylesheet
          if (stylesheet_src = (doc.attr 'copycss')).empty?
            stylesheet_src = doc.normalize_system_path stylesheet
          else
            # NOTE in this case, copycss is a source location (but cannot be a URI)
            stylesheet_src = doc.normalize_system_path stylesheet_src
          end
          stylesheet_dst = doc.normalize_system_path stylesheet, stylesoutdir, (doc.safe >= SafeMode::SAFE ? outdir : nil)
          unless stylesheet_src == stylesheet_dst || (stylesheet_content = doc.read_asset stylesheet_src).nil?
            ::File.open(stylesheet_dst, 'w') {|f|
              f.write stylesheet_content
            }
          end
        end

        if copy_coderay_stylesheet
          Stylesheets.instance.write_coderay_stylesheet stylesoutdir
        elsif copy_pygments_stylesheet
          Stylesheets.instance.write_pygments_stylesheet stylesoutdir, (doc.attr 'pygments-style')
        end
      end
    end
    doc
  else
    output
  end
end
Also aliased as: render
convert_file(filename, options = {}) click to toggle source

Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document and convert it to the specified backend format.

input - the String AsciiDoc source filename options - a String, Array or Hash of options to control processing (default: {})

String and Array values are converted into a Hash.
See Asciidoctor::Document#initialize for details about options.

Returns the Document object if the converted String is written to a file, otherwise the converted String

# File lib/asciidoctor.rb, line 1577
def convert_file filename, options = {}
  self.convert ::File.new(filename || ''), options
end
Also aliased as: render_file
load(input, options = {}) click to toggle source

Public: Parse the AsciiDoc source input into a {Document}

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

input - the AsciiDoc source as a IO, String or Array. options - a String, Array or Hash of options to control processing (default: {})

String and Array values are converted into a Hash.
See {Document#initialize} for details about these options.

Returns the Document

# File lib/asciidoctor.rb, line 1270
def load input, options = {}
  options = options.dup
  if (timings = options[:timings])
    timings.start :read
  end

  attributes = options[:attributes] = if !(attrs = options[:attributes])
    {}
  elsif ::Hash === attrs || (::RUBY_ENGINE_JRUBY && ::Java::JavaUtil::Map === attrs)
    attrs.dup
  elsif ::Array === attrs
    attrs.inject({}) do |accum, entry|
      k, v = entry.split '=', 2
      accum[k] = v || ''
      accum
    end
  elsif ::String === attrs
    # convert non-escaped spaces into null character, so we split on the
    # correct spaces chars, and restore escaped spaces
    capture_1 = '\1'
    attrs = attrs.gsub(SpaceDelimiterRx, %Q(#{capture_1}#{NULL})).gsub(EscapedSpaceRx, capture_1)
    attrs.split(NULL).inject({}) do |accum, entry|
      k, v = entry.split '=', 2
      accum[k] = v || ''
      accum
    end
  elsif (attrs.respond_to? :keys) && (attrs.respond_to? :[])
    # convert it to a Hash as we know it
    original_attrs = attrs
    attrs = {}
    original_attrs.keys.each do |key|
      attrs[key] = original_attrs[key]
    end
    attrs
  else
    raise ::ArgumentError, %Q(illegal type for attributes option: #{attrs.class.ancestors})
  end

  lines = nil
  if ::File === input
    # TODO cli checks if input path can be read and is file, but might want to add check to API
    input_path = ::File.expand_path input.path
    # See https://reproducible-builds.org/specs/source-date-epoch/
    input_mtime = ::ENV['SOURCE_DATE_EPOCH'] ? (::Time.at ::ENV['SOURCE_DATE_EPOCH'].to_i).utc : input.mtime
    lines = input.readlines
    # hold off on setting infile and indir until we get a better sense of their purpose
    attributes['docfile'] = input_path
    attributes['docdir'] = ::File.dirname input_path
    attributes['docname'] = Helpers.basename input_path, true
    docdate = (attributes['docdate'] ||= input_mtime.strftime('%Y-%m-%d'))
    doctime = (attributes['doctime'] ||= input_mtime.strftime('%H:%M:%S %Z'))
    attributes['docdatetime'] = %Q(#{docdate} #{doctime})
  elsif input.respond_to? :readlines
    # NOTE tty, pipes & sockets can't be rewound, but can't be sniffed easily either
    # just fail the rewind operation silently to handle all cases
    begin
      input.rewind
    rescue
    end
    lines = input.readlines
  elsif ::String === input
    lines = input.lines.entries
  elsif ::Array === input
    lines = input.dup
  else
    raise ::ArgumentError, %Q(unsupported input type: #{input.class})
  end

  if timings
    timings.record :read
    timings.start :parse
  end

  if options[:parse] == false
    doc = Document.new lines, options
  else
    doc = (Document.new lines, options).parse
  end

  timings.record :parse if timings
  doc
rescue => ex
  begin
    context = %Q(asciidoctor: FAILED: #{attributes['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
    if ex.respond_to? :exception
      # The original message must be explicitely preserved when wrapping a Ruby exception
      wrapped_ex = ex.exception %Q(#{context} - #{ex.message})
      # JRuby automatically sets backtrace, but not MRI
      wrapped_ex.set_backtrace ex.backtrace
    else
      # Likely a Java exception class
      wrapped_ex = ex.class.new context, ex
      wrapped_ex.stack_trace = ex.stack_trace
    end
  rescue
    wrapped_ex = ex
  end
  raise wrapped_ex
end
load_file(filename, options = {}) click to toggle source

Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document

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

input - the String AsciiDoc source filename options - a String, Array or Hash of options to control processing (default: {})

String and Array values are converted into a Hash.
See Asciidoctor::Document#initialize for details about options.

Returns the Asciidoctor::Document

# File lib/asciidoctor.rb, line 1382
def load_file filename, options = {}
  self.load ::File.new(filename || ''), options
end
render(input, options = {})

Alias render to convert to maintain backwards compatibility

Alias for: convert
render_file(filename, options = {})

Alias ::render_file to ::convert_file to maintain backwards compatibility

Alias for: convert_file