class Asciidoctor::Extensions::Registry

Public: The primary entry point into the extension system.

Registry holds the extensions which have been registered and activated, has methods for registering or defining a processor and looks up extensions stored in the registry during parsing.

Attributes

document[R]

Public: Returns the {Asciidoctor::Document} on which the extensions in this registry are being used.

groups[R]

Public: Returns the Array of {Group} classes, instances and/or Procs that have been registered.

Public Class Methods

new(groups = {}) click to toggle source
# File lib/asciidoctor/extensions.rb, line 517
def initialize groups = {}
  @groups = groups
  @preprocessor_extensions = @treeprocessor_extensions = @postprocessor_extensions = @include_processor_extensions = @docinfo_processor_extensions =nil
  @block_extensions = @block_macro_extensions = @inline_macro_extensions = nil
  @document = nil
end

Public Instance Methods

activate(document) click to toggle source

Public: Activates all the global extension {Group}s and the extension {Group}s associated with this registry.

document - the {Asciidoctor::Document} on which the extensions are to be used.

Returns the instance of this [Registry].

# File lib/asciidoctor/extensions.rb, line 530
def activate document
  @document = document
  (Extensions.groups.values + @groups.values).each do |group|
    case group
    when ::Proc
      case group.arity
      when 0, -1
        instance_exec(&group)
      when 1
        group.call self
      end
    when ::Class
      group.new.activate self
    else
      group.activate self
    end
  end
  self
end
block(*args, &block) click to toggle source

Public: Registers a {BlockProcessor} with the extension registry to process the block content (i.e., delimited block or paragraph) in the AsciiDoc source annotated with the specified block name (i.e., style).

The BlockProcessor may be one of four types:

Unless the BlockProcessor is passed as the method block, it must be the first argument to this method. The second argument is the name (coersed to a Symbol) of the AsciiDoc block content (i.e., delimited block or paragraph) that this processor is registered to handle. If a block name is not passed as an argument, it gets read from the name property of the BlockProcessor instance. If a name still cannot be determined, an error is raised.

Examples

# as a BlockProcessor subclass
block ShoutBlock

# as a BlockProcessor subclass with an explicit block name
block ShoutBlock, :shout

# as an instance of a BlockProcessor subclass
block ShoutBlock.new

# as an instance of a BlockProcessor subclass with an explicit block name
block ShoutBlock.new, :shout

# as a name of a BlockProcessor subclass
block 'ShoutBlock'

# as a name of a BlockProcessor subclass with an explicit block name
block 'ShoutBlock', :shout

# as a method block
block do
  named :shout 
  process |parent, reader, attrs|
    ...
  end
end

# as a method block with an explicit block name
register :shout do
  process |parent, reader, attrs|
    ...
  end
end

Returns an instance of the [Extension] proxy object that is stored in the registry and manages the instance of this BlockProcessor.

# File lib/asciidoctor/extensions.rb, line 887
def block *args, &block
  add_syntax_processor :block, args, &block
end
block_macro(*args, &block) click to toggle source

Public: Registers a {BlockMacroProcessor} with the extension registry to process a block macro with the specified name.

The BlockMacroProcessor may be one of four types:

Unless the BlockMacroProcessor is passed as the method block, it must be the first argument to this method. The second argument is the name (coersed to a Symbol) of the AsciiDoc block macro that this processor is registered to handle. If a block macro name is not passed as an argument, it gets read from the name property of the BlockMacroProcessor instance. If a name still cannot be determined, an error is raised.

Examples

# as a BlockMacroProcessor subclass
block GistBlockMacro

# as a BlockMacroProcessor subclass with an explicit macro name
block GistBlockMacro, :gist

# as an instance of a BlockMacroProcessor subclass
block GistBlockMacro.new

# as an instance of a BlockMacroProcessor subclass with an explicit macro name
block GistBlockMacro.new, :gist

