# codecloth.rb
# By Nathan Weizenbaum (http://nex3.leeweiz.net)
# MIT License (http://www.opensource.org/licenses/mit-license.php)
#
# Integrating CodeRay syntax highlighting with RedCloth.
# Check out http://nex3.leeweiz.net/posts/31-a-solution-to-the-syntax-highlighting-problem
require 'rubygems'
require 'redcloth'
require 'coderay'
module CodeCloth
HTML_OPTIONS = { :wrap => :div }
def self.included(other)
other::BASIC_TAGS['span'] = ['class']
other::BASIC_TAGS['div'] = ['class']
other::BASIC_TAGS['codeclothpre'] = nil
other::DEFAULT_RULES.insert 0, :block_syntax_set
other.send :alias_method, :to_html_without_syntax, :to_html
other.send :alias_method, :to_html, :to_html_with_syntax
other.send :alias_method, :initialize_without_scanner, :initialize
other.send :alias_method, :initialize, :initialize_with_scanner
end
def initialize_with_scanner(*whatever)
initialize_without_scanner(*whatever)
@scanner = CodeRay::Scanners['plain']
end
def block_syntax_set(text)
return nil if text[0] != ?$
syntax, rest = text.split "\n", 2
syntax.slice! 0
syntax.strip!
syntax.downcase!
scanner = CodeRay::Scanners[syntax.empty? ? 'plain' : syntax]
if rest.nil?
@scanner = scanner
text.replace('')
else
text.replace rest.gsub(/^#{'\s' * rest.index(/[^\s]/)}/, '')
blocks text, true
syntaxify text, scanner
end
end
def to_html_with_syntax(*whatever)
unescape_pre syntaxify(syntaxify_manual_html(to_html_without_syntax(*whatever)), @scanner)
end
private
SYNTAXLESS_CODE_RE = /(?:)?(.*?)(?:<\/code>)?<\/pre>/m
def syntaxify(text, scanner)
text.gsub!(SYNTAXLESS_CODE_RE) do
escape_pre scanner.new($1).tokenize.html(HTML_OPTIONS)
end
text
end
MANUAL_HTML_RE = /^\$([^\n]+)\n(#{SYNTAXLESS_CODE_RE})/
def syntaxify_manual_html(text)
text.gsub!(MANUAL_HTML_RE) do
syntaxify $2, CodeRay::Scanners[$1.strip.downcase]
end
text
end
def escape_pre(text)
text.gsub(/<(\/?)pre>/, '<\1codeclothpre>')
end
def unescape_pre(text)
text.gsub(/<(\/?)codeclothpre>/, '<\1pre>')
end
end
RedCloth.send :include, CodeCloth