class Rack::Pygmoku

Public Class Methods

new(app, opts = {}) click to toggle source
# File lib/rack/pygmoku.rb, line 8
def initialize(app, opts = {})
  @app  = app
  @opts = default_opts.merge(opts)
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/pygmoku.rb, line 13
def call(env)
  status, headers, response = @app.call(env)
  headers = HeaderHash.new(headers)

  if highlight?(status, headers)
    content = highlight(response.join)
    headers['Content-Length'] = bytesize(content).to_s
    response = [content]
  end

  [status, headers, response]
end

Private Instance Methods

default_opts() click to toggle source
# File lib/rack/pygmoku.rb, line 65
def default_opts
  {
    :element    => 'pre>code',
    :lexer_attr => 'data-lang'
  }
end
get_lexer(node) click to toggle source
# File lib/rack/pygmoku.rb, line 53
def get_lexer(node)
  attribute = @opts[:lexer_attr]
  lexer = 'html'
  lexer = node[attribute] if node.has_attribute?(attribute)
  lexer
end
highlight(content) click to toggle source
# File lib/rack/pygmoku.rb, line 33
def highlight(content)
  require 'pygments'

  element = @opts[:element]

  document = Nokogiri::HTML(content, nil, 'utf-8')
  nodes = document.css(element)
  nodes.each do |node|
    parent_node = node.parent
    lexer = get_lexer(parent_node)
    content = unescape_html(node.content)

    highlighted = Pygments.highlight(content, {:lexer => lexer })
    parent_node.replace(highlighted)
    parent_node.remove()
  end

  document.serialize
end
highlight?(status, headers) click to toggle source
# File lib/rack/pygmoku.rb, line 27
def highlight?(status, headers)
  status == 200 &&
  !headers['Transfer-Encoding'] &&
  headers['Content-Type'] =~ /html/
end
unescape_html(html) click to toggle source
# File lib/rack/pygmoku.rb, line 60
def unescape_html(html)
  html.to_s.gsub(/&#x000A;/i, "\n").gsub("&lt;", '<').gsub(
    "&gt;", '>').gsub("&amp;", '&')
end