# as a name of a BlockMacroProcessor subclass
block 'GistBlockMacro'

# as a name of a BlockMacroProcessor subclass with an explicit macro name
block 'GistBlockMacro', :gist

# as a method block
block_macro do
  named :gist
  process |parent, target, attrs|
    ...
  end
end

# as a method block with an explicit macro name
register :gist do
  process |parent, target, attrs|
    ...
  end
end

Returns an instance of the [Extension] proxy object that is stored in the registry and manages the instance of this BlockMacroProcessor.

# File lib/asciidoctor/extensions.rb, line 976
def block_macro *args, &block
  add_syntax_processor :block_macro, args, &block
end
block_macros?() click to toggle source

Public: Checks whether any {BlockMacroProcessor} extensions have been registered.

Returns a [Boolean] indicating whether any BlockMacroProcessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 983
def block_macros?
  !!@block_macro_extensions
end
blocks?() click to toggle source

Public: Checks whether any {BlockProcessor} extensions have been registered.

Returns a [Boolean] indicating whether any BlockProcessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 894
def blocks?
  !!@block_extensions
end
docinfo_processor(*args, &block) click to toggle source

Public: Registers an {DocinfoProcessor} with the extension registry to add additionnal docinfo to the document.

The DocinfoProcessor may be one of four types:

Unless the DocinfoProcessor is passed as the method block, it must be the first argument to this method.

Examples

# as an DocinfoProcessor subclass
docinfo_processor MetaRobotsDocinfoProcessor

# as an instance of a DocinfoProcessor subclass with an explicit location
docinfo_processor JQueryDocinfoProcessor.new, :location => :footer

# as a name of a DocinfoProcessor subclass
docinfo_processor 'MetaRobotsDocinfoProcessor'

# as a method block
docinfo_processor do
  process |doc|
    at_location :footer
    'footer content'
  end
end

Returns the [Extension] stored in the registry that proxies the instance of this DocinfoProcessor.

# File lib/asciidoctor/extensions.rb, line 792
def docinfo_processor *args, &block
  add_document_processor :docinfo_processor, args, &block
end
docinfo_processors(location = nil) click to toggle source

Public: Retrieves the {Extension} proxy objects for all the DocinfoProcessor instances stored in this registry.

location - A Symbol for selecting docinfo extensions at a given location (:header or :footer) (default: nil)

Returns an [Array] of Extension proxy objects.

# File lib/asciidoctor/extensions.rb, line 819
def docinfo_processors location = nil
  if @docinfo_processor_extensions
    if location
      @docinfo_processor_extensions.select {|ext| ext.config[:location] == location }
    else
      @docinfo_processor_extensions
    end
  else
    nil
  end
end
docinfo_processors?(location = nil) click to toggle source

Public: Checks whether any {DocinfoProcessor} extensions have been registered.

location - A Symbol for selecting docinfo extensions at a given location (:header or :footer) (default: nil)

Returns a [Boolean] indicating whether any DocinfoProcessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 801
def docinfo_processors? location = nil
  if @docinfo_processor_extensions
    if location
      @docinfo_processor_extensions.find {|ext| ext.config[:location] == location }
    else
      true
    end
  else
    false
  end
end
find_block_extension(name) click to toggle source

Public: Retrieves the {Extension} proxy object for the BlockProcessor registered to handle block content with the name.

name - the String or Symbol (coersed to a Symbol) macro name

Returns the [Extension] object stored in the registry that proxies the corresponding BlockProcessor or nil if a match is not found.

# File lib/asciidoctor/extensions.rb, line 918
def find_block_extension name
  @block_extensions[name.to_sym]
end
find_block_macro_extension(name) click to toggle source

Public: Retrieves the {Extension} proxy object for the BlockMacroProcessor registered to handle a block macro with the specified name.

name - the String or Symbol (coersed to a Symbol) macro name

Returns the [Extension] object stored in the registry that proxies the cooresponding BlockMacroProcessor or nil if a match is not found.

