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
Public: Returns the {Asciidoctor::Document} on which the extensions in this registry are being used.
Public: Returns the Array of {Group} classes, instances and/or Procs that have been registered.
Public Class Methods
# File lib/asciidoctor/extensions.rb, line 485 def initialize groups = {} @groups = groups @preprocessor_extensions = @treeprocessor_extensions = @postprocessor_extensions = @include_processor_extensions = nil @block_extensions = @block_macro_extensions = @inline_macro_extensions = nil @document = nil end
Public Instance Methods
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 498 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
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:
-
A BlockProcessor subclass
-
An instance of a BlockProcessor subclass
-
The String name of a BlockProcessor subclass
-
A method block (i.e., Proc) that conforms to the BlockProcessor contract
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 782 def block *args, &block add_syntax_processor :block, args, &block end
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:
-
A BlockMacroProcessor subclass
-
An instance of a BlockMacroProcessor subclass
-
The String name of a BlockMacroProcessor subclass
-
A method block (i.e., Proc) that conforms to the BlockMacroProcessor contract
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 871 def block_macro *args, &block add_syntax_processor :block_macro, args, &block end
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 878 def block_macros? !!@block_macro_extensions end
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 789 def blocks? !!@block_extensions end
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 813 def find_block_extension name @block_extensions[name.to_sym] end
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 902 def find_block_macro_extension name @block_macro_extensions[name.to_sym] end
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 989 def find_inline_macro_extension name @inline_macro_extensions[name.to_sym] end
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:
-
A IncludeProcessor subclass
-
An instance of a IncludeProcessor subclass
-
The String name of a IncludeProcessor subclass
-
A method block (i.e., Proc) that conforms to the IncludeProcessor contract
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 707 def include_processor *args, &block add_document_processor :include_processor, args, &block end
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 722 def include_processors @include_processor_extensions end
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 714 def include_processors? !!@include_processor_extensions end
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:
-
An InlineMacroProcessor subclass
-
An instance of an InlineMacroProcessor subclass
-
The String name of an InlineMacroProcessor subclass
-
A method block (i.e., Proc) that conforms to the InlineMacroProcessor contract
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 960 def inline_macro *args, &block add_syntax_processor :inline_macro, args, &block end
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 997 def inline_macros @inline_macro_extensions.values end
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 967 def inline_macros? !!@inline_macro_extensions end
Public: Registers a {Postprocessor} with the extension registry to process the output after conversion is complete.
The Postprocessor may be one of four types:
-
A Postprocessor subclass
-
An instance of a Postprocessor subclass
-
The String name of a Postprocessor subclass
-
A method block (i.e., Proc) that conforms to the Postprocessor contract
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 655 def postprocessor *args, &block add_document_processor :postprocessor, args, &block end
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 670 def postprocessors @postprocessor_extensions end
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 662 def postprocessors? !!@postprocessor_extensions end
Public: Registers a {Preprocessor} with the extension registry to process the AsciiDoc source before parsing begins.
The Preprocessor may be one of four types:
-
A Preprocessor subclass
-
An instance of a Preprocessor subclass
-
The String name of a Preprocessor subclass
-
A method block (i.e., Proc) that conforms to the Preprocessor contract
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 551 def preprocessor *args, &block add_document_processor :preprocessor, args, &block end
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 566 def preprocessors @preprocessor_extensions end
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 558 def preprocessors? !!@preprocessor_extensions end
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 798 def registered_for_block? name, context if (ext = @block_extensions[name.to_sym]) (ext.config[:contexts].include? context) ? ext : false else false end end
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 891 def registered_for_block_macro? name (ext = @block_macro_extensions[name.to_sym]) ? ext : false end
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 978 def registered_for_inline_macro? name (ext = @inline_macro_extensions[name.to_sym]) ? ext : false end
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:
-
A Treeprocessor subclass
-
An instance of a Treeprocessor subclass
-
The String name of a Treeprocessor subclass
-
A method block (i.e., Proc) that conforms to the Treeprocessor contract
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 603 def treeprocessor *args, &block add_document_processor :treeprocessor, args, &block end
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 618 def treeprocessors @treeprocessor_extensions end
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 610 def treeprocessors? !!@treeprocessor_extensions end
Private Instance Methods
# File lib/asciidoctor/extensions.rb, line 1003 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 class << processor include_dsl end 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
# File lib/asciidoctor/extensions.rb, line 1050 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 class << processor include_dsl end 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
# File lib/asciidoctor/extensions.rb, line 1118 def as_symbol name name ? ((name.is_a? ::Symbol) ? name : name.to_sym) : nil end
# File lib/asciidoctor/extensions.rb, line 1105 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