class Asciidoctor::Converter::Factory

A factory for instantiating converters that are used to convert a {Document} (i.e., a parsed AsciiDoc tree structure) or {AbstractNode} to a backend format such as HTML or DocBook. {Factory Converter::Factory} is the primary entry point for creating, registering and accessing converters.

{Converter} objects are instantiated by passing a String backend name and, optionally, an options Hash to the {Factory#create} method. The backend can be thought of as an intent to convert a document to a specified format. For example:

converter = Asciidoctor::Converter::Factory.create 'html5', :htmlsyntax => 'xml'

Converter objects are thread safe. They only survive the lifetime of a single conversion.

A singleton instance of {Factory Converter::Factory} can be accessed using the {Factory.default} method. This instance maintains the global registry of statically registered converters. The registery includes built-in converters for {Html5Converter HTML 5}, {DocBook5Converter DocBook 5} and {DocBook45Converter DocBook 4.5}, as well as any custom converters that have been discovered or explicitly registered.

If the {rubygems.org/gems/thread_safe thread_safe} gem is installed, access to the default factory is guaranteed to be thread safe. Otherwise, a warning is issued to the user.

Attributes

converters[R]

Public: Get the Hash of Converter classes keyed by backend name

Public Class Methods

converters() click to toggle source

Public: Retrieve the global Hash of custom Converter classes keyed by backend.

Returns the the global [Hash] of custom Converter classes

# File lib/asciidoctor/converter/factory.rb, line 103
def converters
  default.converters
end
create(backend, opts = {}) click to toggle source

Public: Lookup the converter for the specified backend in the global factory and instantiate it, forwarding the Hash of options to the constructor of the converter class.

If the custom converter is not found, an attempt will be made to find and instantiate a built-in converter.

backend - The String backend name opts - A Hash of options to pass to the converter

Returns an instance of [Converter] for converting the specified backend or nil if no match is found.

# File lib/asciidoctor/converter/factory.rb, line 96
def create backend, opts = {}
  default.create backend, opts
end
default(initialize_singleton = true) click to toggle source

Public: Retrieves a singleton instance of {Factory Converter::Factory}.

If the thread_safe gem is installed, the registry of converters is initialized as a ThreadSafe::Cache. Otherwise, a warning is issued and the registry of converters is initialized using a normal Hash.

initialize_singleton - A Boolean to indicate whether the singleton should

be initialize if it has not already been created.
If false, and a singleton has not been previously
initialized, a fresh instance is returned.

Returns the default [Factory] singleton instance

# File lib/asciidoctor/converter/factory.rb, line 44
def default initialize_singleton = true
  return @__default__ || new unless initialize_singleton
  # FIXME this assignment is not thread_safe, may need to use a ::Threadsafe helper here
  @__default__ ||= begin
    require 'thread_safe'.to_s unless defined? ::ThreadSafe
    new ::ThreadSafe::Cache.new
  rescue ::LoadError
    warn 'asciidoctor: WARNING: gem \thread_safe\ is not installed. This gem is recommended when registering custom converters.'
    new
  end
end
new(converters = nil) click to toggle source
# File lib/asciidoctor/converter/factory.rb, line 118
def initialize converters = nil
  @converters = converters || {}
  @star_converter = nil
end
register(converter, backends = ['*']) click to toggle source

Public: Register a custom converter in the global converter factory to handle conversion to the specified backends. If the backend value is an asterisk, the converter is used to handle any backend that does not have an explicit converter.

converter - The Converter class to register backends - A String Array of backend names that this converter should

be registered to handle (optional, default: ['*'])

Returns nothing

# File lib/asciidoctor/converter/factory.rb, line 66
def register converter, backends = ['*']
  default.register converter, backends
end
resolve(backend) click to toggle source

Public: Lookup the custom converter for the specified backend in the global factory.

This method does not resolve the built-in converters.

backend - The String backend name

Returns the [Converter] class registered to convert the specified backend or nil if no match is found

# File lib/asciidoctor/converter/factory.rb, line 79
def resolve backend
  default.resolve backend
end
unregister_all() click to toggle source

Public: Unregister all Converter classes in the global factory.

Returns nothing

# File lib/asciidoctor/converter/factory.rb, line 110
def unregister_all
  default.unregister_all
end

Public Instance Methods

create(backend, opts = {}) click to toggle source

Public: Create a new Converter object that can be used to convert the {AbstractNode} (typically a {Document}) to the specified String backend. This method accepts an optional Hash of options that are passed to the converter's constructor.

If a custom Converter is found to convert the specified backend, it is instantiated (if necessary) and returned immediately. If a custom Converter is not found, an attempt is made to resolve a built-in converter. If the `:template_dirs` key is found in the Hash passed as the second argument, a {CompositeConverter} is created that delegates to a {TemplateConverter} and, if resolved, the built-in converter. If the `:template_dirs` key is not found, the built-in converter is returned or nil if no converter is resolved.

backend - the String backend name opts - an optional Hash of options that get passed on to the converter's

constructor. If the :template_dirs key is found in the options
Hash, this method returns a {CompositeConverter} that delegates
to a {TemplateConverter}. (optional, default: {})

Returns the [Converter] object

# File lib/asciidoctor/converter/factory.rb, line 184
def create backend, opts = {}
  if (converter = resolve backend)
    return ::Class === converter ? (converter.new backend, opts) : converter
  end

  base_converter = case backend
  when 'html5'
    unless defined? ::Asciidoctor::Converter::Html5Converter
      require 'asciidoctor/converter/html5'.to_s
    end
    Html5Converter.new backend, opts
  when 'docbook5'
    unless defined? ::Asciidoctor::Converter::DocBook5Converter
      require 'asciidoctor/converter/docbook5'.to_s
    end
    DocBook5Converter.new backend, opts
  when 'docbook45'
    unless defined? ::Asciidoctor::Converter::DocBook45Converter
      require 'asciidoctor/converter/docbook45'.to_s
    end
    DocBook45Converter.new backend, opts
  when 'manpage'
    unless defined? ::Asciidoctor::Converter::ManPageConverter
      require 'asciidoctor/converter/manpage'.to_s
    end
    ManPageConverter.new backend, opts
  end

  return base_converter unless opts.key? :template_dirs

  unless defined? ::Asciidoctor::Converter::TemplateConverter
    require 'asciidoctor/converter/template'.to_s
  end
  unless defined? ::Asciidoctor::Converter::CompositeConverter
    require 'asciidoctor/converter/composite'.to_s
  end
  template_converter = TemplateConverter.new backend, opts[:template_dirs], opts
  # QUESTION should we omit the composite converter if built_in_converter is nil?
  CompositeConverter.new backend, template_converter, base_converter
end
register(converter, backends = ['*']) click to toggle source

Public: Register a custom converter with this factory to handle conversion to the specified backends. If the backend value is an asterisk, the converter is used to handle any backend that does not have an explicit converter.

converter - The Converter class to register backends - A String Array of backend names that this converter should

be registered to handle (optional, default: ['*'])

Returns nothing

# File lib/asciidoctor/converter/factory.rb, line 133
def register converter, backends = ['*']
  backends.each do |backend|
    @converters[backend] = converter
    if backend == '*'
      @star_converter = converter
    end
  end
  nil
end
resolve(backend) click to toggle source

Public: Lookup the custom converter registered with this factory to handle the specified backend.

backend - The String backend name

Returns the [Converter] class registered to convert the specified backend or nil if no match is found

# File lib/asciidoctor/converter/factory.rb, line 150
def resolve backend
  @converters && (@converters[backend] || @star_converter)
end
unregister_all() click to toggle source

Public: Unregister all Converter classes that are registered with this factory.

Returns nothing

# File lib/asciidoctor/converter/factory.rb, line 158
def unregister_all
  @converters.clear
  @star_converter = nil
end