How I syntax highlight code in this blog. CodeRay + regular expressions.
I’m using this app-only plugin called cache_html. It lets me do this:
class Post < ActiveRecord::Base
cache_html :intro, :content
end
This runs some parsing – textile and coderay – on that content, and stores it in [column_name]_html. Honestly, that’s kind of useless, as this app is using page caching, but oh well. Even the RSS feed is page cached, yawn.
So, the cache_html
does it’s thing before_save
, and this is one of the things:
def coderay(text)
duped = text.dup
expression = /(<source(?:\:([a-z]+))?>(.+?)<\/source>)/m
text.scan(expression) do |all, language, code|
language ||= :ruby
if (code.scan(/\n/)).empty? # has no newlines?
highlighted = '<span class="inline_code">'
highlighted += CodeRay.scan(code, language.to_sym).div(:wrap => nil, :css => :class)
highlighted += '</span>'
else
code.strip!
highlighted = CodeRay.scan(code, language.to_sym).div(:css => :class)
end
duped.gsub!(all, "<notextile>#{highlighted}</notextile>")
end
duped
end
There ya go. Some notes:
- It’s dirty. This is strictly
ActionView
stuff. I should have usedcontent_tag
and all sorts of neat helpers, but I can’t do that, as I’m in theActiveRecord
scope. - It’s looking for <source> tags, and highlights that. I can also go <source:language>. It’s Ruby by default.
- I’m doing
dup
because a string can’t modify (gsub
) itself inside ascan
block. - It scans the content for newlines. If there’s no newlines around, it’s considered an in-line code sample.
- <notextile> makes sure textile doesn’t parse the code samples (that’d be rather silly)