# File lib/asciidoctor/extensions.rb, line 1007
def find_block_macro_extension name
  @block_macro_extensions[name.to_sym]
end
find_inline_macro_extension(name) click to toggle source

Public: Retrieves the {Extension} proxy object for the InlineMacroProcessor registered to handle an inline macro with the specified name.

name - the String or Symbol (coersed to a Symbol) macro name

Returns the [Extension] object stored in the registry that proxies the cooresponding InlineMacroProcessor or nil if a match is not found.

# File lib/asciidoctor/extensions.rb, line 1094
def find_inline_macro_extension name
  @inline_macro_extensions[name.to_sym]
end
include_processor(*args, &block) click to toggle source

Public: Registers an {IncludeProcessor} with the extension registry to have a shot at handling the include directive.

The IncludeProcessor may be one of four types:

Unless the IncludeProcessor is passed as the method block, it must be the first argument to this method.

Examples

# as an IncludeProcessor subclass
include_processor GitIncludeProcessor

# as an instance of a Postprocessor subclass
include_processor GitIncludeProcessor.new

# as a name of a Postprocessor subclass
include_processor 'GitIncludeProcessor'

# as a method block
include_processor do
  process |document, output|
    ...
  end
end

Returns the [Extension] stored in the registry that proxies the instance of this IncludeProcessor.

# File lib/asciidoctor/extensions.rb, line 739
def include_processor *args, &block
  add_document_processor :include_processor, args, &block
end
include_processors() click to toggle source

Public: Retrieves the {Extension} proxy objects for all the IncludeProcessor instances stored in this registry.

Returns an [Array] of Extension proxy objects.

# File lib/asciidoctor/extensions.rb, line 754
def include_processors
  @include_processor_extensions
end
include_processors?() click to toggle source

Public: Checks whether any {IncludeProcessor} extensions have been registered.

Returns a [Boolean] indicating whether any IncludeProcessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 746
def include_processors?
  !!@include_processor_extensions
end
inline_macro(*args, &block) click to toggle source

Public: Registers a {InlineMacroProcessor} with the extension registry to process an inline macro with the specified name.

The InlineMacroProcessor may be one of four types:

Unless the InlineMacroProcessor is passed as the method block, it must be the first argument to this method. The second argument is the name (coersed to a Symbol) of the AsciiDoc block macro that this processor is registered to handle. If a block macro name is not passed as an argument, it gets read from the name property of the InlineMacroProcessor instance. If a name still cannot be determined, an error is raised.

Examples

# as an InlineMacroProcessor subclass
block ChromeInlineMacro

# as an InlineMacroProcessor subclass with an explicit macro name
block ChromeInineMacro, :chrome

# as an instance of an InlineMacroProcessor subclass
block ChromeInlineMacro.new

# as an instance of an InlineMacroProcessor subclass with an explicit macro name
block ChromeInlineMacro.new, :chrome

# as a name of an InlineMacroProcessor subclass
block 'ChromeInlineMacro'

# as a name of an InlineMacroProcessor subclass with an explicit macro name
block 'ChromeInineMacro', :chrome

# as a method block
inline_macro do
  named :chrome
  process |parent, target, attrs|
    ...
  end
end

# as a method block with an explicit macro name
register :chrome do
  process |parent, target, attrs|
    ...
  end
end

Returns an instance of the [Extension] proxy object that is stored in the registry and manages the instance of this InlineMacroProcessor.

# File lib/asciidoctor/extensions.rb, line 1065
def inline_macro *args, &block
  add_syntax_processor :inline_macro, args, &block
end
inline_macros() click to toggle source

Public: Retrieves the {Extension} proxy objects for all InlineMacroProcessor instances in this registry.

Returns an [Array] of Extension proxy objects.

# File lib/asciidoctor/extensions.rb, line 1102
def inline_macros
  @inline_macro_extensions.values
