asciidoctor 0.1.4 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +209 -25
- data/{LICENSE → LICENSE.adoc} +4 -3
- data/README.adoc +392 -395
- data/Rakefile +94 -137
- data/benchmark/benchmark.rb +127 -0
- data/benchmark/sample-data/mdbasics.adoc +334 -0
- data/bin/asciidoctor +5 -8
- data/bin/asciidoctor-safe +4 -8
- data/compat/asciidoc.conf +78 -11
- data/compat/font-awesome-3-compat.css +397 -0
- data/data/stylesheets/asciidoctor-default.css +399 -0
- data/data/stylesheets/coderay-asciidoctor.css +89 -0
- data/features/open_block.feature +92 -0
- data/features/pass_block.feature +66 -0
- data/features/step_definitions.rb +42 -0
- data/features/text_formatting.feature +55 -0
- data/features/xref.feature +116 -0
- data/lib/asciidoctor.rb +1155 -605
- data/lib/asciidoctor/abstract_block.rb +157 -71
- data/lib/asciidoctor/abstract_node.rb +150 -93
- data/lib/asciidoctor/attribute_list.rb +85 -90
- data/lib/asciidoctor/block.rb +51 -24
- data/lib/asciidoctor/callouts.rb +4 -7
- data/lib/asciidoctor/cli.rb +3 -0
- data/lib/asciidoctor/cli/invoker.rb +86 -76
- data/lib/asciidoctor/cli/options.rb +111 -61
- data/lib/asciidoctor/converter.rb +232 -0
- data/lib/asciidoctor/converter/base.rb +58 -0
- data/lib/asciidoctor/converter/composite.rb +66 -0
- data/lib/asciidoctor/converter/docbook45.rb +94 -0
- data/lib/asciidoctor/converter/docbook5.rb +684 -0
- data/lib/asciidoctor/converter/factory.rb +225 -0
- data/lib/asciidoctor/converter/html5.rb +1081 -0
- data/lib/asciidoctor/converter/template.rb +296 -0
- data/lib/asciidoctor/core_ext.rb +7 -0
- data/lib/asciidoctor/core_ext/object/nil_or_empty.rb +23 -0
- data/lib/asciidoctor/core_ext/string/chr.rb +6 -0
- data/lib/asciidoctor/core_ext/symbol/length.rb +6 -0
- data/lib/asciidoctor/document.rb +590 -304
- data/lib/asciidoctor/extensions.rb +1100 -308
- data/lib/asciidoctor/helpers.rb +109 -46
- data/lib/asciidoctor/inline.rb +16 -9
- data/lib/asciidoctor/list.rb +23 -15
- data/lib/asciidoctor/opal_ext.rb +4 -0
- data/lib/asciidoctor/opal_ext/comparable.rb +38 -0
- data/lib/asciidoctor/opal_ext/dir.rb +13 -0
- data/lib/asciidoctor/opal_ext/error.rb +2 -0
- data/lib/asciidoctor/opal_ext/file.rb +125 -0
- data/lib/asciidoctor/{lexer.rb → parser.rb} +646 -455
- data/lib/asciidoctor/path_resolver.rb +141 -77
- data/lib/asciidoctor/reader.rb +257 -187
- data/lib/asciidoctor/section.rb +12 -16
- data/lib/asciidoctor/stylesheets.rb +91 -0
- data/lib/asciidoctor/substitutors.rb +1548 -0
- data/lib/asciidoctor/table.rb +73 -57
- data/lib/asciidoctor/timings.rb +39 -0
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +22 -14
- data/man/asciidoctor.adoc +18 -10
- data/test/attributes_test.rb +314 -14
- data/test/blocks_test.rb +763 -118
- data/test/converter_test.rb +352 -0
- data/test/document_test.rb +518 -199
- data/test/extensions_test.rb +273 -103
- data/test/fixtures/asciidoc_index.txt +27 -13
- data/test/fixtures/basic-docinfo.xml +1 -1
- data/test/fixtures/chapter-a.adoc +3 -0
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +6 -0
- data/test/fixtures/docinfo.xml +1 -1
- data/test/fixtures/include-file.asciidoc +2 -0
- data/test/fixtures/master.adoc +5 -0
- data/test/invoker_test.rb +173 -61
- data/test/links_test.rb +97 -21
- data/test/lists_test.rb +181 -22
- data/test/options_test.rb +86 -2
- data/test/paragraphs_test.rb +47 -5
- data/test/{lexer_test.rb → parser_test.rb} +128 -57
- data/test/paths_test.rb +36 -1
- data/test/preamble_test.rb +25 -17
- data/test/reader_test.rb +404 -249
- data/test/sections_test.rb +623 -58
- data/test/substitutions_test.rb +609 -132
- data/test/tables_test.rb +198 -24
- data/test/test_helper.rb +101 -31
- data/test/text_test.rb +88 -31
- metadata +160 -64
- data/Gemfile +0 -12
- data/Guardfile +0 -18
- data/asciidoctor.gemspec +0 -143
- data/lib/asciidoctor/backends/_stylesheets.rb +0 -466
- data/lib/asciidoctor/backends/base_template.rb +0 -114
- data/lib/asciidoctor/backends/docbook45.rb +0 -774
- data/lib/asciidoctor/backends/docbook5.rb +0 -103
- data/lib/asciidoctor/backends/html5.rb +0 -1214
- data/lib/asciidoctor/renderer.rb +0 -259
- data/lib/asciidoctor/substituters.rb +0 -1083
- data/test/fixtures/asciidoc.txt +0 -105
- data/test/fixtures/ascshort.txt +0 -32
- data/test/fixtures/list_elements.asciidoc +0 -10
- data/test/renderer_test.rb +0 -162
| @@ -1,443 +1,1235 @@ | |
| 1 1 | 
             
            module Asciidoctor
         | 
| 2 | 
            +
            # Extensions provide a way to participate in the parsing and converting
         | 
| 3 | 
            +
            # phases of the AsciiDoc processor or extend the AsciiDoc syntax.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # The various extensions participate in AsciiDoc processing as follows:
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # 1. After the source lines are normalized, {Preprocessor}s modify or replace
         | 
| 8 | 
            +
            #    the source lines before parsing begins.  {IncludeProcessor}s are used to
         | 
| 9 | 
            +
            #    process include directives for targets which they claim to handle.
         | 
| 10 | 
            +
            # 2. The Parser parses the block-level content into an abstract syntax tree.
         | 
| 11 | 
            +
            #    Custom blocks and block macros are processed by associated {BlockProcessor}s
         | 
| 12 | 
            +
            #    and {BlockMacroProcessor}s, respectively.
         | 
| 13 | 
            +
            # 3. {Treeprocessor}s are run on the abstract syntax tree.
         | 
| 14 | 
            +
            # 4. Conversion of the document begins, at which point inline markup is processed
         | 
| 15 | 
            +
            #    and converted. Custom inline macros are processed by associated {InlineMacroProcessor}s.
         | 
| 16 | 
            +
            # 5. {Postprocessor}s modify or replace the converted document.
         | 
| 17 | 
            +
            # 6. The output is written to the output stream.
         | 
| 18 | 
            +
            #
         | 
| 19 | 
            +
            # Extensions may be registered globally using the {Extensions.register} method
         | 
| 20 | 
            +
            # or added to a custom {Registry} instance and passed as an option to a single
         | 
| 21 | 
            +
            # Asciidoctor processor.
         | 
| 2 22 | 
             
            module Extensions
         | 
| 3 | 
            -
             | 
| 23 | 
            +
             | 
| 24 | 
            +
              # Public: An abstract base class for document and syntax processors.
         | 
| 25 | 
            +
              #
         | 
| 26 | 
            +
              # This class provides access to a class-level Hash for holding default
         | 
| 27 | 
            +
              # configuration options defined using the {Processor.option} method. This
         | 
| 28 | 
            +
              # style of default configuration is specific to the native Ruby environment
         | 
| 29 | 
            +
              # and is only consulted inside the initializer. An overriding configuration
         | 
| 30 | 
            +
              # Hash can be passed to the initializer. Once the processor is initialized,
         | 
| 31 | 
            +
              # the configuration is accessed using the {Processor#config} instance variable.
         | 
| 32 | 
            +
              #
         | 
| 33 | 
            +
              # Instances of the Processor class provide convenience methods for creating
         | 
| 34 | 
            +
              # AST nodes, such as Block and Inline, and for parsing child content.
         | 
| 35 | 
            +
              class Processor
         | 
| 4 36 | 
             
                class << self
         | 
| 5 | 
            -
                   | 
| 6 | 
            -
             | 
| 37 | 
            +
                  # Public: Get the static configuration for this processor class.
         | 
| 38 | 
            +
                  # 
         | 
| 39 | 
            +
                  # Returns a configuration [Hash]
         | 
| 40 | 
            +
                  def config
         | 
| 41 | 
            +
                    @config ||= {}
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  # Public: Assigns a default value for the specified option that gets
         | 
| 45 | 
            +
                  # applied to all instances of this processor.
         | 
| 46 | 
            +
                  #
         | 
| 47 | 
            +
                  # Examples
         | 
| 48 | 
            +
                  #
         | 
| 49 | 
            +
                  #   option :contexts, [:open, :paragraph]
         | 
| 50 | 
            +
                  #
         | 
| 51 | 
            +
                  # Returns nothing
         | 
| 52 | 
            +
                  def option key, default_value
         | 
| 53 | 
            +
                    config[key] = default_value
         | 
| 7 54 | 
             
                  end
         | 
| 8 55 |  | 
| 9 | 
            -
                   | 
| 56 | 
            +
                  # Include the DSL class for this processor into this processor class or instance.
         | 
| 57 | 
            +
                  #
         | 
| 58 | 
            +
                  # This method automatically detects whether to use the include or extend keyword
         | 
| 59 | 
            +
                  # based on what is appropriate.
         | 
| 60 | 
            +
                  #
         | 
| 61 | 
            +
                  # Returns nothing
         | 
| 62 | 
            +
                  def use_dsl
         | 
| 63 | 
            +
                    if self.name.nil_or_empty?
         | 
| 64 | 
            +
                      # NOTE contants(false) doesn't exist in Ruby 1.8.7
         | 
| 65 | 
            +
                      #include const_get :DSL if constants(false).grep :DSL
         | 
| 66 | 
            +
                      include const_get :DSL if constants.grep :DSL
         | 
| 67 | 
            +
                    else
         | 
| 68 | 
            +
                      # NOTE contants(false) doesn't exist in Ruby 1.8.7
         | 
| 69 | 
            +
                      #extend const_get :DSL if constants(false).grep :DSL
         | 
| 70 | 
            +
                      extend const_get :DSL if constants.grep :DSL
         | 
| 71 | 
            +
                    end
         | 
| 10 72 | 
             
                  end
         | 
| 73 | 
            +
                  alias :extend_dsl :use_dsl
         | 
| 74 | 
            +
                  alias :include_dsl :use_dsl
         | 
| 11 75 | 
             
                end
         | 
| 12 | 
            -
              end
         | 
| 13 76 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
                 | 
| 16 | 
            -
             | 
| 77 | 
            +
                # Public: Get the configuration Hash for this processor instance.
         | 
| 78 | 
            +
                attr_reader :config
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                def initialize config = {}
         | 
| 81 | 
            +
                  @config = self.class.config.merge config
         | 
| 17 82 | 
             
                end
         | 
| 18 83 |  | 
| 19 | 
            -
                def  | 
| 20 | 
            -
                  @ | 
| 84 | 
            +
                def update_config config
         | 
| 85 | 
            +
                  @config.update config
         | 
| 21 86 | 
             
                end
         | 
| 22 87 |  | 
| 23 | 
            -
                 | 
| 24 | 
            -
             | 
| 25 | 
            -
                # is name of block if block is given
         | 
| 26 | 
            -
                # having a name makes it easier to unregister an extension
         | 
| 27 | 
            -
                def register extension = nil, &block
         | 
| 28 | 
            -
                  if block_given?
         | 
| 29 | 
            -
                    registered << block
         | 
| 30 | 
            -
                  elsif extension
         | 
