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.