Daniel Doubrovkine bio photo

Daniel Doubrovkine

aka dB., CTO at artsy.net, fun at playplay.io, NYC

Email Twitter LinkedIn Github

I wanted Ruby and JSON code blocks ala Github’s Flavored Markdown when rendering markdown documents in doppler. The idea is that we can API documentation authored in markdown, and rendered within a Rails application.

The first, harder part, is doing markdown rendering with syntax highlighting. You render markdown with your favorite markdown gem (eg. Redcarpet), then parse the document and replace all code divs with a syntax highlighted version produced by Coderay. I had to also do some div swapping to avoid nested <pre> and <code> blocks.

require 'redcarpet'
require 'coderay'

module MarkdownHelper
def render_markdown(text)
renderer = Redcarpet::Markdown.new(Redcarpet::Render::HTML, fenced_code_blocks: true)
doc = Nokogiri::HTML::DocumentFragment.parse(renderer.render(text))
doc.css('code[@class]').each do |code|
div = CodeRay.scan(code.text.rstrip, code[:class].to_sym).div
code = code.replace(div)
code.first.parent.swap(code.first)
end
doc.to_s
end
end

We can use this in a controller, assuming content lives in app/voews/content. Bonus: caching.

class PagesController < ApplicationController
include MarkdownHelper

def show
fail 'Invalid Id' unless params[:id] =~ /^[\w\/]\*$/
filename = Rails.root.join("app/views/content/#{params[:id]}.md")
@content = Rails.cache.fetch "content/#{params[:id]}/#{File.mtime(filename)}" do
text = File.read(filename)
render_markdown text
end
end
end

The corresponding view in pages/show.html.haml is as follows.

%div
!= @content

You can route to one of those pages in routes.rb.

get '/terms', to: 'pages#show', id: 'terms'

See https://github.com/artsy/doppler/pull/24 for a complete pull request with the above.

And here’s a screenshot of a rendered page.