CodeRay helper for Rails
May 10th, 2007 | 5 comments
While I'm using Markdown for formatting blog entries, I wanted to have some decent syntax highlighting support as well. After looking around I decided to use CodeRay. It's fast, customizable, has nice output, and is easy to extend.
All I had to do to make it work with Rails was to create a helper. I wanted to have a simple syntax so I could do stuff like:
<code:ruby> ... code here ... </code>
The helper isn't very complicated:
1 2 3 4 5 6 |
def parse_coderay(text) text.scan(/(<code\:([a-z].+?)>(.+?)<\/code>)/m).each do |match| text.gsub!(match[0],CodeRay.scan(match[2], match[1].to_sym).div( :line_numbers => :table,:css => :class)) end return text end |
Then to add the CSS, I added this to my main layout:
style { CodeRay::Encoders[:html]::CSS.new(:jerrett).stylesheet } |
or for non-markaby users...
1 2 3 |
<style> <%= CodeRay::Encoders[:html]::CSS.new(:jerrett).stylesheet %> </style> |
If you call CSS.new without an argument it will use the default style, which is almost identical to the one I'm using here. I just changed a few colors to make it fit the site better. In the coderay/styles/ directory are two ruby files, cycnus.rb and murphy.rb - these define the CSS styles. By default it will use cycnus, and murphy is a black-based theme. Easiest way to make a new theme is just copy one of the existing to a new .rb file, and tweak.
The only thing missing was JavaScript syntax highlighting support, by I found a pastie by Josh Goebel of a JavaScript CodeRay Scanner
All you need to do is add that to a javascript.rb file in the coderay/scanners folder, and viola, JavaScript support!
Seriously useful stuff! All the suggestions on how to do this I've seen so far has been 50-liners. This rocks.
Great tutorial! If you want to prevent the parser from adding a blank line of code to the beginning of every code block, add the following line to the helper (right before text.gsub!)
match[1] = match[1][2..match[1].length] if match[1][0..1].match(/\n/)
Rather, that's
match[2] = match[2][2..match[2].length] if match[2][0..1].match(/\n/)
forgot that I had modified the helper already ;)
What about blank lines at the end of every code block?
An easier way to get rid of the lines is to use match[2].strip on line 3, thats it!