Adding GitHub Flavoured Markdown with syntax highlighting in your Rails application

There are many options available for us to pick from when choosing Markdown processors and syntax highlighting libraries. If you use GitHub on a daily basis like we do, I'm pretty sure you can appreciate the ease of adding comments, snippets of code and simply working with GitHub Flavoured Markdown.

Adding support for that parser with syntax highlighting in Rails is simple. We will use two gems: redcarpet to render Markdown syntax to HTML and rouge to enable syntax highlighting.

Rendering Markdown

Let's create a MarkdownService that will take a Markdown string and return a rendered HTML:

require 'rouge/plugins/redcarpet' class MarkdownService class Renderer < Redcarpet::Render::HTML include Rouge::Plugins::Redcarpet end attr_reader :markdown def self.call(markdown) new(markdown).call end def initialize(markdown) @markdown = markdown end def call render end private def markdown_renderer Redcarpet::Markdown.new(Renderer, autolink: true, tables: true, fenced_code_blocks: true) end def render markdown_renderer.render(markdown) end end

The necessary option that will allow us to render and enable syntax highlighting similar to GitHub is fenced_code_blocks.

Example of fenced code block:

```ruby puts 'Hello WatchSumo!' ```

Calling MarkdownService.call([...]) will render it as Markdown and additionally process all the fenced code blocks, returning HTML that can be styled with pygments compatible stylesheets.

There is a nice collection available under pygments-css repository.

By default, the main highlight class will be called highlight in Rouge. Remember to change eg.

.hll { background-color: #ffffcc }

to

.highlight { background-color: #ffffcc }

An alternative is to override the redcarpet plugin, by passing the correct class name for compatibility:

class Renderer < Redcarpet::Render::HTML include Rouge::Plugins::Redcarpet protected def rouge_formatter(opts = {}) ::Rouge::Formatters::HTML.new(opts.merge({ css_class: "hll" })) end end

Additional option that you might be interested in adding is line_numbers: true that enables line numbers in the output.