Skip to content

Instantly share code, notes, and snippets.

@sycobuny
Created August 2, 2012 19:26
Show Gist options
  • Save sycobuny/3239904 to your computer and use it in GitHub Desktop.
Save sycobuny/3239904 to your computer and use it in GitHub Desktop.
Simple Document Viewer
#!/usr/bin/env ruby
# discover OS information to see if we should use pygments to colorize code
if RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/
# no clue if this will work at all on windows, so whatever
USE_PYGMENTS = true
PYGMENTS_BLACKLIST = []
elsif RUBY_PLATFORM =~ /darwin/
version = `sw_vers -productVersion`
if version =~ /^10\.7/
# pygments seems to work, but not on apache configs
USE_PYGMENTS = true
PYGMENTS_BLACKLIST = %w(ApacheConf aconf apacheconf)
elsif version =~ /^10\.6/
# pygments does not seem to work at all.
USE_PYGMENTS = false
else
# no clue, probably (hopefully) works
USE_PYGMENTS = true
PYGMENTS_BLACKLIST = []
end
elsif RUBY_PLATFORM =~ /java/
# it'll probably work on java
USE_PYGMENTS = true
PYGMENTS_BLACKLIST = []
else
# probably linux, so we should be safe.
USE_PYGMENTS = true
PYGMENTS_BLACKLIST = []
end
# require stdlibs
require 'digest'
# require gems
gems = {
'sinatra' => 'sinatra',
'haml' => 'haml',
'github/markdown' => 'github-markdown',
'github/markup' => 'github-markup'
}
missing = {}
gems['pygments'] = 'pygments.rb' if USE_PYGMENTS
gems.each do |req, gem|
begin
require req
rescue LoadError => e
missing[req] = gem
end
end
if not missing.empty?
g = gems.keys
g[-1] = "and #{g[-1]}"
puts "The #{g.join(', ')} gems are required."
puts "You are missing: #{missing.keys.join(', ')}"
puts "Please install them using:"
puts " $ gem install --no-ri --no-rdoc #{missing.values.join(' ')}"
exit 1
end
# use html5 and set the layout for the app
set :haml, :format => :html5
set :layout, :layout
get '/*' do
# ignore requests for favicon.ico and robots.txt
if [['favicon.ico'], ['robots.txt']].include?(params[:splat])
return ''
end
# get the full path of the request
path = request.path
# strip off query string
path = $1 if path =~ /^(.*)\?/
# if the last piece of the path is /, we're looking for an Index page
index = path =~ /\/$/
# URL-decode the path bits
path_parts = path.split("/").collect do |piece|
piece = piece.gsub(/\%([a-fA-F0-9]{2})/) do
[$1.hex].pack('C')
end
# ignore requests that translate to potential attempts to get at
# directories which someone should not have access to
if piece =~ /\// or piece =~ /^\.+$/
error 400
end
piece
end
# put the page title together
@page = path_parts.join('/')
# normalize a valid path from the path fragments: add current dir, make the
# last piece Index if appropriate, and use .md suffixes for everything
path_parts.unshift('.')
path_parts.push('Index') if index
path_parts[-1] += '.md'
# put the path together and verify it exists
@path = File.join(path_parts)
error 404 unless File.exists?(@path)
# read the file in
data = File.read(@path)
# skip colorizing code and just render regular Markdown if we can't use
# pygments for whatever reason.
unless USE_PYGMENTS
return haml :doc, {}, :page => GitHub::Markup.render(@path, data)
end
# backup code blocks before processing in GitHub::Markup and Pygments
# this code is ripped from Gollum::Markup
codemap = {}
data.gsub!(/^([ \t]*)``` ?([^\r\n]+)?\r?\n(.+?)\r?\n\1```\r?$/m) do |str|
if PYGMENTS_BLACKLIST.include?($2)
# this code can't be colorized on this system due to failures in
# RubyPython or...something.
str
else
id = Digest::SHA1.hexdigest("#{$2}.#{$3}")
codemap[id] = { :lang => $2, :code => $3, :indent => $1 }
"#{$1}#{id}" # print the SHA1 ID with the proper indentation
end
end
# parse the markdown using GitHub::Markup
data = GitHub::Markup.render(@path, data)
# restore the code blocks, processed through Pygments
# this code is still taken from Gollum::Markup
blocks = []
codemap.each do |id, spec|
code = spec[:code]
[/^#{spec[:indent]}/m, /^( |\t)/m].each do |re|
if code.lines.all? { |line| line =~ /\A\r?\n\Z/ || line =~ re }
code.gsub!(re, '')
end
end
blocks << [spec[:lang], code]
end
# this code is still taken from Gollum::Markup
highlighted = begin
blocks.collect do |lang, code|
Pygments.highlight(code, :lexer => lang)
end
rescue ::RubyPython::PythonError => e
[]
end
# this code is still taken from Gollum::Markup
codemap.each do |id, spec|
body = spec[:output] || begin
if (body = highlighted.shift.to_s).size > 0
body
else
"<pre><code>#{CGI.escapeHTML(spec[:code])}</code></pre>"
end
end
data.gsub!(id, body)
end
haml :doc, {}, :page => data
end
__END__
@@ doc
!!!
%html
%head
%title= @page
:css
h1 {
text-align: center
}
h2, h3 {
text-align: left
}
body {
background-color: #f0f0f0;
font-family: Helvetica, Verdana, Arial, sans-serif;
max-width: 60em;
}
a {
color: #66f;
background-color: #f8f8f8;
text-decoration: none
}
a:hover {
background-color: #f0f0f0;
}
a:visited {
color: #77f;
}
p {
text-align: justify;
}
pre {
width: 650px;
overflow: auto;
border: 1px solid #aaaaaa;
box-shadow: 0 0 5px #cccccc;
background-color: #fff;
border-radius: 5px;
padding: 5px;
}
- if USE_PYGMENTS
%style{:type => 'text/css'}
= Pygments.css('.highlight')
:css
.highlight {
background-color: #f0f0f0;
}
%body
= page
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment