Created
August 2, 2012 19:26
-
-
Save sycobuny/3239904 to your computer and use it in GitHub Desktop.
Simple Document Viewer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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