def load input, options = {}
options = options.dup
if (timings = options[:timings])
timings.start :read
end
if !(attrs = options[:attributes])
attrs = {}
elsif ::Hash === attrs || (::RUBY_ENGINE_JRUBY && ::Java::JavaUtil::Map === attrs)
attrs = attrs.dup
elsif ::Array === attrs
attrs, attrs_arr = {}, attrs
attrs_arr.each do |entry|
k, v = entry.split '=', 2
attrs[k] = v || ''
end
elsif ::String === attrs
attrs, attrs_arr = {}, attrs.gsub(SpaceDelimiterRx, %(\\1#{NULL})).gsub(EscapedSpaceRx, '\1').split(NULL)
attrs_arr.each do |entry|
k, v = entry.split '=', 2
attrs[k] = v || ''
end
elsif (attrs.respond_to? :keys) && (attrs.respond_to? :[])
attrs = ::Hash[attrs.keys.map {|k| [k, attrs[k]] }]
else
raise ::ArgumentError, %(illegal type for attributes option: #{attrs.class.ancestors * ' < '})
end
lines = nil
if ::File === input
input_path = ::File.expand_path input.path
input_mtime = ::ENV['SOURCE_DATE_EPOCH'] ? ::Time.at(Integer ::ENV['SOURCE_DATE_EPOCH']).utc : input.mtime
lines = input.readlines
attrs['docfile'] = input_path
attrs['docdir'] = ::File.dirname input_path
attrs['docname'] = Helpers.basename input_path, (attrs['docfilesuffix'] = ::File.extname input_path)
if (docdate = attrs['docdate'])
attrs['docyear'] ||= ((docdate.index '-') == 4 ? (docdate.slice 0, 4) : nil)
else
docdate = attrs['docdate'] = (input_mtime.strftime '%Y-%m-%d')
attrs['docyear'] ||= input_mtime.year.to_s
end
doctime = (attrs['doctime'] ||= input_mtime.strftime('%H:%M:%S %Z'))
attrs['docdatetime'] = %(#{docdate} #{doctime})
elsif input.respond_to? :readlines
begin
input.rewind
rescue
end
lines = input.readlines
elsif ::String === input
lines = ::RUBY_MIN_VERSION_2 ? input.lines : input.each_line.to_a
elsif ::Array === input
lines = input.dup
else
raise ::ArgumentError, %(unsupported input type: #{input.class})
end
if timings
timings.record :read
timings.start :parse
end
options[:attributes] = attrs
doc = options[:parse] == false ? (Document.new lines, options) : (Document.new lines, options).parse
timings.record :parse if timings
doc
rescue => ex
begin
context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
if ex.respond_to? :exception
wrapped_ex = ex.exception %(#{context} - #{ex.message})
wrapped_ex.set_backtrace ex.backtrace
else
wrapped_ex = ex.class.new context, ex
wrapped_ex.stack_trace = ex.stack_trace
end
rescue
wrapped_ex = ex
end
raise wrapped_ex
end