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?
@document.set_attr 'coderay-unavailable'
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?
@document.set_attr 'pygments-unavailable'
else
highlighter_loaded = true
end
end
else
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
callout_rx = (attr? 'line-comment') ? /(?:#{::Regexp.escape(attr 'line-comment')} )?#{CalloutExtractRxt}/ : CalloutExtractRx
source = source.split(LF, -1).map {|line|
lineno = lineno + 1
line.gsub(callout_rx) {
m = $~
if m[1] == RS
m[0].sub RS, ''
else
(callout_marks[lineno] ||= []) << m[3]
last = lineno
nil
end
}
} * LF
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', nil, false) ? (@document.attributes['coderay-linenums-mode'] || :table).to_sym : nil)
if attr? 'highlight', nil, false
highlight_lines = resolve_highlight_lines(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.find_by_alias(attr 'language', 'text', false) || ::Pygments::Lexer.find_by_mimetype('text/plain')
opts = { :cssclass => 'pyhl', :classprefix => 'tok-', :nobackground => true, :stripnl => false }
opts[:startinline] = !(option? 'mixed') if lexer.name == 'PHP'
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_highlight_lines(attr 'highlight', nil, false)).empty?
opts[:hl_lines] = highlight_lines * ' '
end
end
if (attr? 'linenums', nil, false) && (opts[:linenos] = @document.attributes['pygments-linenums-mode'] || 'table') == 'table'
linenums_mode = :table
result = lexer.highlight(source, :options => opts).sub(PygmentsWrapperDivRx, '\1').gsub(PygmentsWrapperPreRx, '\1')
else
if PygmentsWrapperPreRx =~ (result = lexer.highlight(source, :options => opts))
result = $1
end
end
end
unless @passthroughs.empty?
result = result.gsub HighlightedPassSlotRx, %(#{PASS_START}\\1#{PASS_END})
end
if process_callouts && callout_marks
lineno = 0
reached_code = linenums_mode != :table
result.split(LF, -1).map {|line|
unless reached_code
next line unless line.include?('<td class="code">')
reached_code = true
end
lineno += 1
if (conums = callout_marks.delete(lineno))
tail = nil
if callout_on_last && callout_marks.empty? && linenums_mode == :table
if highlighter == 'coderay' && (pos = line.index '</pre>')
line, tail = (line.slice 0, pos), (line.slice pos, line.length)
elsif highlighter == 'pygments' && (pos = line.start_with? '</td>')
line, tail = '', line
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
} * LF
else
result
end
end