end
inline_macros?() click to toggle source

Public: Checks whether any {InlineMacroProcessor} extensions have been registered.

Returns a [Boolean] indicating whether any IncludeMacroProcessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 1072
def inline_macros?
  !!@inline_macro_extensions
end
postprocessor(*args, &block) click to toggle source

Public: Registers a {Postprocessor} with the extension registry to process the output after conversion is complete.

The Postprocessor may be one of four types:

Unless the Postprocessor is passed as the method block, it must be the first argument to this method.

Examples

# as a Postprocessor subclass
postprocessor AnalyticsPostprocessor

# as an instance of a Postprocessor subclass
postprocessor AnalyticsPostprocessor.new

# as a name of a Postprocessor subclass
postprocessor 'AnalyticsPostprocessor'

# as a method block
postprocessor do
  process |document, output|
    ...
  end
end

Returns the [Extension] stored in the registry that proxies the instance of this Postprocessor.

# File lib/asciidoctor/extensions.rb, line 687
def postprocessor *args, &block
  add_document_processor :postprocessor, args, &block
end
postprocessors() click to toggle source

Public: Retrieves the {Extension} proxy objects for all Postprocessor instances in this registry.

Returns an [Array] of Extension proxy objects.

# File lib/asciidoctor/extensions.rb, line 702
def postprocessors
  @postprocessor_extensions
end
postprocessors?() click to toggle source

Public: Checks whether any {Postprocessor} extensions have been registered.

Returns a [Boolean] indicating whether any Postprocessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 694
def postprocessors?
  !!@postprocessor_extensions
end
preprocessor(*args, &block) click to toggle source

Public: Registers a {Preprocessor} with the extension registry to process the AsciiDoc source before parsing begins.

The Preprocessor may be one of four types:

Unless the Preprocessor is passed as the method block, it must be the first argument to this method.

Examples

# as a Preprocessor subclass
preprocessor FrontMatterPreprocessor

# as an instance of a Preprocessor subclass
preprocessor FrontMatterPreprocessor.new

# as a name of a Preprocessor subclass
preprocessor 'FrontMatterPreprocessor'

# as a method block
preprocessor do
  process |reader, lines|
    ...
  end
end

Returns the [Extension] stored in the registry that proxies the instance of this Preprocessor.

# File lib/asciidoctor/extensions.rb, line 583
def preprocessor *args, &block
  add_document_processor :preprocessor, args, &block
end
preprocessors() click to toggle source

Public: Retrieves the {Extension} proxy objects for all Preprocessor instances in this registry.

Returns an [Array] of Extension proxy objects.

# File lib/asciidoctor/extensions.rb, line 598
def preprocessors
  @preprocessor_extensions
end
preprocessors?() click to toggle source

Public: Checks whether any {Preprocessor} extensions have been registered.

Returns a [Boolean] indicating whether any Preprocessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 590
def preprocessors?
  !!@preprocessor_extensions
end
registered_for_block?(name, context) click to toggle source

Public: Checks whether any {BlockProcessor} extensions are registered to handle the specified block name appearing on the specified context.

Returns the [Extension] proxy object for the BlockProcessor that matches the block name and context or false if no match is found.

# File lib/asciidoctor/extensions.rb, line 903
def registered_for_block? name, context
  if (ext = @block_extensions[name.to_sym])
    (ext.config[:contexts].include? context) ? ext : false
  else
    false
  end
end
registered_for_block_macro?(name) click to toggle source

Public: Checks whether any {BlockMacroProcessor} extensions are registered to handle the block macro with the specified name.

name - the String or Symbol (coersed to a Symbol) macro name

Returns the [Extension] proxy object for the BlockMacroProcessor that matches the macro name or false if no match is found.

# File lib/asciidoctor/extensions.rb, line 996
def registered_for_block_macro? name
  (ext = @block_macro_extensions[name.to_sym]) ? ext : false