| 31 | 
            -
                    registered << resolve_class(extension)
         | 
| 32 | 
            -
                  end 
         | 
| 88 | 
            +
                def process *args
         | 
| 89 | 
            +
                  raise ::NotImplementedError
         | 
| 33 90 | 
             
                end
         | 
| 34 91 |  | 
| 35 | 
            -
                def  | 
| 36 | 
            -
                   | 
| 92 | 
            +
                def create_block parent, context, source, attrs, opts = {}
         | 
| 93 | 
            +
                  Block.new parent, context, { :source => source, :attributes => attrs }.merge(opts)
         | 
| 37 94 | 
             
                end
         | 
| 38 95 |  | 
| 39 | 
            -
                def  | 
| 40 | 
            -
                   | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 96 | 
            +
                def create_image_block parent, attrs, opts = {}
         | 
| 97 | 
            +
                  create_block parent, :image, nil, attrs, opts
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def create_inline parent, context, text, opts = {}
         | 
| 101 | 
            +
                  Inline.new parent, context, text, opts
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                # Public: Parses blocks in the content and attaches the block to the parent.
         | 
| 105 | 
            +
                #
         | 
| 106 | 
            +
                # Returns nothing
         | 
| 107 | 
            +
                #--
         | 
| 108 | 
            +
                # QUESTION is parse_content the right method name? should we wrap in open block automatically?
         | 
| 109 | 
            +
                def parse_content parent, content, attributes = {}
         | 
| 110 | 
            +
                  reader = (content.is_a? Reader) ? reader : (Reader.new content)
         | 
| 111 | 
            +
                  while reader.has_more_lines?
         | 
| 112 | 
            +
                    block = Parser.next_block(reader, parent, attributes)
         | 
| 113 | 
            +
                    parent << block if block
         | 
| 48 114 | 
             
                  end
         | 
| 115 | 
            +
                  nil
         | 
| 49 116 | 
             
                end
         | 
| 50 117 |  | 
| 51 | 
            -
                 | 
| 52 | 
            -
             | 
| 118 | 
            +
                # TODO fill out remaining methods
         | 
| 119 | 
            +
                [
         | 
| 120 | 
            +
                  [:create_paragraph,     :create_block,  :paragraph],
         | 
| 121 | 
            +
                  [:create_open_block,    :create_block,  :open],
         | 
| 122 | 
            +
                  [:create_example_block, :create_block,  :example],
         | 
| 123 | 
            +
                  [:create_pass_block,    :create_block,  :pass],
         | 
| 124 | 
            +
                  [:create_listing_block, :create_block,  :listing],
         | 
| 125 | 
            +
                  [:create_literal_block, :create_block,  :literal],
         | 
| 126 | 
            +
                  [:create_anchor,        :create_inline, :anchor]
         | 
| 127 | 
            +
                ].each do |method_name, delegate_method_name, context|
         | 
| 128 | 
            +
                  define_method method_name do |*args|
         | 
| 129 | 
            +
                    send delegate_method_name, *args.dup.insert(1, context)
         | 
| 130 | 
            +
                  end
         | 
| 53 131 | 
             
                end
         | 
| 54 132 | 
             
              end
         | 
| 55 133 |  | 
| 56 | 
            -
               | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
                 | 
| 61 | 
            -
             | 
| 62 | 
            -
                 | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
                   | 
| 67 | 
            -
                   | 
| 68 | 
            -
                   | 
| 69 | 
            -
             | 
| 70 | 
            -
                  @ | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
                  @block_macro_processor_cache = {}
         | 
| 76 | 
            -
                  @inline_macros = {}
         | 
| 77 | 
            -
                  @inline_macro_processor_cache = {}
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                  Extensions.registered.each do |extension|
         | 
| 80 | 
            -
                    if extension.is_a? Proc
         | 
| 81 | 
            -
                      register document, &extension
         | 
| 82 | 
            -
                    else
         | 
| 83 | 
            -
                      extension.activate self, document
         | 
| 84 | 
            -
                    end
         | 
| 85 | 
            -
                  end
         | 
| 86 | 
            -
                end 
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                def preprocessor processor, position = :<<
         | 
| 89 | 
            -
                  processor = resolve_processor_class processor
         | 
| 90 | 
            -
                  if position == :<< || @preprocessors.empty?
         | 
| 91 | 
            -
                    @preprocessors.push processor
         | 
| 92 | 
            -
                  elsif position == :>>
         | 
| 93 | 
            -
                    @preprocessors.unshift processor
         | 
| 134 | 
            +
              # Internal: Overlays a builder DSL for configuring the Processor instance.
         | 
| 135 | 
            +
              # Includes a method to define configuration options and another to define the
         | 
| 136 | 
            +
              # {Processor#process} method.
         | 
| 137 | 
            +
              module ProcessorDsl
         | 
| 138 | 
            +
                def option key, value
         | 
| 139 | 
            +
                  config[key] = value
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                def process *args, &block
         | 
| 143 | 
            +
                  # need to check for both block/proc and lambda
         | 
| 144 | 
            +
                  # TODO need test for this!
         | 
| 145 | 
            +
                  #if block_given? || (args.size == 1 && ((block = args[0]).is_a? ::Proc))
         | 
| 146 | 
            +
                  if block_given?
         | 
| 147 | 
            +
                    @process_block = block
         | 
| 148 | 
            +
                  elsif @process_block
         | 
| 149 | 
            +
                    # NOTE Proc automatically expands a single array argument
         | 
| 150 | 
            +
                    # ...but lambda doesn't (and we want to accept lambdas too)
         | 
| 151 | 
            +
                    # TODO need a test for this!
         | 
| 152 | 
            +
                    @process_block.call(*args)
         | 
| 94 153 | 
             
                  else
         | 
| 95 | 
            -
                     | 
| 154 | 
            +
                    raise ::NotImplementedError
         | 
| 96 155 | 
             
                  end
         | 
| 97 156 | 
             
                end
         | 
| 157 | 
            +
                #alias :process_with :process
         | 
| 98 158 |  | 
| 99 | 
            -
                def  | 
| 100 | 
            -
                   | 
| 159 | 
            +
                def process_block_given?
         | 
| 160 | 
            +
                  defined? @process_block
         | 
| 101 161 | 
             
                end
         | 
| 162 | 
            +
              end
         | 
| 102 163 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 164 | 
            +
              # Public: Preprocessors are run after the source text is split into lines and
         | 
| 165 | 
            +
              # normalized, but before parsing begins.
         | 
| 166 | 
            +
              #
         | 
| 167 | 
            +
              # Prior to invoking the preprocessor, Asciidoctor splits the source text into
         | 
| 168 | 
            +
              # lines and normalizes them. The normalize process strips trailing whitespace
         | 
| 169 | 
            +
              # from each line and leaves behind a line-feed character (i.e., "\n").
         | 
| 170 | 
            +
              #
         | 
| 171 | 
            +
              # Asciidoctor passes a reference to the Reader and a copy of the lines Array
         | 
| 172 | 
            +
              # to the {Processor#process} method of an instance of each registered
         | 
| 173 | 
            +
              # Preprocessor. The Preprocessor modifies the Array as necessary and either
         | 
| 174 | 
            +
              # returns a reference to the same Reader or a reference to a new Reader.
         | 
| 175 | 
            +
              #
         | 
| 176 | 
            +
              # Preprocessor implementations must extend the Preprocessor class.
         | 
| 177 | 
            +
              class Preprocessor < Processor
         | 
| 178 | 
            +
                def process document, reader
         | 
| 179 | 
            +
                  raise ::NotImplementedError
         | 
| 107 180 | 
             
                end
         | 
| 181 | 
            +
              end
         | 
| 182 | 
            +
              Preprocessor::DSL = ProcessorDsl
         | 
| 108 183 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 184 | 
            +
              # Public: Treeprocessors are run on the Document after the source has been
         | 
| 185 | 
            +
              # parsed into an abstract syntax tree (AST), as represented by the Document
         | 
| 186 | 
            +
              # object and its child Node objects (e.g., Section, Block, List, ListItem).
         | 
| 187 | 
            +
              #
         | 
| 188 | 
            +
              # Asciidoctor invokes the {Processor#process} method on an instance of each
         | 
| 189 | 
            +
              # registered Treeprocessor.
         | 
| 190 | 
            +
              #
         | 
| 191 | 
            +
              # Treeprocessor implementations must extend Treeprocessor.
         | 
| 192 | 
            +
              #--
         | 
| 193 | 
            +
              # QUESTION should the treeprocessor get invoked after parse header too?
         | 
| 194 | 
            +
              class Treeprocessor < Processor
         | 
| 195 | 
            +
                def process document
         | 
| 196 | 
            +
                  raise ::NotImplementedError
         | 
| 197 | 
            +
                end
         | 
| 198 | 
            +
              end
         | 
| 199 | 
            +
              Treeprocessor::DSL = ProcessorDsl
         | 
| 200 | 
            +
             | 
| 201 | 
            +
              # Public: Postprocessors are run after the document is converted, but before
         | 
| 202 | 
            +
              # it is written to the output stream.
         | 
| 203 | 
            +
              #
         | 
| 204 | 
            +
              # Asciidoctor passes a reference to the converted String to the {Processor#process}
         | 
| 205 | 
            +
              # method of each registered Postprocessor. The Preprocessor modifies the
         | 
| 206 | 
            +
              # String as necessary and returns the String replacement.
         | 
| 207 | 
            +
              #
         | 
| 208 | 
            +
              # The markup format in the String is determined by the backend used to convert
         | 
| 209 | 
            +
              # the Document. The backend and be looked up using the backend method on the
         | 
| 210 | 
            +
              # Document object, as well as various backend-related document attributes.
         | 
| 211 | 
            +
              #
         | 
| 212 | 
            +
              # TIP: Postprocessors can also be used to relocate assets needed by the published
         | 
| 213 | 
            +
              # document.
         | 
| 214 | 
            +
              #
         | 
| 215 | 
            +
              # Postprocessor implementations must Postprocessor.
         | 
| 216 | 
            +
              class Postprocessor < Processor
         | 
| 217 | 
            +
                def process document, output
         | 
| 218 | 
            +
                  raise ::NotImplementedError
         | 
| 219 | 
            +
                end
         | 
| 220 | 
            +
              end
         | 
| 221 | 
            +
              Postprocessor::DSL = ProcessorDsl
         | 
| 222 | 
            +
             | 
| 223 | 
            +
              # Public: IncludeProcessors are used to process `include::<target>[]`
         | 
| 224 | 
            +
              # directives in the source document.
         | 
| 225 | 
            +
              #
         | 
| 226 | 
            +
              # When Asciidoctor comes across a `include::<target>[]` directive in the
         | 
| 227 | 
            +
              # source document, it iterates through the IncludeProcessors and delegates
         | 
| 228 | 
            +
              # the work of reading the content to the first processor that identifies
         | 
| 229 | 
            +
              # itself as capable of handling that target.
         | 
| 230 | 
            +
              #
         | 
| 231 | 
            +
              # IncludeProcessor implementations must extend IncludeProcessor.
         | 
| 232 | 
            +
              #--
         | 
| 233 | 
            +
              # TODO add file extension or regexp to shortcut handles?
         | 
| 234 | 
            +
              class IncludeProcessor < Processor
         | 
| 235 | 
            +
                def process document, reader, target, attributes
         | 
| 236 | 
            +
                  raise ::NotImplementedError
         | 
| 237 | 
            +
                end
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                def handles? target
         | 
| 240 | 
            +
                  true
         | 
| 241 | 
            +
                end
         | 
| 242 | 
            +
              end
         | 
| 243 | 
            +
              IncludeProcessor::DSL = ProcessorDsl
         | 
| 244 | 
            +
             | 
| 245 | 
            +
              # Public: BlockProcessors are used to handle delimited blocks and paragraphs
         | 
| 246 | 
            +
              # that have a custom name.
         | 
| 247 | 
            +
              #
         | 
| 248 | 
            +
              # When Asciidoctor encounters a delimited block or paragraph with an
         | 
| 249 | 
            +
              # unrecognized name while parsing the document, it looks for a BlockProcessor
         | 
