DevelopmentWeb

Rendering code with Markdown and HAML

By September 14, 2011 No Comments

While writing a future blog post on Openbox, I had some troubles with code Markdown rendering in HAML.

A few months ago Ryan Bates released a Railscast on Markdown with Redcarpet. Redcarpet is awesome, but for this blog I needed a bit more flexibility on my Markdown and I chose to use Kramdown.

The problem you face with both Redcarpet or Kramdown is that when you render your generated HTML containing some code, your code will be completely wrongly formated. Something like this

def foo
       bar = "bar"
                  foobar = "foobar"
                              end

See, wrong indentation.

Plus when you’re using Kramdown there is no automatic lang element in the pre tag, so Albino does not know what to colorize.

Solution(s)

From this Railscast, I have extracted these 2 helpers methods:

def markdown(text)
  options = [:hard_wrap, :filter_html, :autolink, :no_intraemphasis, :fenced_code, :gh_blockcode]
  syntax_highlighter(Redcarpet.new(text, *options).to_html).html_safe
end

def syntax_highlighter(html)
  doc = Nokogiri::HTML(html)
  doc.search("//pre[@lang]").each do |pre|
    pre.replace Albino.colorize(pre.text.rstrip, pre[:lang])
  end
  doc.to_s
end

When rendering your view you’ll use

= markdown(@article.content)

For the first problem, the wrong indentation, you have to add a preserve(HTML) to the call:

def markdown(text)
  options = [:hard_wrap, :filter_html, :autolink, :no_intraemphasis, :fenced_code, :gh_blockcode]
  preserve(syntax_highlighter(Redcarpet.new(text, *options).to_html).html_safe)
end

See HAML preserve doc

For the second problem, passing a lang element to the pre tag with Kramdown, all you have to do is add the lang using an ials block and everything will be working smoothly.