# File lib/asciidoctor/abstract_block.rb, line 337
  def find_by selector = {}, &block
    result = []

    if ((any_context = !(context_selector = selector[:context])) || context_selector == @context) &&
        (!(style_selector = selector[:style]) || style_selector == @style) &&
        (!(role_selector = selector[:role]) || (has_role? role_selector)) &&
        (!(id_selector = selector[:id]) || id_selector == @id)
      if id_selector
        if block_given?
          return (yield self) ? [self] : result
        else
          return [self]
        end
      elsif block_given?
        result << self if (yield self)
      else
        result << self
      end
    end

    # process document header as a section if present
    if @context == :document && (any_context || context_selector == :section) && header?
      result.concat(@header.find_by selector, &block)
    end

    unless context_selector == :document # optimization
      # yuck, dlist is a special case
      if @context == :dlist
        if any_context || context_selector != :section # optimization
          @blocks.flatten.each do |li|
            # NOTE the list item of a dlist can be nil, so we have to check
            result.concat(li.find_by selector, &block) if li
          end
        end
      elsif
        @blocks.each do |b|
          next if (context_selector == :section && b.context != :section) # optimization
          result.concat(b.find_by selector, &block)
        end
      end
    end
    result
  end