| 250 | 
            +
              # registered to handle this name and, if found, invokes its {Processor#process}
         | 
| 251 | 
            +
              # method to build a cooresponding node in the document tree.
         | 
| 252 | 
            +
              #
         | 
| 253 | 
            +
              # AsciiDoc example:
         | 
| 254 | 
            +
              #
         | 
| 255 | 
            +
              #   [shout]
         | 
| 256 | 
            +
              #   Get a move on.
         | 
| 257 | 
            +
              #
         | 
| 258 | 
            +
              # Recognized options:
         | 
| 259 | 
            +
              #
         | 
| 260 | 
            +
              # * :named - The name of the block (required: true)
         | 
| 261 | 
            +
              # * :contexts - The blocks contexts on which this style can be used (default: [:paragraph, :open]
         | 
| 262 | 
            +
              # * :content_model - The structure of the content supported in this block (default: :compound)
         | 
| 263 | 
            +
              # * :positional_attributes - A list of attribute names used to map positional attributes (default: nil)
         | 
| 264 | 
            +
              # * ...
         | 
| 265 | 
            +
              #
         | 
| 266 | 
            +
              # BlockProcessor implementations must extend BlockProcessor.
         | 
| 267 | 
            +
              class BlockProcessor < Processor
         | 
| 268 | 
            +
                attr_accessor :name
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                def initialize name = nil, config = {}
         | 
| 271 | 
            +
                  super config
         | 
| 272 | 
            +
                  @name = name || @config[:name]
         | 
| 273 | 
            +
                  # assign fallbacks
         | 
| 274 | 
            +
                  case @config[:contexts]
         | 
| 275 | 
            +
                  when ::NilClass
         | 
| 276 | 
            +
                    @config[:contexts] ||= [:open, :paragraph].to_set
         | 
| 277 | 
            +
                  when ::Symbol
         | 
| 278 | 
            +
                    @config[:contexts] = [@config[:contexts]].to_set
         | 
| 115 279 | 
             
                  else
         | 
| 116 | 
            -
                    @ | 
| 280 | 
            +
                    @config[:contexts] = @config[:contexts].to_set
         | 
| 117 281 | 
             
                  end
         | 
| 282 | 
            +
                  # QUESTION should the default content model be raw??
         | 
| 283 | 
            +
                  @config[:content_model] ||= :compound
         | 
| 118 284 | 
             
                end
         | 
| 119 285 |  | 
| 120 | 
            -
                def  | 
| 121 | 
            -
                   | 
| 286 | 
            +
                def process parent, reader, attributes
         | 
| 287 | 
            +
                  raise ::NotImplementedError
         | 
| 122 288 | 
             
                end
         | 
| 289 | 
            +
              end
         | 
| 290 | 
            +
             | 
| 291 | 
            +
              module BlockProcessorDsl
         | 
| 292 | 
            +
                include ProcessorDsl
         | 
| 123 293 |  | 
| 124 | 
            -
                 | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 294 | 
            +
                # FIXME this isn't the prettiest thing
         | 
| 295 | 
            +
                def named value
         | 
| 296 | 
            +
                  if self.is_a? Processor
         | 
| 297 | 
            +
                    @name = value
         | 
| 298 | 
            +
                  else
         | 
| 299 | 
            +
                    option :name, value
         | 
| 127 300 | 
             
                  end
         | 
| 128 301 | 
             
                end
         | 
| 302 | 
            +
                alias :match_name :named
         | 
| 303 | 
            +
                alias :bind_to :named
         | 
| 129 304 |  | 
| 130 | 
            -
                def  | 
| 131 | 
            -
                   | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 305 | 
            +
                def contexts *value
         | 
| 306 | 
            +
                  option :contexts, value.flatten
         | 
| 307 | 
            +
                end
         | 
| 308 | 
            +
                alias :on_contexts :contexts
         | 
| 309 | 
            +
                alias :on_context :contexts
         | 
| 310 | 
            +
             | 
| 311 | 
            +
                def content_model value
         | 
| 312 | 
            +
                  option :content_model, value
         | 
| 313 | 
            +
                end
         | 
| 314 | 
            +
                alias :parse_content_as :content_model
         | 
| 315 | 
            +
             | 
| 316 | 
            +
                def positional_attributes *value
         | 
| 317 | 
            +
                  option :pos_attrs, value.flatten
         | 
| 318 | 
            +
                end
         | 
| 319 | 
            +
                alias :pos_attrs :positional_attributes
         | 
| 320 | 
            +
                alias :name_attributes :positional_attributes
         | 
| 321 | 
            +
                alias :name_positional_attributes :positional_attributes
         | 
| 322 | 
            +
             | 
| 323 | 
            +
                def default_attrs value
         | 
| 324 | 
            +
                  option :default_attrs, value
         | 
| 325 | 
            +
                end
         | 
| 326 | 
            +
                alias :seed_attributes_with :default_attrs
         | 
| 327 | 
            +
              end
         | 
| 328 | 
            +
              BlockProcessor::DSL = BlockProcessorDsl
         | 
| 329 | 
            +
             | 
| 330 | 
            +
              class MacroProcessor < Processor
         | 
| 331 | 
            +
                attr_accessor :name
         | 
| 332 | 
            +
             | 
| 333 | 
            +
                def initialize name = nil, config = {}
         | 
| 334 | 
            +
                  super config
         | 
| 335 | 
            +
                  @name = name || @config[:name]
         | 
| 336 | 
            +
                  @config[:content_model] ||= :attributes
         | 
| 337 | 
            +
                end
         | 
| 338 | 
            +
             | 
| 339 | 
            +
                def process parent, target, attributes
         | 
| 340 | 
            +
                  raise ::NotImplementedError
         | 
| 341 | 
            +
                end
         | 
| 342 | 
            +
              end
         | 
| 343 | 
            +
             | 
| 344 | 
            +
              module MacroProcessorDsl
         | 
| 345 | 
            +
                include ProcessorDsl
         | 
| 346 | 
            +
                # QUESTION perhaps include a SyntaxDsl?
         | 
| 347 | 
            +
             | 
| 348 | 
            +
                def named value
         | 
| 349 | 
            +
                  if self.is_a? Processor
         | 
| 350 | 
            +
                    @name = value
         | 
| 136 351 | 
             
                  else
         | 
| 137 | 
            -
                     | 
| 352 | 
            +
                    option :name, value
         | 
| 138 353 | 
             
                  end
         | 
| 139 354 | 
             
                end
         | 
| 355 | 
            +
                alias :match_name :named
         | 
| 356 | 
            +
                alias :bind_to :named
         | 
| 140 357 |  | 
| 141 | 
            -
                def  | 
| 142 | 
            -
                   | 
| 358 | 
            +
                def content_model value
         | 
| 359 | 
            +
                  option :content_model, value
         | 
| 143 360 | 
             
                end
         | 
| 361 | 
            +
                alias :parse_content_as :content_model
         | 
| 144 362 |  | 
| 145 | 
            -
                def  | 
| 146 | 
            -
                   | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 363 | 
            +
                def positional_attributes *value
         | 
| 364 | 
            +
                  option :pos_attrs, value.flatten
         | 
| 365 | 
            +
                end
         | 
| 366 | 
            +
                alias :pos_attrs :positional_attributes
         | 
| 367 | 
            +
                alias :name_attributes :positional_attributes
         | 
| 368 | 
            +
                alias :name_positional_attributes :positional_attributes
         | 
| 369 | 
            +
             | 
| 370 | 
            +
                def default_attrs value
         | 
| 371 | 
            +
                  option :default_attrs, value
         | 
| 149 372 | 
             
                end
         | 
| 373 | 
            +
                alias :seed_attributes_with :default_attrs
         | 
| 374 | 
            +
              end
         | 
| 375 | 
            +
             | 
| 376 | 
            +
              # Public: BlockMacroProcessors are used to handle block macros that have a
         | 
| 377 | 
            +
              # custom name.
         | 
| 378 | 
            +
              #
         | 
| 379 | 
            +
              # BlockMacroProcessor implementations must extend BlockMacroProcessor.
         | 
| 380 | 
            +
              class BlockMacroProcessor < MacroProcessor
         | 
| 381 | 
            +
              end
         | 
| 382 | 
            +
              BlockMacroProcessor::DSL = MacroProcessorDsl
         | 
| 150 383 |  | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 384 | 
            +
              # Public: InlineMacroProcessors are used to handle block macros that have a
         | 
| 385 | 
            +
              # custom name.
         | 
| 386 | 
            +
              #
         | 
| 387 | 
            +
              # InlineMacroProcessor implementations must extend InlineMacroProcessor.
         | 
| 388 | 
            +
              #--
         | 
| 389 | 
            +
              # TODO break this out into different pattern types
         | 
| 390 | 
            +
              # for example, FormalInlineMacro, ShortInlineMacro (no target) and other patterns
         | 
| 391 | 
            +
              # FIXME for inline passthrough, we need to have some way to specify the text as a passthrough
         | 
| 392 | 
            +
              class InlineMacroProcessor < MacroProcessor
         | 
| 393 | 
            +
                def initialize name, config = {}
         | 
| 394 | 
            +
                  super
         | 
| 395 | 
            +
                  @config[:regexp] ||= (resolve_regexp @name, @config[:format])
         | 
| 396 | 
            +
                end
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                def resolve_regexp name, format
         | 
| 399 | 
            +
                  # TODO memoize these regular expressions!
         | 
| 400 | 
            +
                  if format == :short
         | 
