module Asciidoctor::Helpers

def basename filename, drop_ext = nil

Returns the String filename with leading directories removed and, if specified, the extension removed

# => "tiger"
Helpers.basename 'images/tiger.png', '.png'

# => "tiger"
Helpers.basename 'images/tiger.png', true

Examples

or an explicit String extension to drop (default: nil).
drop_ext - A Boolean flag indicating whether to drop the extension
filename - The String file name to process.

Public: Retrieves the basename of the filename, optionally removing the extension, if present
def basename filename, drop_ext = nil
  if drop_ext
    ::File.basename filename, (drop_ext == true ? (extname filename) : drop_ext)
  else
    ::File.basename filename
  end
end

def class_for_name qualified_name

Returns Class

Internal: Resolves a Class object (not a Module) for the qualified name.
def class_for_name qualified_name
  raise unless ::Class === (resolved = ::Object.const_get qualified_name, false)
  resolved
rescue
  raise ::NameError, %(Could not resolve class for name: #{qualified_name})
end

def encode_spaces_in_uri str

Returns the specified String with all spaces replaced with %20.

str - the String to encode

Internal: Apply URI path encoding to spaces in the specified string (i.e., convert spaces to %20).
def encode_spaces_in_uri str
  (str.include? ' ') ? (str.gsub ' ', '%20') : str
end

def encode_uri_component str

def encode_uri_component str
  # patch necessary to adhere with RFC-3986 (and thus CGI.escape)
  # see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Description
  %x(
    return encodeURIComponent(str).replace(/%20|[!'()*]/g, function (m) {
      return m === '%20' ? '+' : '%' + m.charCodeAt(0).toString(16)
    })
  )
end

def encode_uri_component str

def encode_uri_component str
  CGI.escape str
end

def extname path, fallback = ''

def extname path, fallback = ''
  if (last_dot_idx = path.rindex '.')
    (path.index '/', last_dot_idx) || (path.index ::File::ALT_SEPARATOR, last_dot_idx) ? fallback : (path.slice last_dot_idx, path.length)
  else
    fallback
  end
end

def extname path, fallback = ''

def extname path, fallback = ''
  if (last_dot_idx = path.rindex '.')
    (path.index '/', last_dot_idx) ? fallback : (path.slice last_dot_idx, path.length)
  else
    fallback
  end
end

def extname? path

Returns true if the path has a file extension, false otherwise

path - The path String to check; expects a posix path

Public: Returns whether this path has a file extension.
def extname? path
  (last_dot_idx = path.rindex '.') && !(path.index '/', last_dot_idx)
end

def int_to_roman val

Returns the [String] roman numeral for this integer

val - the [Integer] value to convert

Internal: Converts an integer to a Roman numeral.
def int_to_roman val
  ROMAN_NUMERALS.map do |l, i|
    repeat, val = val.divmod i
    l * repeat
  end.join
end

def mkdir_p dir

Internal: Make a directory, ensuring all parent directories exist.
def mkdir_p dir
  unless ::File.directory? dir
    unless (parent_dir = ::File.dirname dir) == '.'
      mkdir_p parent_dir
    end
    begin
      ::Dir.mkdir dir
    rescue ::SystemCallError
      raise unless ::File.directory? dir
    end
  end
end

def nextval current

returns the next value in the sequence according to the current value's type

current - the value to increment as a String or Integer

Handles both integer and character sequences.

Internal: Get the next value in the sequence.
def nextval current
  if ::Integer === current
    current + 1
  else
    intval = current.to_i
    if intval.to_s != current.to_s
      (current[0].ord + 1).chr
    else
      intval + 1
    end
  end
end

def prepare_source_array data, trim_end = true

returns a String Array of prepared lines

(true cleans all whitespace; false only removes trailing newline) (default: true)
trim_end - whether to trim whitespace from the end of each line;
data - the source data Array to prepare (no nil entries allowed)

encode it to UTF-8 from the specified source encoding.
If a BOM is found at the beginning of the data, a best attempt is made to

whitespace from every line.
Encodes the data to UTF-8, if necessary, and removes any trailing

Internal: Prepare the source data Array for parsing.
def prepare_source_array data, trim_end = true
  return [] if data.empty?
  if (leading_2_bytes = (leading_bytes = (first = data[0]).unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
    data[0] = first.byteslice 2, first.bytesize
    # NOTE you can't split a UTF-16LE string using .lines when encoding is UTF-8; doing so will cause this line to fail
    return trim_end ? data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16LE).rstrip } : data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16LE).chomp }
  elsif leading_2_bytes == BOM_BYTES_UTF_16BE
    data[0] = first.byteslice 2, first.bytesize
    return trim_end ? data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16BE).rstrip } : data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16BE).chomp }
  elsif leading_bytes == BOM_BYTES_UTF_8
    data[0] = first.byteslice 3, first.bytesize
  end
  if first.encoding == UTF_8
    trim_end ? data.map {|line| line.rstrip } : data.map {|line| line.chomp }
  else
    trim_end ? data.map {|line| (line.encode UTF_8).rstrip } : data.map {|line| (line.encode UTF_8).chomp }
  end
