lib/asciidoctor/extensions.rb in asciidoctor-1.5.7.1 vs lib/asciidoctor/extensions.rb in asciidoctor-1.5.8

- old
+ new

@@ -157,10 +157,33 @@ def create_block parent, context, source, attrs, opts = {} Block.new parent, context, { :source => source, :attributes => attrs }.merge(opts) end + # Public: Creates a list node and links it to the specified parent. + # + # parent - The parent Block (Block, Section, or Document) of this new list block. + # context - The list context (e.g., :ulist, :olist, :colist, :dlist) + # attrs - A Hash of attributes to set on this list block + # + # Returns a [List] node with all properties properly initialized. + def create_list parent, context, attrs = nil + list = List.new parent, context + list.update_attributes attrs if attrs + list + end + + # Public: Creates a list item node and links it to the specified parent. + # + # parent - The parent List of this new list item block. + # text - The text of the list item. + # + # Returns a [ListItem] node with all properties properly initialized. + def create_list_item parent, text = nil + ListItem.new parent, text + end + # Public: Creates an image block node and links it to the specified parent. # # parent - The parent Block (Block, Section, or Document) of this new image block. # attrs - A Hash of attributes to control how the image block is built. # Use the target attribute to set the source of the image. @@ -171,11 +194,17 @@ def create_image_block parent, attrs, opts = {} unless (target = attrs['target']) raise ::ArgumentError, 'Unable to create an image block, target attribute is required' end attrs['alt'] ||= (attrs['default-alt'] = Helpers.basename(target, true).tr('_-', ' ')) - create_block parent, :image, nil, attrs, opts + title = (attrs.key? 'title') ? (attrs.delete 'title') : nil + block = create_block parent, :image, nil, attrs, opts + if title + block.title = title + block.assign_caption((attrs.delete 'caption'), (opts[:caption_context] || 'figure')) + end + block end def create_inline parent, context, text, opts = {} Inline.new parent, context, text, opts end @@ -241,13 +270,21 @@ def process_block_given? defined? @process_block end end - module SyntaxDsl + module DocumentProcessorDsl include ProcessorDsl + def prefer + option :position, :>> + end + end + + module SyntaxProcessorDsl + include ProcessorDsl + def named value # NOTE due to how processors get initialized, we must defer this assignment in some scenarios if Processor === self @name = value else @@ -341,11 +378,11 @@ class Preprocessor < Processor def process document, reader raise ::NotImplementedError, %(Asciidoctor::Extensions::Preprocessor subclass must implement ##{__method__} method) end end - Preprocessor::DSL = ProcessorDsl + Preprocessor::DSL = DocumentProcessorDsl # Public: TreeProcessors are run on the Document after the source has been # parsed into an abstract syntax tree (AST), as represented by the Document # object and its child Node objects (e.g., Section, Block, List, ListItem). # @@ -358,11 +395,11 @@ class TreeProcessor < Processor def process document raise ::NotImplementedError, %(Asciidoctor::Extensions::TreeProcessor subclass must implement ##{__method__} method) end end - TreeProcessor::DSL = ProcessorDsl + TreeProcessor::DSL = DocumentProcessorDsl # Alias deprecated class name for backwards compatibility Treeprocessor = TreeProcessor # Public: Postprocessors are run after the document is converted, but before @@ -383,11 +420,11 @@ class Postprocessor < Processor def process document, output raise ::NotImplementedError, %(Asciidoctor::Extensions::Postprocessor subclass must implement ##{__method__} method) end end - Postprocessor::DSL = ProcessorDsl + Postprocessor::DSL = DocumentProcessorDsl # Public: IncludeProcessors are used to process `include::<target>[]` # directives in the source document. # # When Asciidoctor comes across a `include::<target>[]` directive in the @@ -407,11 +444,11 @@ true end end module IncludeProcessorDsl - include ProcessorDsl + include DocumentProcessorDsl def handles? *args, &block if block_given? raise ::ArgumentError, %(wrong number of arguments (given #{args.size}, expected 0)) unless args.empty? @handles_block = block @@ -449,11 +486,11 @@ raise ::NotImplementedError, %(Asciidoctor::Extensions::DocinfoProcessor subclass must implement ##{__method__} method) end end module DocinfoProcessorDsl - include ProcessorDsl + include DocumentProcessorDsl def at_location value option :location, value end end @@ -505,11 +542,11 @@ raise ::NotImplementedError, %(Asciidoctor::Extensions::BlockProcessor subclass must implement ##{__method__} method) end end module BlockProcessorDsl - include SyntaxDsl + include SyntaxProcessorDsl def contexts *value option :contexts, value.flatten.to_set end alias on_contexts contexts @@ -531,11 +568,11 @@ raise ::NotImplementedError, %(Asciidoctor::Extensions::MacroProcessor subclass must implement ##{__method__} method) end end module MacroProcessorDsl - include SyntaxDsl + include SyntaxProcessorDsl def resolves_attributes *args if args.size == 1 && !args[0] option :content_model, :text return @@ -550,10 +587,14 @@ # Public: BlockMacroProcessors are used to handle block macros that have a # custom name. # # BlockMacroProcessor implementations must extend BlockMacroProcessor. class BlockMacroProcessor < MacroProcessor + def name + raise ::ArgumentError, %(invalid name for block macro: #{@name}) unless MacroNameRx.match? @name.to_s + @name + end end BlockMacroProcessor::DSL = MacroProcessorDsl # Public: InlineMacroProcessors are used to handle block macros that have a # custom name. @@ -1251,10 +1292,30 @@ # Returns an [Array] of Extension proxy objects. def inline_macros @inline_macro_extensions.values end + # Public: Inserts the document processor {Extension} instance as the first + # processor of its kind in the extension registry. + # + # Examples + # + # prefer :include_processor do + # process do |document, reader, target, attrs| + # ... + # end + # end + # + # Returns the [Extension] stored in the registry that proxies the instance + # of this processor. + def prefer *args, &block + extension = ProcessorExtension === (arg0 = args.shift) ? arg0 : (send arg0, *args, &block) + extensions_store = instance_variable_get(%(@#{extension.kind}_extensions).to_sym) + extensions_store.unshift extensions_store.delete extension + extension + end + private def add_document_processor kind, args, &block kind_name = kind.to_s.tr '_', ' ' kind_class_symbol = kind_name.split.map {|it| it.capitalize }.join.to_sym @@ -1296,15 +1357,12 @@ else raise ::ArgumentError, %(Invalid arguments specified for registering #{kind_name} extension: #{args}) end end - if extension.config[:position] == :>> - kind_store.unshift extension - else - kind_store << extension - end + extension.config[:position] == :>> ? (kind_store.unshift extension) : (kind_store << extension) + extension end def add_syntax_processor kind, args, &block kind_name = kind.to_s.tr '_', ' ' kind_class_symbol = (kind_name.split.map {|it| it.capitalize }.push 'Processor').join.to_sym @@ -1488,18 +1546,18 @@ end # Public: Resolves the Class object for the qualified name. # # Returns Class - if RUBY_MIN_VERSION_2 + if ::RUBY_MIN_VERSION_2 def class_for_name qualified_name resolved = ::Object.const_get qualified_name, false raise unless ::Class === resolved resolved rescue raise ::NameError, %(Could not resolve class for name: #{qualified_name}) end - elsif RUBY_MIN_VERSION_1_9 + elsif ::RUBY_MIN_VERSION_1_9 def class_for_name qualified_name resolved = (qualified_name.split '::').reduce ::Object do |current, name| name.empty? ? current : (current.const_get name, false) end raise unless ::Class === resolved