end
registered_for_inline_macro?(name) click to toggle source

Public: Checks whether any {InlineMacroProcessor} extensions are registered to handle the inline macro with the specified name.

name - the String or Symbol (coersed to a Symbol) macro name

Returns the [Extension] proxy object for the InlineMacroProcessor that matches the macro name or false if no match is found.

# File lib/asciidoctor/extensions.rb, line 1083
def registered_for_inline_macro? name
  (ext = @inline_macro_extensions[name.to_sym]) ? ext : false
end
treeprocessor(*args, &block) click to toggle source

Public: Registers a {Treeprocessor} with the extension registry to process the AsciiDoc source after parsing is complete.

The Treeprocessor may be one of four types:

Unless the Treeprocessor is passed as the method block, it must be the first argument to this method.

Examples

# as a Treeprocessor subclass
treeprocessor ShellTreeprocessor

# as an instance of a Treeprocessor subclass
treeprocessor ShellTreeprocessor.new

# as a name of a Treeprocessor subclass
treeprocessor 'ShellTreeprocessor'

# as a method block
treeprocessor do
  process |document|
    ...
  end
end

Returns the [Extension] stored in the registry that proxies the instance of this Treeprocessor.

# File lib/asciidoctor/extensions.rb, line 635
def treeprocessor *args, &block
  add_document_processor :treeprocessor, args, &block
end
treeprocessors() click to toggle source

Public: Retrieves the {Extension} proxy objects for all Treeprocessor instances in this registry.

Returns an [Array] of Extension proxy objects.

# File lib/asciidoctor/extensions.rb, line 650
def treeprocessors
  @treeprocessor_extensions
end
treeprocessors?() click to toggle source

Public: Checks whether any {Treeprocessor} extensions have been registered.

Returns a [Boolean] indicating whether any Treeprocessor extensions are registered.

# File lib/asciidoctor/extensions.rb, line 642
def treeprocessors?
  !!@treeprocessor_extensions
end

Private Instance Methods

