module Kramdown::Options

def self.defaults

Return a Hash with the default values for all options.
def self.defaults
  temp = {}
  @options.each {|n, o| temp[o.name] = o.default}
  temp
end

def self.define(name, type, default, desc, &block)

a value given as string and as the opaque type.
suffices. A block needs to be specified when using type 'Object' and it has to cope with
The type 'Object' should only be used for complex types for which none of the other types

specified, it should validate the value and either raise an error or return a valid value.
Symbol, Boolean, Object), default value +default+ and the description +desc+. If a block is
Define a new option called +name+ (a Symbol) with the given +type+ (String, Integer, Float,
def self.define(name, type, default, desc, &block)
  name = name.to_sym
  raise ArgumentError, "Option name #{name} is already used" if @options.has_key?(name)
  raise ArgumentError, "Invalid option type #{type} specified" if !ALLOWED_TYPES.include?(type)
  raise ArgumentError, "Invalid type for default value" if !(type === default) && !default.nil?
  raise ArgumentError, "Missing validator block" if type == Object && block.nil?
  @options[name] = Definition.new(name, type, default, desc, block)
end

def self.defined?(name)

Return +true+ if an option called +name+ is defined.
def self.defined?(name)
  @options.has_key?(name.to_sym)
end

def self.definitions

Return all option definitions.
def self.definitions
  @options
end

def self.merge(hash)

names are considered and their value is run through the #parse method.
Merge the #defaults Hash with the *parsed* options from the given Hash, i.e. only valid option
def self.merge(hash)
  temp = defaults
  hash.each do |k,v|
    k = k.to_sym
    @options.has_key?(k) ? temp[k] = parse(k, v) : temp[k] = v
  end
  temp
end

def self.parse(name, data)

String and then to the correct type.
If +data+ already has the correct type, it is just returned. Otherwise it is converted to a

value with the correct type.
Parse the given value +data+ as if it was a value for the option +name+ and return the parsed
def self.parse(name, data)
  name = name.to_sym
  raise ArgumentError, "No option named #{name} defined" if !@options.has_key?(name)
  if !(@options[name].type === data)
    data = data.to_s
    data = if @options[name].type == String
             data
           elsif @options[name].type == Integer
             Integer(data) rescue raise Kramdown::Error, "Invalid integer value for option '#{name}': '#{data}'"
           elsif @options[name].type == Float
             Float(data) rescue raise Kramdown::Error, "Invalid float value for option '#{name}': '#{data}'"
           elsif @options[name].type == Symbol
             str_to_sym(data)
           elsif @options[name].type == Boolean
             data.downcase.strip != 'false' && !data.empty?
           end
  end
  data = @options[name].validator[data] if @options[name].validator
  data
end

def self.simple_array_validator(val, name, size)

Additionally, the array is checked for the correct size.

- or an array.
- a comma separated string which is split into an array of values

parameter +val+ can be
Ensures that the option value +val+ for the option called +name+ is a valid array. The
def self.simple_array_validator(val, name, size)
  if String === val
    val = val.split(/,/)
  elsif !(Array === val)
    raise Kramdown::Error, "Invalid type #{val.class} for option #{name}"
  end
  if val.size != size
    raise Kramdown::Error, "Option #{name} needs exactly #{size} values"
  end
  val
end

def self.simple_hash_validator(val, name)

- or a Ruby Hash object.
- a hash in YAML format

parameter +val+ can be
Ensures that the option value +val+ for the option called +name+ is a valid hash. The
def self.simple_hash_validator(val, name)
  if String === val
    begin
      val = YAML.load(val)
    rescue RuntimeError, ArgumentError, SyntaxError
      raise Kramdown::Error, "Invalid YAML value for option #{name}"
    end
  end
  raise Kramdown::Error, "Invalid type #{val.class} for option #{name}" if !(Hash === val)
  val
end

def self.str_to_sym(data)

- An empty value or a value equal to "nil" results in +nil+.
- A leading colon is stripped from the string.

following provisions:
Converts the given String +data+ into a Symbol or +nil+ with the
def self.str_to_sym(data)
  data = data.strip
  data = data[1..-1] if data[0] == ?:
  (data.empty? || data == 'nil' ? nil : data.to_sym)
end