| 401 | 
            +
                    %r(\\?#{name}:\[((?:\\\]|[^\]])*?)\])
         | 
| 157 402 | 
             
                  else
         | 
| 158 | 
            -
                     | 
| 403 | 
            +
                    %r(\\?#{name}:(\S+?)\[((?:\\\]|[^\]])*?)\])
         | 
| 159 404 | 
             
                  end
         | 
| 160 405 | 
             
                end
         | 
| 406 | 
            +
              end
         | 
| 161 407 |  | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 408 | 
            +
              module InlineMacroProcessorDsl
         | 
| 409 | 
            +
                include MacroProcessorDsl
         | 
| 410 | 
            +
             | 
| 411 | 
            +
                def using_format value
         | 
| 412 | 
            +
                  option :format, value
         | 
| 164 413 | 
             
                end
         | 
| 165 414 |  | 
| 166 | 
            -
                def  | 
| 167 | 
            -
                   | 
| 168 | 
            -
                    processor.new(*args)
         | 
| 169 | 
            -
                  end
         | 
| 170 | 
            -
                  # QUESTION do we need/want the cache?
         | 
| 171 | 
            -
                  #@include_processors.map do |processor|
         | 
| 172 | 
            -
                  #  @include_processor_cache[processor] ||= processor.new(*args)
         | 
| 173 | 
            -
                  #end
         | 
| 415 | 
            +
                def match value
         | 
| 416 | 
            +
                  option :regexp, value
         | 
| 174 417 | 
             
                end
         | 
| 418 | 
            +
              end
         | 
| 419 | 
            +
              InlineMacroProcessor::DSL = InlineMacroProcessorDsl
         | 
| 175 420 |  | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 421 | 
            +
              # Public: Extension is a proxy object for an extension implementation such as
         | 
| 422 | 
            +
              # a processor. It allows the preparation of the extension instance to be
         | 
| 423 | 
            +
              # separated from its usage to provide consistency between different
         | 
| 424 | 
            +
              # interfaces and avoid tight coupling with the extension type.
         | 
| 425 | 
            +
              #
         | 
| 426 | 
            +
              # The proxy encapsulates the extension kind (e.g., :block), its config Hash
         | 
| 427 | 
            +
              # and the extension instance. This Proxy is what gets stored in the extension
         | 
| 428 | 
            +
              # registry when activated.
         | 
| 429 | 
            +
              #--
         | 
| 430 | 
            +
              # QUESTION call this ExtensionInfo?
         | 
| 431 | 
            +
              class Extension
         | 
| 432 | 
            +
                attr :kind
         | 
| 433 | 
            +
                attr :config
         | 
| 434 | 
            +
                attr :instance
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                def initialize kind, instance, config
         | 
| 437 | 
            +
                  @kind = kind
         | 
| 438 | 
            +
                  @instance = instance
         | 
| 439 | 
            +
                  @config = config
         | 
| 440 | 
            +
                end
         | 
| 441 | 
            +
              end
         | 
| 442 | 
            +
             | 
| 443 | 
            +
              # Public: A specialization of the Extension proxy that additionally stores a
         | 
| 444 | 
            +
              # reference to the {Processor#process} method. By storing this reference, its
         | 
| 445 | 
            +
              # possible to accomodate both concrete extension implementations and Procs.
         | 
| 446 | 
            +
              class ProcessorExtension < Extension
         | 
| 447 | 
            +
                attr :process_method
         | 
| 448 | 
            +
             | 
| 449 | 
            +
                def initialize kind, instance, process_method = nil
         | 
| 450 | 
            +
                  super kind, instance, instance.config
         | 
| 451 | 
            +
                  @process_method = process_method || instance.method(:process)
         | 
| 452 | 
            +
                end
         | 
| 453 | 
            +
              end
         | 
| 454 | 
            +
             | 
| 455 | 
            +
              # Public: A Group is used to register one or more extensions with the Registry.
         | 
| 456 | 
            +
              #
         | 
| 457 | 
            +
              # The Group should be subclassed and registered with the Registry either by
         | 
| 458 | 
            +
              # invoking the {Group.register} method or passing the subclass to the
         | 
| 459 | 
            +
              # {Extensions.register} method. Extensions are registered with the Registry
         | 
| 460 | 
            +
              # inside the {Group#activate} method.
         | 
| 461 | 
            +
              class Group
         | 
| 462 | 
            +
                class << self
         | 
| 463 | 
            +
                  def register name = nil
         | 
| 464 | 
            +
                    Extensions.register name, self
         | 
| 184 465 | 
             
                  end
         | 
| 185 466 | 
             
                end
         | 
| 186 467 |  | 
| 187 | 
            -
                def  | 
| 188 | 
            -
                   | 
| 468 | 
            +
                def activate registry
         | 
| 469 | 
            +
                  raise ::NotImplementedError
         | 
| 189 470 | 
             
                end
         | 
| 471 | 
            +
              end
         | 
| 472 | 
            +
             | 
| 473 | 
            +
              # Public: The primary entry point into the extension system.
         | 
| 474 | 
            +
              #
         | 
| 475 | 
            +
              # Registry holds the extensions which have been registered and activated, has
         | 
| 476 | 
            +
              # methods for registering or defining a processor and looks up extensions
         | 
| 477 | 
            +
              # stored in the registry during parsing.
         | 
| 478 | 
            +
              class Registry
         | 
| 479 | 
            +
                # Public: Returns the {Asciidoctor::Document} on which the extensions in this registry are being used.
         | 
| 480 | 
            +
                attr_reader :document
         | 
| 481 | 
            +
             | 
| 482 | 
            +
                # Public: Returns the Array of {Group} classes, instances and/or Procs that have been registered.
         | 
| 483 | 
            +
                attr_reader :groups
         | 
| 190 484 |  | 
| 191 | 
            -
                def  | 
| 192 | 
            -
                   | 
| 485 | 
            +
                def initialize groups = {}
         | 
| 486 | 
            +
                  @groups = groups
         | 
| 487 | 
            +
                  @preprocessor_extensions = @treeprocessor_extensions = @postprocessor_extensions = @include_processor_extensions = nil
         | 
| 488 | 
            +
                  @block_extensions = @block_macro_extensions = @inline_macro_extensions = nil
         | 
| 489 | 
            +
                  @document = nil
         | 
| 193 490 | 
             
                end
         | 
| 194 491 |  | 
| 195 | 
            -
                #  | 
| 196 | 
            -
                 | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 492 | 
            +
                # Public: Activates all the global extension {Group}s and the extension {Group}s
         | 
| 493 | 
            +
                # associated with this registry.
         | 
| 494 | 
            +
                #
         | 
| 495 | 
            +
                # document - the {Asciidoctor::Document} on which the extensions are to be used.
         | 
| 496 | 
            +
                #
         | 
| 497 | 
            +
                # Returns the instance of this [Registry].
         | 
| 498 | 
            +
                def activate document
         | 
| 499 | 
            +
                  @document = document
         | 
| 500 | 
            +
                  (Extensions.groups.values + @groups.values).each do |group|
         | 
| 501 | 
            +
                    case group
         | 
| 502 | 
            +
                    when ::Proc
         | 
| 503 | 
            +
                      case group.arity
         | 
| 504 | 
            +
                      when 0, -1
         | 
| 505 | 
            +
                        instance_exec(&group)
         | 
| 506 | 
            +
                      when 1
         | 
| 507 | 
            +
                        group.call self
         | 
| 201 508 | 
             
                      end
         | 
| 509 | 
            +
                    when ::Class
         | 
| 510 | 
            +
                      group.new.activate self
         | 
| 202 511 | 
             
                    else
         | 
| 203 | 
            -
                       | 
| 204 | 
            -
                        return name
         | 
| 205 | 
            -
                      end
         | 
| 512 | 
            +
                      group.activate self
         | 
| 206 513 | 
             
                    end
         | 
| 207 514 | 
             
                  end
         | 
| 208 | 
            -
                   | 
| 515 | 
            +
                  self
         | 
| 209 516 | 
             
                end
         | 
| 210 517 |  | 
| 211 | 
            -
                 | 
| 212 | 
            -
             | 
| 518 | 
            +
                # Public: Registers a {Preprocessor} with the extension registry to process
         | 
| 519 | 
            +
                # the AsciiDoc source before parsing begins.
         | 
| 520 | 
            +
                #
         | 
| 521 | 
            +
                # The Preprocessor may be one of four types:
         | 
| 522 | 
            +
                #
         | 
| 523 | 
            +
                # * A Preprocessor subclass
         | 
| 524 | 
            +
                # * An instance of a Preprocessor subclass
         | 
| 525 | 
            +
                # * The String name of a Preprocessor subclass
         | 
| 526 | 
            +
                # * A method block (i.e., Proc) that conforms to the Preprocessor contract
         | 
| 527 | 
            +
                #
         | 
| 528 | 
            +
                # Unless the Preprocessor is passed as the method block, it must be the
         | 
| 529 | 
            +
                # first argument to this method.
         | 
| 530 | 
            +
                #
         | 
| 531 | 
            +
                # Examples
         | 
| 532 | 
            +
                #
         | 
| 533 | 
            +
                #   # as a Preprocessor subclass
         | 
| 534 | 
            +
                #   preprocessor FrontMatterPreprocessor
         | 
| 535 | 
            +
                #
         | 
| 536 | 
            +
                #   # as an instance of a Preprocessor subclass
         | 
| 537 | 
            +
                #   preprocessor FrontMatterPreprocessor.new
         | 
| 538 | 
            +
                #
         | 
| 539 | 
            +
                #   # as a name of a Preprocessor subclass
         | 
| 540 | 
            +
                #   preprocessor 'FrontMatterPreprocessor'
         | 
| 541 | 
            +
                #
         | 
| 542 | 
            +
                #   # as a method block
         | 
| 543 | 
            +
                #   preprocessor do
         | 
| 544 | 
            +
                #     process |reader, lines|
         | 
| 545 | 
            +
                #       ...
         | 
| 546 | 
            +
                #     end
         | 
| 547 | 
            +
                #   end
         | 
| 548 | 
            +
                #
         | 
| 549 | 
            +
                # Returns the [Extension] stored in the registry that proxies the
         | 
| 550 | 
            +
                # instance of this Preprocessor.
         | 
| 551 | 
            +
                def preprocessor *args, &block
         | 
| 552 | 
            +
                  add_document_processor :preprocessor, args, &block
         | 
| 213 553 | 
             
                end
         | 
| 214 554 |  | 
| 215 | 
            -
                 | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
                  end
         | 
| 555 | 
            +
                # Public: Checks whether any {Preprocessor} extensions have been registered.
         | 
| 556 | 
            +
                #
         | 
| 557 | 
            +
                # Returns a [Boolean] indicating whether any Preprocessor extensions are registered.
         | 
| 558 | 
            +
                def preprocessors?
         | 
| 559 | 
            +
                  !!@preprocessor_extensions
         | 
| 221 560 | 
             
                end
         | 
| 222 561 |  | 
| 223 | 
            -
                 | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 562 | 
            +
                # Public: Retrieves the {Extension} proxy objects for all
         | 
| 563 | 
            +
                # Preprocessor instances in this registry.
         | 
| 564 | 
            +
                #
         | 
| 565 | 
            +
                # Returns an [Array] of Extension proxy objects.
         | 
| 566 | 
            +
                def preprocessors
         | 
| 567 | 
            +
                  @preprocessor_extensions
         | 
| 226 568 | 
             
                end
         | 
| 227 569 |  | 
| 228 | 
            -
                 | 
| 229 | 
            -
             | 
| 570 | 
            +
                # Public: Registers a {Treeprocessor} with the extension registry to process
         | 
| 571 | 
            +
                # the AsciiDoc source after parsing is complete.
         | 
| 572 | 
            +
                #
         | 
| 573 | 
            +
                # The Treeprocessor may be one of four types:
         | 
| 574 | 
            +
                #
         | 
| 575 | 
            +
                # * A Treeprocessor subclass
         | 
| 576 | 
            +
                # * An instance of a Treeprocessor subclass
         | 
| 577 | 
            +
                # * The String name of a Treeprocessor subclass
         | 
| 578 | 
            +
                # * A method block (i.e., Proc) that conforms to the Treeprocessor contract
         | 
| 579 | 
            +
                #
         | 
| 580 | 
            +
                # Unless the Treeprocessor is passed as the method block, it must be the
         | 
| 581 | 
            +
                # first argument to this method.
         | 
| 582 | 
            +
                #
         | 
| 583 | 
            +
                # Examples
         | 
| 584 | 
            +
                #
         | 
| 585 | 
            +
                #   # as a Treeprocessor subclass
         | 
| 586 | 
            +
                #   treeprocessor ShellTreeprocessor
         | 
| 587 | 
            +
                #
         | 
| 588 | 
            +
                #   # as an instance of a Treeprocessor subclass
         | 
| 589 | 
            +
                #   treeprocessor ShellTreeprocessor.new
         | 
| 590 | 
            +
                #
         | 
| 591 | 
            +
                #   # as a name of a Treeprocessor subclass
         | 
| 592 | 
            +
                #   treeprocessor 'ShellTreeprocessor'
         | 
| 593 | 
            +
                #
         | 
| 594 | 
            +
                #   # as a method block
         | 
| 595 | 
            +
                #   treeprocessor do
         | 
| 596 | 
            +
                #     process |document|
         | 
| 597 | 
            +
                #       ...
         | 
| 598 | 
            +
                #     end
         | 
| 599 | 
            +
                #   end
         | 
| 600 | 
            +
                #
         | 
| 601 | 
            +
                # Returns the [Extension] stored in the registry that proxies the
         | 
| 602 | 
            +
                # instance of this Treeprocessor.
         | 
| 603 | 
            +
                def treeprocessor *args, &block
         | 
| 604 | 
            +
                  add_document_processor :treeprocessor, args, &block
         | 
| 230 605 | 
             
                end
         | 
| 231 606 |  | 
| 232 | 
            -
                 | 
| 233 | 
            -
             | 
| 607 | 
            +
                # Public: Checks whether any {Treeprocessor} extensions have been registered.
         | 
| 608 | 
            +
                #
         | 
| 609 | 
            +
                # Returns a [Boolean] indicating whether any Treeprocessor extensions are registered.
         | 
| 610 | 
            +
                def treeprocessors?
         | 
| 611 | 
            +
                  !!@treeprocessor_extensions
         | 
| 234 612 | 
             
                end
         | 
| 235 613 |  | 
| 236 | 
            -
                 | 
| 237 | 
            -
             | 
| 614 | 
            +
                # Public: Retrieves the {Extension} proxy objects for all
         | 
| 615 | 
            +
                # Treeprocessor instances in this registry.
         | 
| 616 | 
            +
                #
         | 
| 617 | 
            +
                # Returns an [Array] of Extension proxy objects.
         | 
| 618 | 
            +
                def treeprocessors
         | 
| 619 | 
            +
                  @treeprocessor_extensions
         | 
| 238 620 | 
             
                end
         | 
| 239 621 |  | 
| 240 | 
            -
                #  | 
| 241 | 
            -
                 | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 622 | 
            +
                # Public: Registers a {Postprocessor} with the extension registry to process
         | 
| 623 | 
            +
                # the output after conversion is complete.
         | 
| 624 | 
            +
                #
         | 
| 625 | 
            +
                # The Postprocessor may be one of four types:
         | 
| 626 | 
            +
                #
         | 
| 627 | 
            +
                # * A Postprocessor subclass
         | 
| 628 | 
            +
                # * An instance of a Postprocessor subclass
         | 
| 629 | 
            +
                # * The String name of a Postprocessor subclass
         | 
| 630 | 
            +
                # * A method block (i.e., Proc) that conforms to the Postprocessor contract
         | 
| 631 | 
            +
                #
         | 
| 632 | 
            +
                # Unless the Postprocessor is passed as the method block, it must be the
         | 
| 633 | 
            +
                # first argument to this method.
         | 
| 634 | 
            +
                #
         | 
| 635 | 
            +
                # Examples
         | 
| 636 | 
            +
                #
         | 
| 637 | 
            +
                #   # as a Postprocessor subclass
         | 
| 638 | 
            +
                #   postprocessor AnalyticsPostprocessor
         | 
| 639 | 
            +
                #
         | 
| 640 | 
            +
                #   # as an instance of a Postprocessor subclass
         | 
| 641 | 
            +
                #   postprocessor AnalyticsPostprocessor.new
         | 
| 642 | 
            +
                #
         | 
| 643 | 
            +
                #   # as a name of a Postprocessor subclass
         | 
| 644 | 
            +
                #   postprocessor 'AnalyticsPostprocessor'
         | 
| 645 | 
            +
                #
         | 
| 646 | 
            +
                #   # as a method block
         | 
| 647 | 
            +
                #   postprocessor do
         | 
| 648 | 
            +
                #     process |document, output|
         | 
| 649 | 
            +
                #       ...
         | 
| 650 | 
            +
                #     end
         | 
| 651 | 
            +
                #   end
         | 
| 652 | 
            +
                #
         | 
| 653 | 
            +
                # Returns the [Extension] stored in the registry that proxies the
         | 
| 654 | 
            +
                # instance of this Postprocessor.
         | 
| 655 | 
            +
                def postprocessor *args, &block
         | 
| 656 | 
            +
                  add_document_processor :postprocessor, args, &block
         | 
| 244 657 | 
             
                end
         | 
| 245 658 |  | 
| 246 | 
            -
                 | 
| 247 | 
            -
             | 
| 659 | 
            +
                # Public: Checks whether any {Postprocessor} extensions have been registered.
         | 
| 660 | 
            +
                #
         | 
| 661 | 
            +
                # Returns a [Boolean] indicating whether any Postprocessor extensions are registered.
         | 
| 662 | 
            +
                def postprocessors?
         | 
| 663 | 
            +
                  !!@postprocessor_extensions
         | 
| 248 664 | 
             
                end
         | 
| 249 665 |  | 
| 250 | 
            -
                 | 
| 251 | 
            -
             | 
| 666 | 
            +
                # Public: Retrieves the {Extension} proxy objects for all
         | 
| 667 | 
            +
                # Postprocessor instances in this registry.
         | 
| 668 | 
            +
                #
         | 
| 669 | 
            +
                # Returns an [Array] of Extension proxy objects.
         | 
| 670 | 
            +
                def postprocessors
         | 
| 671 | 
            +
                  @postprocessor_extensions
         | 
| 252 672 | 
             
                end
         | 
| 253 673 |  | 
| 254 | 
            -
                 | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 674 | 
            +
                # Public: Registers an {IncludeProcessor} with the extension registry to have
         | 
| 675 | 
            +
                # a shot at handling the include directive.
         | 
| 676 | 
            +
                #
         | 
| 677 | 
            +
                # The IncludeProcessor may be one of four types:
         | 
| 678 | 
            +
                #
         | 
| 679 | 
            +
                # * A IncludeProcessor subclass
         | 
| 680 | 
            +
                # * An instance of a IncludeProcessor subclass
         | 
| 681 | 
            +
                # * The String name of a IncludeProcessor subclass
         | 
| 682 | 
            +
                # * A method block (i.e., Proc) that conforms to the IncludeProcessor contract
         | 
| 683 | 
            +
                #
         | 
| 684 | 
            +
                # Unless the IncludeProcessor is passed as the method block, it must be the
         | 
| 685 | 
            +
                # first argument to this method.
         | 
| 686 | 
            +
                #
         | 
| 687 | 
            +
                # Examples
         | 
| 688 | 
            +
                #
         | 
| 689 | 
            +
                #   # as an IncludeProcessor subclass
         | 
| 690 | 
            +
                #   include_processor GitIncludeProcessor
         | 
| 691 | 
            +
                #
         | 
| 692 | 
            +
                #   # as an instance of a Postprocessor subclass
         | 
| 693 | 
            +
                #   include_processor GitIncludeProcessor.new
         | 
| 694 | 
            +
                #
         | 
| 695 | 
            +
                #   # as a name of a Postprocessor subclass
         | 
| 696 | 
            +
                #   include_processor 'GitIncludeProcessor'
         | 
| 697 | 
            +
                #
         | 
| 698 | 
            +
                #   # as a method block
         | 
| 699 | 
            +
                #   include_processor do
         | 
| 700 | 
            +
                #     process |document, output|
         | 
| 701 | 
            +
                #       ...
         | 
| 702 | 
            +
                #     end
         | 
| 703 | 
            +
                #   end
         | 
| 704 | 
            +
                #
         | 
| 705 | 
            +
                # Returns the [Extension] stored in the registry that proxies the
         | 
| 706 | 
            +
                # instance of this IncludeProcessor.
         | 
| 707 | 
            +
                def include_processor *args, &block
         | 
| 708 | 
            +
                  add_document_processor :include_processor, args, &block
         | 
| 258 709 | 
             
                end
         | 
| 259 710 |  | 
| 260 | 
            -
                 | 
| 261 | 
            -
             | 
| 711 | 
            +
                # Public: Checks whether any {IncludeProcessor} extensions have been registered.
         | 
| 712 | 
            +
                #
         | 
| 713 | 
            +
                # Returns a [Boolean] indicating whether any IncludeProcessor extensions are registered.
         | 
| 714 | 
            +
                def include_processors?
         | 
| 715 | 
            +
                  !!@include_processor_extensions
         | 
| 262 716 | 
             
                end
         | 
| 263 717 |  | 
| 264 | 
            -
                 | 
| 265 | 
            -
             | 
| 718 | 
            +
                # Public: Retrieves the {Extension} proxy objects for all the
         | 
| 719 | 
            +
                # IncludeProcessor instances stored in this registry.
         | 
| 720 | 
            +
                #
         | 
| 721 | 
            +
                # Returns an [Array] of Extension proxy objects.
         | 
| 722 | 
            +
                def include_processors
         | 
| 723 | 
            +
                  @include_processor_extensions
         | 
| 266 724 | 
             
                end
         | 
| 267 725 |  | 
| 268 | 
            -
                 | 
| 269 | 
            -
             | 
| 726 | 
            +
                # Public: Registers a {BlockProcessor} with the extension registry to
         | 
| 727 | 
            +
                # process the block content (i.e., delimited block or paragraph) in the
         | 
| 728 | 
            +
                # AsciiDoc source annotated with the specified block name (i.e., style).
         | 
| 729 | 
            +
                #
         | 
| 730 | 
            +
                # The BlockProcessor may be one of four types:
         | 
| 731 | 
            +
                #
         | 
| 732 | 
            +
                # * A BlockProcessor subclass
         | 
| 733 | 
            +
                # * An instance of a BlockProcessor subclass
         | 
| 734 | 
            +
                # * The String name of a BlockProcessor subclass
         | 
| 735 | 
            +
                # * A method block (i.e., Proc) that conforms to the BlockProcessor contract
         | 
| 736 | 
            +
                #
         | 
| 737 | 
            +
                # Unless the BlockProcessor is passed as the method block, it must be the
         | 
| 738 | 
            +
                # first argument to this method. The second argument is the name (coersed
         | 
| 739 | 
            +
                # to a Symbol) of the AsciiDoc block content (i.e., delimited block or
         | 
| 740 | 
            +
                # paragraph) that this processor is registered to handle. If a block name
         | 
| 741 | 
            +
                # is not passed as an argument, it gets read from the name property of the
         | 
| 742 | 
            +
                # BlockProcessor instance. If a name still cannot be determined, an error
         | 
| 743 | 
            +
                # is raised.
         | 
| 744 | 
            +
                # 
         | 
| 745 | 
            +
                # Examples
         | 
| 746 | 
            +
                #
         | 
| 747 | 
            +
                #   # as a BlockProcessor subclass
         | 
| 748 | 
            +
                #   block ShoutBlock
         | 
| 749 | 
            +
                #
         | 
| 750 | 
            +
                #   # as a BlockProcessor subclass with an explicit block name
         | 
| 751 | 
            +
                #   block ShoutBlock, :shout
         | 
| 752 | 
            +
                #
         | 
| 753 | 
            +
                #   # as an instance of a BlockProcessor subclass
         | 
| 754 | 
            +
                #   block ShoutBlock.new
         | 
| 755 | 
            +
                #
         | 
| 756 | 
            +
                #   # as an instance of a BlockProcessor subclass with an explicit block name
         | 
| 757 | 
            +
                #   block ShoutBlock.new, :shout
         | 
| 758 | 
            +
                #
         | 
| 759 | 
            +
                #   # as a name of a BlockProcessor subclass
         | 
| 760 | 
            +
                #   block 'ShoutBlock'
         | 
| 761 | 
            +
                #
         | 
| 762 | 
            +
                #   # as a name of a BlockProcessor subclass with an explicit block name
         | 
| 763 | 
            +
                #   block 'ShoutBlock', :shout
         | 
| 764 | 
            +
                #
         | 
| 765 | 
            +
                #   # as a method block
         | 
| 766 | 
            +
                #   block do
         | 
| 767 | 
            +
                #     named :shout 
         | 
| 768 | 
            +
                #     process |parent, reader, attrs|
         | 
| 769 | 
            +
                #       ...
         | 
| 770 | 
            +
                #     end
         | 
| 771 | 
            +
                #   end
         | 
| 772 | 
            +
                #
         | 
| 773 | 
            +
                #   # as a method block with an explicit block name
         | 
| 774 | 
            +
                #   register :shout do
         | 
| 775 | 
            +
                #     process |parent, reader, attrs|
         | 
| 776 | 
            +
                #       ...
         | 
| 777 | 
            +
                #     end
         | 
| 778 | 
            +
                #   end
         | 
| 779 | 
            +
                #
         | 
| 780 | 
            +
                # Returns an instance of the [Extension] proxy object that is stored in the
         | 
| 781 | 
            +
                # registry and manages the instance of this BlockProcessor.
         | 
| 782 | 
            +
                def block *args, &block
         | 
| 783 | 
            +
                  add_syntax_processor :block, args, &block
         | 
| 270 784 | 
             
                end
         | 
| 271 785 |  | 
| 272 | 
            -
                 | 
| 273 | 
            -
             | 
| 274 | 
            -
             | 
| 275 | 
            -
             | 
| 786 | 
            +
                # Public: Checks whether any {BlockProcessor} extensions have been registered.
         | 
| 787 | 
            +
                #
         | 
| 788 | 
            +
                # Returns a [Boolean] indicating whether any BlockProcessor extensions are registered.
         | 
| 789 | 
            +
                def blocks?
         | 
| 790 | 
            +
                  !!@block_extensions
         | 
| 276 791 | 
             
                end
         | 
| 277 | 
            -
              end
         | 
| 278 792 |  | 
| 279 | 
            -
             | 
| 280 | 
            -
                 | 
| 281 | 
            -
             | 
| 793 | 
            +
                # Public: Checks whether any {BlockProcessor} extensions are registered to
         | 
| 794 | 
            +
                # handle the specified block name appearing on the specified context.
         | 
| 795 | 
            +
                #
         | 
| 796 | 
            +
                # Returns the [Extension] proxy object for the BlockProcessor that matches
         | 
| 797 | 
            +
                # the block name and context or false if no match is found.
         | 
| 798 | 
            +
                def registered_for_block? name, context
         | 
| 799 | 
            +
                  if (ext = @block_extensions[name.to_sym])
         | 
| 800 | 
            +
                    (ext.config[:contexts].include? context) ? ext : false
         | 
| 801 | 
            +
                  else
         | 
| 802 | 
            +
                    false
         | 
| 803 | 
            +
                  end
         | 
| 282 804 | 
             
                end
         | 
| 283 | 
            -
              end
         | 
| 284 805 |  | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
              #
         | 
| 288 | 
            -
              # Prior to invoking the preprocessor, Asciidoctor splits the source text into
         | 
| 289 | 
            -
              # lines and normalizes them. The normalize process strips trailing whitespace
         | 
| 290 | 
            -
              # from each line and leaves behind a line-feed character (i.e., "\n").
         | 
| 291 | 
            -
              #
         | 
| 292 | 
            -
              # Asciidoctor passes a reference to the Reader and a copy of the lines Array
         | 
| 293 | 
            -
              # to the process method of an instance of each registered Preprocessor. The
         | 
| 294 | 
            -
              # Preprocessor modifies the Array as necessary and either returns a reference
         | 
| 295 | 
            -
              # to the same Reader or a reference to a new one.
         | 
| 296 | 
            -
              #
         | 
| 297 | 
            -
              # Preprocessors must extend Asciidoctor::Extensions::Preprocessor.
         | 
| 298 | 
            -
              class Preprocessor < Processor
         | 
| 299 | 
            -
                # Public: Accepts the Reader and an Array of lines, modifies them as
         | 
| 300 | 
            -
                # needed, then returns the Reader or a reference to a new one.
         | 
| 806 | 
            +
                # Public: Retrieves the {Extension} proxy object for the BlockProcessor registered
         | 
| 807 | 
            +
                # to handle block content with the name.
         | 
| 301 808 | 
             
                #
         | 
| 302 | 
            -
                #  | 
| 303 | 
            -
                 | 
| 304 | 
            -
             | 
| 809 | 
            +
                # name - the String or Symbol (coersed to a Symbol) macro name
         | 
| 810 | 
            +
                #
         | 
| 811 | 
            +
                # Returns the [Extension] object stored in the registry that proxies the
         | 
| 812 | 
            +
                # corresponding BlockProcessor or nil if a match is not found.
         | 
| 813 | 
            +
                def find_block_extension name
         | 
| 814 | 
            +
                  @block_extensions[name.to_sym]
         | 
| 305 815 | 
             
                end
         | 
| 306 | 
            -
              end
         | 
| 307 816 |  | 
| 308 | 
            -
             | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 311 | 
            -
             | 
| 312 | 
            -
             | 
| 313 | 
            -
             | 
| 314 | 
            -
             | 
| 315 | 
            -
             | 
| 316 | 
            -
             | 
| 317 | 
            -
             | 
| 318 | 
            -
             | 
| 319 | 
            -
                 | 
| 817 | 
            +
                # Public: Registers a {BlockMacroProcessor} with the extension registry to
         | 
| 818 | 
            +
                # process a block macro with the specified name.
         | 
| 819 | 
            +
                #
         | 
| 820 | 
            +
                # The BlockMacroProcessor may be one of four types:
         | 
| 821 | 
            +
                #
         | 
| 822 | 
            +
                # * A BlockMacroProcessor subclass
         | 
| 823 | 
            +
                # * An instance of a BlockMacroProcessor subclass
         | 
| 824 | 
            +
                # * The String name of a BlockMacroProcessor subclass
         | 
| 825 | 
            +
                # * A method block (i.e., Proc) that conforms to the BlockMacroProcessor contract
         | 
| 826 | 
            +
                #
         | 
| 827 | 
            +
                # Unless the BlockMacroProcessor is passed as the method block, it must be
         | 
| 828 | 
            +
                # the first argument to this method. The second argument is the name
         | 
| 829 | 
            +
                # (coersed to a Symbol) of the AsciiDoc block macro that this processor is
         | 
| 830 | 
            +
                # registered to handle. If a block macro name is not passed as an argument,
         | 
| 831 | 
            +
                # it gets read from the name property of the BlockMacroProcessor instance.
         | 
| 832 | 
            +
                # If a name still cannot be determined, an error is raised.
         | 
| 833 | 
            +
                # 
         | 
| 834 | 
            +
                # Examples
         | 
| 835 | 
            +
                #
         | 
| 836 | 
            +
                #   # as a BlockMacroProcessor subclass
         | 
| 837 | 
            +
                #   block GistBlockMacro
         | 
| 838 | 
            +
                #
         | 
| 839 | 
            +
                #   # as a BlockMacroProcessor subclass with an explicit macro name
         | 
| 840 | 
            +
                #   block GistBlockMacro, :gist
         | 
| 841 | 
            +
                #
         | 
| 842 | 
            +
                #   # as an instance of a BlockMacroProcessor subclass
         | 
| 843 | 
            +
                #   block GistBlockMacro.new
         | 
| 844 | 
            +
                #
         | 
| 845 | 
            +
                #   # as an instance of a BlockMacroProcessor subclass with an explicit macro name
         | 
| 846 | 
            +
                #   block GistBlockMacro.new, :gist
         | 
| 847 | 
            +
                #
         | 
| 848 | 
            +
                #   # as a name of a BlockMacroProcessor subclass
         | 
| 849 | 
            +
                #   block 'GistBlockMacro'
         | 
| 850 | 
            +
                #
         | 
| 851 | 
            +
                #   # as a name of a BlockMacroProcessor subclass with an explicit macro name
         | 
| 852 | 
            +
                #   block 'GistBlockMacro', :gist
         | 
| 853 | 
            +
                #
         | 
| 854 | 
            +
                #   # as a method block
         | 
| 855 | 
            +
                #   block_macro do
         | 
| 856 | 
            +
                #     named :gist
         | 
| 857 | 
            +
                #     process |parent, target, attrs|
         | 
| 858 | 
            +
                #       ...
         | 
| 859 | 
            +
                #     end
         | 
| 860 | 
            +
                #   end
         | 
| 861 | 
            +
                #
         | 
| 862 | 
            +
                #   # as a method block with an explicit macro name
         | 
| 863 | 
            +
                #   register :gist do
         | 
| 864 | 
            +
                #     process |parent, target, attrs|
         | 
| 865 | 
            +
                #       ...
         | 
| 866 | 
            +
                #     end
         | 
| 867 | 
            +
                #   end
         | 
| 868 | 
            +
                #
         | 
| 869 | 
            +
                # Returns an instance of the [Extension] proxy object that is stored in the
         | 
| 870 | 
            +
                # registry and manages the instance of this BlockMacroProcessor.
         | 
| 871 | 
            +
                def block_macro *args, &block
         | 
| 872 | 
            +
                  add_syntax_processor :block_macro, args, &block
         | 
| 320 873 | 
             
                end
         | 
| 321 | 
            -
              end
         | 
| 322 874 |  | 
| 323 | 
            -
             | 
| 324 | 
            -
             | 
| 325 | 
            -
             | 
| 326 | 
            -
             | 
| 327 | 
            -
             | 
| 328 | 
            -
              # necessary and returns the String replacement.
         | 
| 329 | 
            -
              #
         | 
| 330 | 
            -
              # The markup format in the String is determined from the backend used to
         | 
| 331 | 
            -
              # render the Document. The backend and be looked up using the backend method
         | 
| 332 | 
            -
              # on the Document object, as well as various backend-related document
         | 
| 333 | 
            -
              # attributes.
         | 
| 334 | 
            -
              #
         | 
| 335 | 
            -
              # Postprocessors can also be used to relocate assets needed by the published
         | 
| 336 | 
            -
              # document.
         | 
| 337 | 
            -
              #
         | 
| 338 | 
            -
              # Postprocessors must extend Asciidoctor::Extensions::Postprocessor.
         | 
| 339 | 
            -
              class Postprocessor < Processor
         | 
| 340 | 
            -
                def process output
         | 
| 341 | 
            -
                  output
         | 
| 875 | 
            +
                # Public: Checks whether any {BlockMacroProcessor} extensions have been registered.
         | 
| 876 | 
            +
                #
         | 
| 877 | 
            +
                # Returns a [Boolean] indicating whether any BlockMacroProcessor extensions are registered.
         | 
| 878 | 
            +
                def block_macros?
         | 
| 879 | 
            +
                  !!@block_macro_extensions
         | 
| 342 880 | 
             
                end
         | 
| 343 | 
            -
              end
         | 
| 344 881 |  | 
| 345 | 
            -
             | 
| 346 | 
            -
             | 
| 347 | 
            -
             | 
| 348 | 
            -
             | 
| 349 | 
            -
             | 
| 350 | 
            -
             | 
| 351 | 
            -
             | 
| 352 | 
            -
             | 
| 353 | 
            -
             | 
| 354 | 
            -
             | 
| 355 | 
            -
             | 
| 356 | 
            -
                  output
         | 
| 882 | 
            +
                # Public: Checks whether any {BlockMacroProcessor} extensions are registered to
         | 
| 883 | 
            +
                # handle the block macro with the specified name.
         | 
| 884 | 
            +
                #
         | 
| 885 | 
            +
                # name - the String or Symbol (coersed to a Symbol) macro name
         | 
| 886 | 
            +
                #
         | 
| 887 | 
            +
                # Returns the [Extension] proxy object for the BlockMacroProcessor that matches
         | 
| 888 | 
            +
                # the macro name or false if no match is found.
         | 
| 889 | 
            +
                #--
         | 
| 890 | 
            +
                # TODO only allow blank target if format is :short
         | 
| 891 | 
            +
                def registered_for_block_macro? name
         | 
| 892 | 
            +
                  (ext = @block_macro_extensions[name.to_sym]) ? ext : false
         | 
| 357 893 | 
             
                end
         | 
| 358 | 
            -
              end
         | 
| 359 894 |  | 
| 360 | 
            -
             | 
| 361 | 
            -
             | 
| 362 | 
            -
             | 
| 363 | 
            -
             | 
| 364 | 
            -
             | 
| 365 | 
            -
             | 
| 366 | 
            -
             | 
| 367 | 
            -
                 | 
| 368 | 
            -
                   | 
| 369 | 
            -
             | 
| 370 | 
            -
                  end
         | 
| 895 | 
            +
                # Public: Retrieves the {Extension} proxy object for the BlockMacroProcessor registered
         | 
| 896 | 
            +
                # to handle a block macro with the specified name.
         | 
| 897 | 
            +
                #
         | 
| 898 | 
            +
                # name - the String or Symbol (coersed to a Symbol) macro name
         | 
| 899 | 
            +
                #
         | 
| 900 | 
            +
                # Returns the [Extension] object stored in the registry that proxies the
         | 
| 901 | 
            +
                # cooresponding BlockMacroProcessor or nil if a match is not found.
         | 
| 902 | 
            +
                def find_block_macro_extension name
         | 
| 903 | 
            +
                  @block_macro_extensions[name.to_sym]
         | 
| 904 | 
            +
                end
         | 
| 371 905 |  | 
| 372 | 
            -
             | 
| 373 | 
            -
             | 
| 374 | 
            -
             | 
| 906 | 
            +
                # Public: Registers a {InlineMacroProcessor} with the extension registry to
         | 
| 907 | 
            +
                # process an inline macro with the specified name.
         | 
| 908 | 
            +
                #
         | 
| 909 | 
            +
                # The InlineMacroProcessor may be one of four types:
         | 
| 910 | 
            +
                #
         | 
| 911 | 
            +
                # * An InlineMacroProcessor subclass
         | 
| 912 | 
            +
                # * An instance of an InlineMacroProcessor subclass
         | 
| 913 | 
            +
                # * The String name of an InlineMacroProcessor subclass
         | 
| 914 | 
            +
                # * A method block (i.e., Proc) that conforms to the InlineMacroProcessor contract
         | 
| 915 | 
            +
                #
         | 
| 916 | 
            +
                # Unless the InlineMacroProcessor is passed as the method block, it must be
         | 
| 917 | 
            +
                # the first argument to this method. The second argument is the name
         | 
| 918 | 
            +
                # (coersed to a Symbol) of the AsciiDoc block macro that this processor is
         | 
| 919 | 
            +
                # registered to handle. If a block macro name is not passed as an argument,
         | 
| 920 | 
            +
                # it gets read from the name property of the InlineMacroProcessor instance.
         | 
| 921 | 
            +
                # If a name still cannot be determined, an error is raised.
         | 
| 922 | 
            +
                # 
         | 
| 923 | 
            +
                # Examples
         | 
| 924 | 
            +
                #
         | 
| 925 | 
            +
                #   # as an InlineMacroProcessor subclass
         | 
| 926 | 
            +
                #   block ChromeInlineMacro
         | 
| 927 | 
            +
                #
         | 
| 928 | 
            +
                #   # as an InlineMacroProcessor subclass with an explicit macro name
         | 
| 929 | 
            +
                #   block ChromeInineMacro, :chrome
         | 
| 930 | 
            +
                #
         | 
| 931 | 
            +
                #   # as an instance of an InlineMacroProcessor subclass
         | 
| 932 | 
            +
                #   block ChromeInlineMacro.new
         | 
| 933 | 
            +
                #
         | 
| 934 | 
            +
                #   # as an instance of an InlineMacroProcessor subclass with an explicit macro name
         | 
| 935 | 
            +
                #   block ChromeInlineMacro.new, :chrome
         | 
| 936 | 
            +
                #
         | 
| 937 | 
            +
                #   # as a name of an InlineMacroProcessor subclass
         | 
| 938 | 
            +
                #   block 'ChromeInlineMacro'
         | 
| 939 | 
            +
                #
         | 
| 940 | 
            +
                #   # as a name of an InlineMacroProcessor subclass with an explicit macro name
         | 
| 941 | 
            +
                #   block 'ChromeInineMacro', :chrome
         | 
| 942 | 
            +
                #
         | 
| 943 | 
            +
                #   # as a method block
         | 
| 944 | 
            +
                #   inline_macro do
         | 
| 945 | 
            +
                #     named :chrome
         | 
| 946 | 
            +
                #     process |parent, target, attrs|
         | 
| 947 | 
            +
                #       ...
         | 
| 948 | 
            +
                #     end
         | 
| 949 | 
            +
                #   end
         | 
| 950 | 
            +
                #
         | 
| 951 | 
            +
                #   # as a method block with an explicit macro name
         | 
| 952 | 
            +
                #   register :chrome do
         | 
| 953 | 
            +
                #     process |parent, target, attrs|
         | 
| 954 | 
            +
                #       ...
         | 
| 955 | 
            +
                #     end
         | 
| 956 | 
            +
                #   end
         | 
| 957 | 
            +
                #
         | 
| 958 | 
            +
                # Returns an instance of the [Extension] proxy object that is stored in the
         | 
| 959 | 
            +
                # registry and manages the instance of this InlineMacroProcessor.
         | 
| 960 | 
            +
                def inline_macro *args, &block
         | 
| 961 | 
            +
                  add_syntax_processor :inline_macro, args, &block
         | 
| 375 962 | 
             
                end
         | 
| 376 963 |  | 
| 377 | 
            -
                 | 
| 378 | 
            -
                 | 
| 379 | 
            -
                 | 
| 964 | 
            +
                # Public: Checks whether any {InlineMacroProcessor} extensions have been registered.
         | 
| 965 | 
            +
                #
         | 
| 966 | 
            +
                # Returns a [Boolean] indicating whether any IncludeMacroProcessor extensions are registered.
         | 
| 967 | 
            +
                def inline_macros?
         | 
| 968 | 
            +
                  !!@inline_macro_extensions
         | 
| 969 | 
            +
                end
         | 
| 380 970 |  | 
| 381 | 
            -
                 | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 384 | 
            -
             | 
| 385 | 
            -
             | 
| 386 | 
            -
             | 
| 387 | 
            -
             | 
| 388 | 
            -
             | 
| 971 | 
            +
                # Public: Checks whether any {InlineMacroProcessor} extensions are registered to
         | 
| 972 | 
            +
                # handle the inline macro with the specified name.
         | 
| 973 | 
            +
                #
         | 
| 974 | 
            +
                # name - the String or Symbol (coersed to a Symbol) macro name
         | 
| 975 | 
            +
                #
         | 
| 976 | 
            +
                # Returns the [Extension] proxy object for the InlineMacroProcessor that matches
         | 
| 977 | 
            +
                # the macro name or false if no match is found.
         | 
| 978 | 
            +
                def registered_for_inline_macro? name
         | 
| 979 | 
            +
                  (ext = @inline_macro_extensions[name.to_sym]) ? ext : false
         | 
| 389 980 | 
             
                end
         | 
| 390 981 |  | 
| 391 | 
            -
                 | 
| 392 | 
            -
             | 
| 982 | 
            +
                # Public: Retrieves the {Extension} proxy object for the InlineMacroProcessor registered
         | 
| 983 | 
            +
                # to handle an inline macro with the specified name.
         | 
| 984 | 
            +
                #
         | 
| 985 | 
            +
                # name - the String or Symbol (coersed to a Symbol) macro name
         | 
| 986 | 
            +
                #
         | 
| 987 | 
            +
                # Returns the [Extension] object stored in the registry that proxies the
         | 
| 988 | 
            +
                # cooresponding InlineMacroProcessor or nil if a match is not found.
         | 
| 989 | 
            +
                def find_inline_macro_extension name
         | 
| 990 | 
            +
                  @inline_macro_extensions[name.to_sym]
         | 
| 393 991 | 
             
                end
         | 
| 394 | 
            -
              end
         | 
| 395 992 |  | 
| 396 | 
            -
             | 
| 397 | 
            -
                 | 
| 398 | 
            -
             | 
| 399 | 
            -
             | 
| 993 | 
            +
                # Public: Retrieves the {Extension} proxy objects for all
         | 
| 994 | 
            +
                # InlineMacroProcessor instances in this registry.
         | 
| 995 | 
            +
                #
         | 
| 996 | 
            +
                # Returns an [Array] of Extension proxy objects.
         | 
| 997 | 
            +
                def inline_macros
         | 
| 998 | 
            +
                  @inline_macro_extensions.values
         | 
| 999 | 
            +
                end
         | 
| 1000 | 
            +
             | 
| 1001 | 
            +
                private
         | 
| 1002 | 
            +
             | 
| 1003 | 
            +
                def add_document_processor kind, args, &block
         | 
| 1004 | 
            +
                  kind_name = kind.to_s.tr '_', ' '
         | 
| 1005 | 
            +
                  kind_class_symbol = kind_name.split(' ').map {|word| %(#{word.chr.upcase}#{word[1..-1]}) }.join.to_sym
         | 
| 1006 | 
            +
                  kind_class = Extensions.const_get kind_class_symbol
         | 
| 1007 | 
            +
                  kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol) : nil
         | 
| 1008 | 
            +
                  kind_store = instance_variable_get(%(@#{kind}_extensions).to_sym) || instance_variable_set(%(@#{kind}_extensions).to_sym, [])
         | 
| 1009 | 
            +
                  # style 1: specified as block
         | 
| 1010 | 
            +
                  extension = if block_given?
         | 
| 1011 | 
            +
                    config = resolve_args args, 1
         | 
| 1012 | 
            +
                    # TODO if block arity is 0, assume block is process method
         | 
| 1013 | 
            +
                    processor = kind_class.new config
         | 
| 1014 | 
            +
                    class << processor
         | 
| 1015 | 
            +
                      include_dsl
         | 
| 1016 | 
            +
                    end
         | 
| 1017 | 
            +
                    processor.instance_exec(&block)
         | 
| 1018 | 
            +
                    processor.freeze
         | 
| 1019 | 
            +
                    unless processor.process_block_given?
         | 
| 1020 | 
            +
                      raise ::ArgumentError.new %(No block specified to process #{kind_name} extension at #{block.source_location})
         | 
| 1021 | 
            +
                    end
         | 
| 1022 | 
            +
                    ProcessorExtension.new kind, processor
         | 
| 1023 | 
            +
                  else
         | 
| 1024 | 
            +
                    processor, config = resolve_args args, 2
         | 
| 1025 | 
            +
                    # style 2: specified as class or class name
         | 
| 1026 | 
            +
                    if (processor.is_a? ::Class) || ((processor.is_a? ::String) && (processor = Extensions.class_for_name processor))
         | 
| 1027 | 
            +
                      unless processor < kind_class || (kind_java_class && processor < kind_java_class)
         | 
| 1028 | 
            +
                        raise ::ArgumentError.new %(Invalid type for #{kind_name} extension: #{processor})
         | 
| 1029 | 
            +
                      end
         | 
| 1030 | 
            +
                      processor_instance = processor.new config
         | 
| 1031 | 
            +
                      processor_instance.freeze
         | 
| 1032 | 
            +
                      ProcessorExtension.new kind, processor_instance
         | 
| 1033 | 
            +
                    # style 3: specified as instance
         | 
| 1034 | 
            +
                    elsif (processor.is_a? kind_class) || (kind_java_class && (processor.is_a? kind_java_class))
         | 
| 1035 | 
            +
                      processor.update_config config
         | 
| 1036 | 
            +
                      processor.freeze
         | 
| 1037 | 
            +
                      ProcessorExtension.new kind, processor
         | 
| 1038 | 
            +
                    else
         | 
| 1039 | 
            +
                      raise ::ArgumentError.new %(Invalid arguments specified for registering #{kind_name} extension: #{args})
         | 
| 1040 | 
            +
                    end
         | 
| 400 1041 | 
             
                  end
         | 
| 401 1042 |  | 
| 402 | 
            -
                   | 
| 403 | 
            -
                     | 
| 1043 | 
            +
                  if extension.config[:position] == :>>
         | 
| 1044 | 
            +
                    kind_store.unshift extension
         | 
| 1045 | 
            +
                  else
         | 
| 1046 | 
            +
                    kind_store << extension
         | 
| 404 1047 | 
             
                  end
         | 
| 405 1048 | 
             
                end
         | 
| 406 1049 |  | 
| 407 | 
            -
                 | 
| 408 | 
            -
             | 
| 409 | 
            -
             | 
| 1050 | 
            +
                def add_syntax_processor kind, args, &block
         | 
| 1051 | 
            +
                  kind_name = kind.to_s.tr '_', ' '
         | 
| 1052 | 
            +
                  kind_class_basename = kind_name.split(' ').map {|word| %(#{word.chr.upcase}#{word[1..-1]}) }.join
         | 
| 1053 | 
            +
                  kind_class_symbol = %(#{kind_class_basename}Processor).to_sym
         | 
| 1054 | 
            +
                  kind_class = Extensions.const_get kind_class_symbol
         | 
| 1055 | 
            +
                  kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol) : nil
         | 
| 1056 | 
            +
                  kind_store = instance_variable_get(%(@#{kind}_extensions).to_sym) || instance_variable_set(%(@#{kind}_extensions).to_sym, {})
         | 
| 1057 | 
            +
                  # style 1: specified as block
         | 
| 1058 | 
            +
                  if block_given?
         | 
| 1059 | 
            +
                    name, config = resolve_args args, 2
         | 
| 1060 | 
            +
                    processor = kind_class.new as_symbol(name), config
         | 
| 1061 | 
            +
                    class << processor
         | 
| 1062 | 
            +
                      include_dsl
         | 
| 1063 | 
            +
                    end
         | 
| 1064 | 
            +
                    if block.arity == 1
         | 
| 1065 | 
            +
                      yield processor
         | 
| 1066 | 
            +
                    else
         | 
| 1067 | 
            +
                      processor.instance_exec(&block)
         | 
| 1068 | 
            +
                    end
         | 
| 1069 | 
            +
                    unless (name = as_symbol processor.name)
         | 
| 1070 | 
            +
                      raise ::ArgumentError.new %(No name specified for #{kind_name} extension at #{block.source_location})
         | 
| 1071 | 
            +
                    end
         | 
| 1072 | 
            +
                    unless processor.process_block_given?
         | 
| 1073 | 
            +
                      raise ::NoMethodError.new %(No block specified to process #{kind_name} extension at #{block.source_location})
         | 
| 1074 | 
            +
                    end
         | 
| 1075 | 
            +
                    processor.freeze
         | 
| 1076 | 
            +
                    kind_store[name] = ProcessorExtension.new kind, processor
         | 
| 1077 | 
            +
                  else
         | 
| 1078 | 
            +
                    processor, name, config = resolve_args args, 3
         | 
| 1079 | 
            +
                    # style 2: specified as class or class name
         | 
| 1080 | 
            +
                    if (processor.is_a? ::Class) || ((processor.is_a? ::String) && (processor = Extensions.class_for_name processor))
         | 
| 1081 | 
            +
                      unless processor < kind_class || (kind_java_class && processor < kind_java_class)
         | 
| 1082 | 
            +
                        raise ::ArgumentError.new %(Class specified for #{kind_name} extension does not inherit from #{kind_class}: #{processor})
         | 
| 1083 | 
            +
                      end
         | 
| 1084 | 
            +
                      processor_instance = processor.new as_symbol(name), config
         | 
| 1085 | 
            +
                      unless (name = as_symbol processor_instance.name)
         | 
| 1086 | 
            +
                        raise ::ArgumentError.new %(No name specified for #{kind_name} extension: #{processor})
         | 
| 1087 | 
            +
                      end
         | 
| 1088 | 
            +
                      processor.freeze
         | 
| 1089 | 
            +
                      kind_store[name] = ProcessorExtension.new kind, processor_instance
         | 
| 1090 | 
            +
                    # style 3: specified as instance
         | 
| 1091 | 
            +
                    elsif (processor.is_a? kind_class) || (kind_java_class && (processor.is_a? kind_java_class))
         | 
| 1092 | 
            +
                      processor.update_config config
         | 
| 1093 | 
            +
                      # TODO need a test for this override!
         | 
| 1094 | 
            +
                      unless (name = name ? (processor.name = as_symbol name) : (as_symbol processor.name))
         | 
| 1095 | 
            +
                        raise ::ArgumentError.new %(No name specified for #{kind_name} extension: #{processor})
         | 
| 1096 | 
            +
                      end
         | 
| 1097 | 
            +
                      processor.freeze
         | 
| 1098 | 
            +
                      kind_store[name] = ProcessorExtension.new kind, processor
         | 
| 1099 | 
            +
                    else
         | 
| 1100 | 
            +
                      raise ::ArgumentError.new %(Invalid arguments specified for registering #{kind_name} extension: #{args})
         | 
| 1101 | 
            +
                    end
         | 
| 1102 | 
            +
                  end
         | 
| 1103 | 
            +
                end
         | 
| 410 1104 |  | 
| 411 | 
            -
                def  | 
| 412 | 
            -
                   | 
| 413 | 
            -
                   | 
| 414 | 
            -
                   | 
| 415 | 
            -
                   | 
| 1105 | 
            +
                def resolve_args args, expect
         | 
| 1106 | 
            +
                  opts = (args[-1].is_a? ::Hash) ? args.pop : {}
         | 
| 1107 | 
            +
                  return opts if expect == 1
         | 
| 1108 | 
            +
                  num_args = args.size
         | 
| 1109 | 
            +
                  if (missing = expect - 1 - num_args) > 0
         | 
| 1110 | 
            +
                    args.fill nil, num_args, missing
         | 
| 1111 | 
            +
                  elsif missing < 0
         | 
| 1112 | 
            +
                    args.pop(-missing)
         | 
| 1113 | 
            +
                  end
         | 
| 1114 | 
            +
                  args << opts
         | 
| 1115 | 
            +
                  args
         | 
| 416 1116 | 
             
                end
         | 
| 417 1117 |  | 
| 418 | 
            -
                def  | 
| 419 | 
            -
                  nil
         | 
| 1118 | 
            +
                def as_symbol name
         | 
| 1119 | 
            +
                  name ? ((name.is_a? ::Symbol) ? name : name.to_sym) : nil
         | 
| 420 1120 | 
             
                end
         | 
| 421 1121 | 
             
              end
         | 
| 422 1122 |  | 
| 423 | 
            -
              class  | 
| 424 | 
            -
             | 
| 1123 | 
            +
              class << self
         | 
| 1124 | 
            +
                def generate_name
         | 
| 1125 | 
            +
                  %(extgrp#{next_auto_id})
         | 
| 1126 | 
            +
                end
         | 
| 425 1127 |  | 
| 426 | 
            -
             | 
| 427 | 
            -
             | 
| 428 | 
            -
             | 
| 429 | 
            -
                 | 
| 430 | 
            -
             | 
| 431 | 
            -
             | 
| 1128 | 
            +
                def next_auto_id
         | 
| 1129 | 
            +
                  @auto_id ||= -1
         | 
| 1130 | 
            +
                  @auto_id += 1
         | 
| 1131 | 
            +
                end
         | 
| 1132 | 
            +
             | 
| 1133 | 
            +
                def groups
         | 
| 1134 | 
            +
                  @groups ||= {}
         | 
| 432 1135 | 
             
                end
         | 
| 433 1136 |  | 
| 434 | 
            -
                def  | 
| 435 | 
            -
                  if  | 
| 436 | 
            -
                     | 
| 1137 | 
            +
                def build_registry name = nil, &block
         | 
| 1138 | 
            +
                  if block_given?
         | 
| 1139 | 
            +
                    name ||= generate_name
         | 
| 1140 | 
            +
                    Registry.new({ name => block })
         | 
| 437 1141 | 
             
                  else
         | 
| 438 | 
            -
                     | 
| 1142 | 
            +
                    Registry.new
         | 
| 439 1143 | 
             
                  end
         | 
| 440 1144 | 
             
                end
         | 
| 1145 | 
            +
             | 
| 1146 | 
            +
                # Public: Registers an extension Group that subsequently registers a
         | 
| 1147 | 
            +
                # collection of extensions.
         | 
| 1148 | 
            +
                #
         | 
| 1149 | 
            +
                # Registers the extension Group specified under the given name. If a name is
         | 
| 1150 | 
            +
                # not given, one is calculated by appending the next value in a 0-based
         | 
| 1151 | 
            +
                # index to the string "extgrp". For instance, the first unnamed extension
         | 
| 1152 | 
            +
                # group to be registered is assigned the name "extgrp0" if a name is not
         | 
| 1153 | 
            +
                # specified.
         | 
| 1154 | 
            +
                #
         | 
| 1155 | 
            +
                # The names are not yet used, but are intended for selectively activating
         | 
| 1156 | 
            +
                # extensions in the future.
         | 
| 1157 | 
            +
                #
         | 
| 1158 | 
            +
                # If the extension group argument is a String or a Symbol, it gets resolved
         | 
| 1159 | 
            +
                # to a Class before being registered.
         | 
| 1160 | 
            +
                #
         | 
| 1161 | 
            +
                # name    - The name under which this extension group is registered (optional, default: nil)
         | 
| 1162 | 
            +
                # group   - A block (Proc), a Class, a String or Symbol name of a Class or
         | 
| 1163 | 
            +
                #           an Object instance of a Class.
         | 
| 1164 | 
            +
                #
         | 
| 1165 | 
            +
                # Examples
         | 
| 1166 | 
            +
                #
         | 
| 1167 | 
            +
                #   Asciidoctor::Extensions.register UmlExtensions
         | 
| 1168 | 
            +
                #
         | 
| 1169 | 
            +
                #   Asciidoctor::Extensions.register :uml, UmlExtensions
         | 
| 1170 | 
            +
                #
         | 
| 1171 | 
            +
                #   Asciidoctor::Extensions.register do
         | 
| 1172 | 
            +
                #     block_processor :plantuml, PlantUmlBlock
         | 
| 1173 | 
            +
                #   end
         | 
| 1174 | 
            +
                #
         | 
| 1175 | 
            +
                #   Asciidoctor::Extensions.register :uml do
         | 
| 1176 | 
            +
                #     block_processor :plantuml, PlantUmlBlock
         | 
| 1177 | 
            +
                #   end
         | 
| 1178 | 
            +
                #
         | 
| 1179 | 
            +
                # Returns the [Proc, Class or Object] instance, matching the type passed to this method.
         | 
| 1180 | 
            +
                def register *args, &block
         | 
| 1181 | 
            +
                  argc = args.length
         | 
| 1182 | 
            +
                  resolved_group = if block_given?
         | 
| 1183 | 
            +
                    block
         | 
| 1184 | 
            +
                  elsif !(group = args.pop)
         | 
| 1185 | 
            +
                    raise ::ArgumentError.new %(Extension group to register not specified)
         | 
| 1186 | 
            +
                  else
         | 
| 1187 | 
            +
                    # QUESTION should we instantiate the group class here or defer until
         | 
| 1188 | 
            +
                    # activation??
         | 
| 1189 | 
            +
                    case group
         | 
| 1190 | 
            +
                    when ::Class
         | 
| 1191 | 
            +
                      group
         | 
| 1192 | 
            +
                    when ::String
         | 
| 1193 | 
            +
                      class_for_name group
         | 
| 1194 | 
            +
                    when ::Symbol
         | 
| 1195 | 
            +
                      class_for_name group.to_s
         | 
| 1196 | 
            +
                    else
         | 
| 1197 | 
            +
                      group
         | 
| 1198 | 
            +
                    end
         | 
| 1199 | 
            +
                  end
         | 
| 1200 | 
            +
                  name = args.pop || generate_name
         | 
| 1201 | 
            +
                  unless args.empty?
         | 
| 1202 | 
            +
                    raise ::ArgumentError.new %(Wrong number of arguments (#{argc} for 1..2))
         | 
| 1203 | 
            +
                  end
         | 
| 1204 | 
            +
                  groups[name] = resolved_group
         | 
| 1205 | 
            +
                end
         | 
| 1206 | 
            +
             | 
| 1207 | 
            +
                def unregister_all
         | 
| 1208 | 
            +
                  @groups = {}
         | 
| 1209 | 
            +
                end
         | 
| 1210 | 
            +
             | 
| 1211 | 
            +
                # unused atm, but tested
         | 
| 1212 | 
            +
                def resolve_class object
         | 
| 1213 | 
            +
                  (object.is_a? ::Class) ? object : (class_for_name object.to_s)
         | 
| 1214 | 
            +
                end
         | 
| 1215 | 
            +
             | 
| 1216 | 
            +
                # Public: Resolves the Class object for the qualified name.
         | 
| 1217 | 
            +
                #
         | 
| 1218 | 
            +
                # Returns Class
         | 
| 1219 | 
            +
                def class_for_name qualified_name
         | 
| 1220 | 
            +
                  resolved_class = ::Object
         | 
| 1221 | 
            +
                  qualified_name.split('::').each do |name|
         | 
| 1222 | 
            +
                    if name.empty?
         | 
| 1223 | 
            +
                      # do nothing
         | 
| 1224 | 
            +
                    elsif resolved_class.const_defined? name
         | 
| 1225 | 
            +
                      resolved_class = resolved_class.const_get name
         | 
| 1226 | 
            +
                    else
         | 
| 1227 | 
            +
                      raise %(Could not resolve class for name: #{qualified_name})
         | 
| 1228 | 
            +
                    end
         | 
| 1229 | 
            +
                  end
         | 
| 1230 | 
            +
                  resolved_class
         | 
| 1231 | 
            +
                end
         | 
| 441 1232 | 
             
              end
         | 
| 1233 | 
            +
             | 
| 442 1234 | 
             
            end
         | 
| 443 1235 | 
             
            end
         |