CodeRay helper for Rails

May 9, 2007

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:

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...

<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.

The 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!

Update: I'm no longer using this, as my blog has been moved to Viviti which handles syntax highlighting automatically - but all the above still works well :)

Comments

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?

Add comment

Blog Archives

Recent Comments