Better GitHub-style syntax highlighting with Rouge

Update 2016: This tutorial is out-of-date. See the repository for alexpeattie.com and the associated README to see how I do it now.

This is a sequel to my earlier post: GitHub-style syntax highlighting with Pygments - I recently updated the way I do syntax highlighting on this site, so here's a quick writeup of how I'm doing it. As before, here's a snippet of Ruby code to demonstrate how the highlighting looks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A < B; def self.create(object = User)
class Zebra; def inspect; "X#{2 + self.object_id}"

module ABC::DEF
  include Comparable

  # @param test
  # @return [String] nothing
  def foo(test)
    Thread.new do |blockvar|
      ABC::DEF.reverse(:a_symbol, :'a symbol', :<=>, 'test' + test)
    end.join
  end

  def [](index) self[index] end
  def ==(other) other == self end
end

anIdentifier = an_identifier
Constant = 1
render action: :new

Of course better is a very fuzzy term - but some advantages over the previous approach:

This post focuses on middleman (which this site is built on) but rouge can be used with Rails1 or Sinatra2 too.

Setup

To enable basic syntax highlighting, we need to add the middleman-syntax gem to our Gemfile:

1
gem "middleman-syntax"

and activate it in our config.rb:

1
activate :syntax

Finally we'll enable line numbers with the aptly-named line_numbers option:

1
activate :syntax, line_numbers: true

Styling

Most of the work is done already, thanks to richleland's Github color scheme. We just need to tweak the first line, to replace .hll with .highlight

1
2
.hll { background-color: #ffffcc } /* WRONG */
.highlight { background-color: #ffffcc } /* RIGHT */

And we'll add a little extra CSS to style our <pre>, add some extra padding, and prettify the line numbers a bit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
pre {
  border: solid 1px #ddd;
  background: #fff;
  padding: 0;
  line-height: 23px;
  margin-bottom: 30px;
  white-space: pre;
  overflow-x: auto;
  word-break: inherit;
  word-wrap: inherit;
}

.highlight td {
    padding: 8px 15px;
}

.gl { 
  background: #fafafa;
  border-right: 1px solid #ddd;
  color: #999;
  
  /* Stop line numbers being visually selected */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

Markdown

I couldn't get rouge to play nicely with Redcarpet on middleman - so I decided to switch to Kramdown, which I highly recommend. It's written in pure Ruby, and comes with fenced code blocks out-of-the-box, as well as footnotes and a bunch of other useful features3.

Footnotes