# File lib/asciidoctor/substitutors.rb, line 1400
  def highlight_source source, process_callouts, highlighter = nil
    case (highlighter ||= @document.attributes['source-highlighter'])
    when 'coderay'
      unless (highlighter_loaded = defined? ::CodeRay) || @document.attributes['coderay-unavailable']
        if (Helpers.require_library 'coderay', true, :warn).nil?
          # prevent further attempts to load CodeRay
          @document.set_attr 'coderay-unavailable', true
        else
          highlighter_loaded = true
        end
      end
    when 'pygments'
      unless (highlighter_loaded = defined? ::Pygments) || @document.attributes['pygments-unavailable']
        if (Helpers.require_library 'pygments', 'pygments.rb', :warn).nil?
          # prevent further attempts to load Pygments
          @document.set_attr 'pygments-unavailable', true
        else
          highlighter_loaded = true
        end
      end
    else
      # unknown highlighting library (something is misconfigured if we arrive here)
      highlighter_loaded = false
    end

    return sub_source source, process_callouts unless highlighter_loaded

    lineno = 0
    callout_on_last = false
    if process_callouts
      callout_marks = {}
      last = -1
      # FIXME cache this dynamic regex
      callout_rx = (attr? 'line-comment') ? /(?:#{::Regexp.escape(attr 'line-comment')} )?#{CalloutExtractRxt}/ : CalloutExtractRx
      # extract callout marks, indexed by line number
      source = source.split(EOL).map {|line|
        lineno = lineno + 1
        line.gsub(callout_rx) {
          # alias match for Ruby 1.8.7 compat
          m = $~
          # honor the escape
          if m[1] == '\\'
            m[0].sub('\\', '')
          else
            (callout_marks[lineno] ||= []) << m[3]
            last = lineno
            nil
          end
        }
      } * EOL
      callout_on_last = (last == lineno)
      callout_marks = nil if callout_marks.empty?
    else
      callout_marks = nil
    end

    linenums_mode = nil
    highlight_lines = nil

    case highlighter
    when 'coderay'
      if (linenums_mode = (attr? 'linenums') ? (@document.attributes['coderay-linenums-mode'] || :table).to_sym : nil)
        if attr? 'highlight', nil, false
          highlight_lines = resolve_lines_to_highlight(attr 'highlight', nil, false)
        end
      end
      result = ::CodeRay::Duo[attr('language', :text, false).to_sym, :html, {
          :css => (@document.attributes['coderay-css'] || :class).to_sym,
          :line_numbers => linenums_mode,
          :line_number_anchors => false,
          :highlight_lines => highlight_lines,
          :bold_every => false}].highlight source
    when 'pygments'
      lexer = ::Pygments::Lexer[attr('language', nil, false)] || ::Pygments::Lexer['text']
      opts = { :cssclass => 'pyhl', :classprefix => 'tok-', :nobackground => true }
      unless (@document.attributes['pygments-css'] || 'class') == 'class'
        opts[:noclasses] = true
        opts[:style] = (@document.attributes['pygments-style'] || Stylesheets::DEFAULT_PYGMENTS_STYLE)
      end
      if attr? 'highlight', nil, false
        unless (highlight_lines = resolve_lines_to_highlight(attr 'highlight', nil, false)).empty?
          opts[:hl_lines] = highlight_lines * ' '
        end
      end
      if attr? 'linenums'
        # TODO we could add the line numbers in ourselves instead of having to strip out the junk
        # FIXME move these regular expressions into constants
        if (opts[:linenos] = @document.attributes['pygments-linenums-mode'] || 'table') == 'table'
          linenums_mode = :table
          # NOTE these subs clean out HTML that messes up our styles
          result = lexer.highlight(source, :options => opts).
              sub(/<div class="pyhl">(.*)<\/div>/m, '\1').
              gsub(/<pre[^>]*>(.*?)<\/pre>\s*/m, '\1')
        else
          result = lexer.highlight(source, :options => opts).
              sub(/<div class="pyhl"><pre[^>]*>(.*?)<\/pre><\/div>/m, '\1')
        end
      else
        # nowrap gives us just the highlighted source; won't work when we need linenums though
        opts[:nowrap] = true
        result = lexer.highlight(source, :options => opts)
      end
    end

    # fix passthrough placeholders that got caught up in syntax highlighting
    unless @passthroughs.empty?
      result = result.gsub PASS_MATCH_HI, %(#{PASS_START}\\1#{PASS_END})
    end

    if process_callouts && callout_marks
      lineno = 0
      reached_code = linenums_mode != :table
      result.split(EOL).map {|line|
        unless reached_code
          unless line.include?('<td class="code">')
            next line
          end
          reached_code = true
        end
        lineno = lineno + 1
        if (conums = callout_marks.delete(lineno))
          tail = nil
          if callout_on_last && callout_marks.empty?
            # QUESTION when does this happen?
            if (pos = line.index '</pre>')
              tail = line[pos..-1]
              line = %(#{line[0...pos].chomp ' '} )
            else
              # Give conum on final line breathing room if trailing space in source is dropped
              line = %(#{line.chomp ' '} )
            end
          end
          if conums.size == 1
            %(#{line}#{Inline.new(self, :callout, conums[0], :id => @document.callouts.read_next_id).convert }#{tail})
          else
            conums_markup = conums.map {|conum| Inline.new(self, :callout, conum, :id => @document.callouts.read_next_id).convert } * ' '
            %(#{line}#{conums_markup}#{tail})
          end
        else
          line
        end
      } * EOL
    else
      result
    end
  end