add_document_processor(kind, args, &block) click to toggle source
# File lib/asciidoctor/extensions.rb, line 1108
def add_document_processor kind, args, &block
  kind_name = kind.to_s.tr '_', ' '
  kind_class_symbol = kind_name.split(' ').map {|word| %Q(#{word.chr.upcase}#{word[1..-1]}) }.join.to_sym
  kind_class = Extensions.const_get kind_class_symbol
  kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol) : nil
  kind_store = instance_variable_get(%Q(@#{kind}_extensions).to_sym) || instance_variable_set(%Q(@#{kind}_extensions).to_sym, [])
  # style 1: specified as block
  extension = if block_given?
    config = resolve_args args, 1
    # TODO if block arity is 0, assume block is process method
    processor = kind_class.new config
    # NOTE class << processor idiom doesn't work in Opal
    #class << processor
    #  include_dsl
    #end
    # NOTE kind_class.contants(false) doesn't exist in Ruby 1.8.7
    processor.extend kind_class.const_get :DSL if kind_class.constants.grep :DSL
    processor.instance_exec(&block)
    processor.freeze
    unless processor.process_block_given?
      raise ::ArgumentError.new %Q(No block specified to process #{kind_name} extension at #{block.source_location})
    end
    ProcessorExtension.new kind, processor
  else
    processor, config = resolve_args args, 2
    # style 2: specified as class or class name
    if (processor.is_a? ::Class) || ((processor.is_a? ::String) && (processor = Extensions.class_for_name processor))
      unless processor < kind_class || (kind_java_class && processor < kind_java_class)
        raise ::ArgumentError.new %Q(Invalid type for #{kind_name} extension: #{processor})
      end
      processor_instance = processor.new config
      processor_instance.freeze
      ProcessorExtension.new kind, processor_instance
    # style 3: specified as instance
    elsif (processor.is_a? kind_class) || (kind_java_class && (processor.is_a? kind_java_class))
      processor.update_config config
      processor.freeze
      ProcessorExtension.new kind, processor
    else
      raise ::ArgumentError.new %Q(Invalid arguments specified for registering #{kind_name} extension: #{args})
    end
  end

  if extension.config[:position] == :>>
    kind_store.unshift extension
  else
    kind_store << extension
  end
end
add_syntax_processor(kind, args) { |processor| ... } click to toggle source
# File lib/asciidoctor/extensions.rb, line 1158
def add_syntax_processor kind, args, &block
  kind_name = kind.to_s.tr '_', ' '
  kind_class_basename = kind_name.split(' ').map {|word| %Q(#{word.chr.upcase}#{word[1..-1]}) }.join
  kind_class_symbol = %Q(#{kind_class_basename}Processor).to_sym
  kind_class = Extensions.const_get kind_class_symbol
  kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol) : nil
  kind_store = instance_variable_get(%Q(@#{kind}_extensions).to_sym) || instance_variable_set(%Q(@#{kind}_extensions).to_sym, {})
  # style 1: specified as block
  if block_given?
    name, config = resolve_args args, 2
    processor = kind_class.new as_symbol(name), config
    # NOTE class << processor idiom doesn't work in Opal
    #class << processor
    #  include_dsl
    #end
    # NOTE kind_class.contants(false) doesn't exist in Ruby 1.8.7
    processor.extend kind_class.const_get :DSL if kind_class.constants.grep :DSL
    if block.arity == 1
      yield processor
    else
      processor.instance_exec(&block)
    end
    unless (name = as_symbol processor.name)
      raise ::ArgumentError.new %Q(No name specified for #{kind_name} extension at #{block.source_location})
    end
    unless processor.process_block_given?
      raise ::NoMethodError.new %Q(No block specified to process #{kind_name} extension at #{block.source_location})
    end
    processor.freeze
    kind_store[name] = ProcessorExtension.new kind, processor
  else
    processor, name, config = resolve_args args, 3
    # style 2: specified as class or class name
    if (processor.is_a? ::Class) || ((processor.is_a? ::String) && (processor = Extensions.class_for_name processor))
      unless processor < kind_class || (kind_java_class && processor < kind_java_class)
        raise ::ArgumentError.new %Q(Class specified for #{kind_name} extension does not inherit from #{kind_class}: #{processor})
      end
      processor_instance = processor.new as_symbol(name), config
      unless (name = as_symbol processor_instance.name)
        raise ::ArgumentError.new %Q(No name specified for #{kind_name} extension: #{processor})
      end
      processor.freeze
      kind_store[name] = ProcessorExtension.new kind, processor_instance
    # style 3: specified as instance
    elsif (processor.is_a? kind_class) || (kind_java_class && (processor.is_a? kind_java_class))
      processor.update_config config
      # TODO need a test for this override!
      unless (name = name ? (processor.name = as_symbol name) : (as_symbol processor.name))
        raise ::ArgumentError.new %Q(No name specified for #{kind_name} extension: #{processor})
      end
      processor.freeze
      kind_store[name] = ProcessorExtension.new kind, processor
    else
      raise ::ArgumentError.new %Q(Invalid arguments specified for registering #{kind_name} extension: #{args})
    end
  end
end
as_symbol(name) click to toggle source
# File lib/asciidoctor/extensions.rb, line 1229
def as_symbol name
  name ? ((name.is_a? ::Symbol) ? name : name.to_sym) : nil
end
resolve_args(args, expect) click to toggle source
# File lib/asciidoctor/extensions.rb, line 1216
def resolve_args args, expect
  opts = (args[-1].is_a? ::Hash) ? args.pop : {}
  return opts if expect == 1
  num_args = args.size
  if (missing = expect - 1 - num_args) > 0
    args.fill nil, num_args, missing
  elsif missing < 0
    args.pop(-missing)
  end
  args << opts
  args
end