end

def prepare_source_string data, trim_end = true

returns a String Array of prepared lines

(true cleans all whitespace; false only removes trailing newline) (default: true)
trim_end - whether to trim whitespace from the end of each line;
data - the source data String to prepare

encode it to UTF-8 from the specified source encoding.
If a BOM is found at the beginning of the data, a best attempt is made to

removes any trailing whitespace from every line.
Encodes the data to UTF-8, if necessary, splits it into an array, and

Internal: Prepare the source data String for parsing.
def prepare_source_string data, trim_end = true
  return [] if data.nil_or_empty?
  if (leading_2_bytes = (leading_bytes = data.unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
    data = (data.byteslice 2, data.bytesize).encode UTF_8, ::Encoding::UTF_16LE
  elsif leading_2_bytes == BOM_BYTES_UTF_16BE
    data = (data.byteslice 2, data.bytesize).encode UTF_8, ::Encoding::UTF_16BE
  elsif leading_bytes == BOM_BYTES_UTF_8
    data = data.byteslice 3, data.bytesize
    data = data.encode UTF_8 unless data.encoding == UTF_8
  elsif data.encoding != UTF_8
    data = data.encode UTF_8
  end
  if trim_end
    [].tap {|lines| data.each_line {|line| lines << line.rstrip } }
  else
    [].tap {|lines| data.each_line {|line| lines << line.chomp } }
  end
end

def require_library name, gem_name = true, on_failure = :abort

Otherwise, nil is returned.
Otherwise, if on_failure is :warn, Kernel#warn is called with an appropriate message and nil returned.
Otherwise, if on_failure is :abort, Kernel#raise is called with an appropriate message.
Returns The [Boolean] return value of Kernel#require if the library can be loaded.

on_failure - a Symbol that indicates how to handle a load failure (:abort, :warn, :ignore) (default: :abort)
(default: true)
or the String name of the RubyGem if it differs from the library name
gem_name - a Boolean that indicates whether this library is provided by a RubyGem,
name - the String name of the library to require.

specified, the message communicates that a required gem is not available.
aborted or functionality is disabled, respectively. If a gem_name is
on_failure is :warn to communicate to the user that processing is being
passes a message to Kernel#raise if on_failure is :abort or Kernel#warn if
Kernel#require. Rescues the LoadError if the library is not available and
Attempts to load the library specified in the first argument using the

Public: Require the specified library using Kernel#require.
def require_library name, gem_name = true, on_failure = :abort
  require name
rescue ::LoadError
  include Logging unless include? Logging
  if gem_name
    gem_name = name if gem_name == true
    case on_failure
    when :abort
      details = $!.path == gem_name ? '' : %[ (reason: #{$!.path ? %(cannot load '#{$!.path}') : $!.message})]
      raise ::LoadError, %(asciidoctor: FAILED: required gem '#{gem_name}' is not available#{details}. Processing aborted.)
    when :warn
      details = $!.path == gem_name ? '' : %[ (reason: #{$!.path ? %(cannot load '#{$!.path}') : $!.message})]
      logger.warn %(optional gem '#{gem_name}' is not available#{details}. Functionality disabled.)
    end
  else
    case on_failure
    when :abort
      raise ::LoadError, %(asciidoctor: FAILED: #{$!.message.chomp '.'}. Processing aborted.)
    when :warn
      logger.warn %(#{$!.message.chomp '.'}. Functionality disabled.)
    end
  end
  nil
end

def resolve_class object

a String that resolves to a Class; otherwise, nil
Returns a Class if the specified object is a Class (but not a Module) or

object - The Object to resolve as a Class

Internal: Resolve the specified object as a Class
def resolve_class object
  ::Class === object ? object : (::String === object ? (class_for_name object) : nil)
end

def rootname filename

Returns the String filename with the file extension removed

# => "part1/chapter1"
Helpers.rootname 'part1/chapter1.adoc'

Examples

filename - The String file name to process; expected to be a posix path

Public: Removes the file extension from filename and returns the result
def rootname filename
  if (last_dot_idx = filename.rindex '.')
    (filename.index '/', last_dot_idx) ? filename : (filename.slice 0, last_dot_idx)
  else
    filename
  end
end

def uriish? str

returns true if the String is a URI, false if it is not

str - the String to check

with a URI prefix (e.g., http://). No validation of the URI is performed.
Uses the Asciidoctor::UriSniffRx regex to check whether the String begins

Internal: Efficiently checks whether the specified String resembles a URI
def uriish? str
  (str.include? ':') && (UriSniffRx.match? str)
end