If you are like me you are easily allured by any type of programming eye candy and enjoy syntax highlighting a lot. My natural choices for stitching highlighting support to this wannabe blog were limited to these:
- Syntax
- Ultraviolet
- CodeRay
- SyntaxHighligher and other on-the-fly JavaScript highlighters alike
The Syntax gem was crossed out of this list as it provides very limited support for language schemes – Ruby only. It ain’t no good for me as I am all about using any effective tool at hand to get the job done – C++, bash, Perl, Python, C#, NSE and probably some others.
Although SyntaxHighligher seemed very yummy any sexily pretty it’s a bit like a duct-tape having other solutions at hand. It may easily be another interesting thing to try out here.
Ultraviolet is incredible. The overall list of supported syntax schemes tops 50. It is capable of using themes from TextMate (which by itself makes me drool pretty easily). And then there is a very handy tm_syntax_highlighting plugin to simplify working with the gem even further.
Alas… it pulls in a number of dependencies among which the ominous Oniguruma library. Compiling it is relatively easy and is limited to the usuals configure/make/make-install and you can find instructions here.
All would be good or great but the impenetrable obstacle I am currently struggling to overcome with Dreamhost and Phusion Passenger. It seems that Passenger is for some reason unable to pick up any additional library paths through setting them in environment – so far I only tried setting LD_LIBRARY_PATH via ENV in environment.rb which fails in solving this. This leaves me in a very awkward state:
libonig.so.2: cannot open shared object file: No such file or directory - /home/user/.gems/gems/oniguruma-1.1.0/lib/oregexp.so
This probably has something to do with Passenger’s configuration at DreamHost and maybe there is a way to fix this but so far it does not seem to work out well. Ryan Heath tried something similar here with similar results and switched back to using Syntax.
Oh well. So this leaves me biting my elbows. But wait – there is CodeRay and it is actually not that bad. The set of supported language schemes is definitely quite limited. The fact that Ryan Bates of Railscasts uses it got me enthusiastic and excited in no time. I gave CodeRay a try.
The solution I have for now is quite basic – I use RedCloth to enable textile in all the content in my blog so I simply want to plug the highlighting into my textilize processing. The code below is pretty self-explanatory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# in redclothext.rb require 'coderay' module RedClothExt include WhiteListHelper def syntax(text) text.gsub!(/<pre(\s*lang\=["']?(\w+)["']?[^>]*)?>(.*?)<\/pre>/m) do code = $3.nil? ? $2 : $3 lang = $2 unless $3.nil? html = "<notextile><div class='CodeRay'>" + CodeRay.scan(code, lang).html.numerize.div + "</div></notextile>" end end def whiten(text) white_list(text) end end RedCloth.send(:include, RedClothExt) |
Few notes here. The regular expression I have concocted here allows having code snippets embraced in pre as well as having them start with pre class="language-of-choice". This is all to allow having some minimal colorization for unsupported languages.
I am using RedCloth 4.0.3 which I believe has some changes in terms of how extensions should be implemented – I looked in the tests folder of the gem to grasp some basic understanding.
Now in the application helper I have all the RedCloth processing goodness chained in the following sequence – texile, whiten, then syntax:
1 2 3 4 5 6 |
# in appplication_helper.rb module ApplicationHelper def secure_textilize(text) RedCloth.new(text).to_html(:textile, :whiten, :syntax) end end |
You may have noticed I am using the white_list plugin here. The reason the syntax method is after sanitize in this sequence – white_list would have obliterated the minimal JavaScript created by CodeRay. The code generated there is for the purpose of toggling the line numbers.
Regarding the CSS – it’s a shameless mix of the one from Railscasts with some colors from UltraViolet’s sunburst.css for brighter glowing colors.
That’s all for now… Hope this is useful for someone. There may be other better solutions – let me know!
Re: Syntax highlighting - Ultraviolet vs CodeRay
15 Sep 13:35 taelor (from shovelchat.com) says:
coderay FTW, not only railscast, but railsenvy uses it as well. im sure I have seen it on other blogs too. oh and mine at slightlycoded.com/blog. anyway you gotta check out the work leethal has been doing over at github.
http://github.com/leethal/redcloth-with-coderay/tree/master
looks very similar. maybe you could help contribute.
PS. dugg your article. if you get some extra kill time check out this app I have been working on. http://shovelchat.com built using rails and juggernaut (its a push server using a TCP flash socket).
Email me back if you reply to this $)
Re: Syntax highlighting - Ultraviolet vs CodeRay
16 Sep 18:17 r00tyfruit says:
Hey, awesome! Thanks for pointing this out. I saw Railsenvy actually while reading some popular post on caching a day ago.
In general I was thinking this Coderay hook-up should be solved somewhere – felt like that – but could find anything. Had some thought that I should probably be using Liquid for these types of things.
I took a peek at Leethal’s plugin – JavaScript for toggling line numbers column will not survive if you do white_list on top of textilize. But if you do white_list before textilize it’s kinda tricky – it’s not HTML content yet. But maybe I am missing something in view of my relative n00bness. My concerns regarding default textilize and XSS are based on this post here.
I will def check out your app this week (looks like a good idea) – a bit tied up with other things right at the moment..
Sorry there is no checkbox to notify regarding replies to comments – “work in progress” :) Will email you shortly. Thanks again for stopping by… and digging :)
Cheers,
-Ivan