Just a small Sinatra app to show xkcd comics with the mouseover text visible at the bottom of the page. xkcd.heroku.com does the same thing but I find their images are too small sometimes.
Created
October 29, 2010 22:17
-
-
Save BinaryMuse/654553 to your computer and use it in GitHub Desktop.
xkcd2.heroku.com : Sinatra app to display xkcd comics so that the alt text can be seen
This file contains 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
sinatra | |
haml |
This file contains 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
.rvmrc |
This file contains 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
$: << '.' | |
require 'xkcd' | |
run Sinatra::Application |
This file contains 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
require 'net/http' | |
require 'uri' | |
require 'sinatra' | |
require 'json' | |
require 'haml' | |
# Blank route for the favicon to keep errors low | |
get '/favicon.ico' do | |
nil | |
end | |
# Random gets a random comic | |
get '/random' do | |
current = symbolize_keys(JSON::parse(get_comic_json(:current))) | |
current = current[:num] | |
random = rand(current) + 1 | |
# Make sure we don't hit 404, which is XKCD's actual 404 page. | |
while random == 404 | |
random = rand(current) + 1 | |
end | |
redirect "/#{random}" | |
end | |
# Index gets the current comic | |
get '/' do | |
return do_comic(:current) | |
end | |
get '/:number' do |number| | |
return do_comic(number) | |
end | |
def do_comic(number) | |
begin | |
# Get the JSON data | |
current = symbolize_keys(JSON::parse(get_comic_json(:current))) | |
@data = symbolize_keys(JSON::parse(get_comic_json(number))) | |
rescue | |
@data = { :safe_title => "Not Found" } | |
return haml :error | |
end | |
# Turn the "year", "month", and "day" properties into numbers | |
[:year, :month, :day].each { |key| @data[key] = @data[key].to_i } | |
# Calculate the "previous" and "next" comics, if any | |
@data[:previous] = @data[:num] - 1 unless @data[:num] == 1 || @data[:num].nil? | |
unless current[:num] == @data[:num] | |
@data[:next] = @data[:num] + 1 unless @data[:num].nil? | |
end | |
# Make sure we don't hit 404, which is XKCD's actual 404 page. | |
@data[:previous] -= 1 if @data[:previous] == 404 | |
@data[:next] += 1 if @data[:next] == 404 | |
# Render the page | |
haml :comic | |
end | |
# If the comic number is 0, get today's comic | |
# Else get the given comic | |
def get_comic_json(number) | |
if number == :current | |
Net::HTTP.get(URI.parse("http://xkcd.com/info.0.json")) | |
else | |
Net::HTTP.get(URI.parse("http://xkcd.com/#{number}/info.0.json")) | |
end | |
end | |
# change string keys into symbols | |
def symbolize_keys(arg) | |
case arg | |
when Array | |
arg.map { |elem| symbolize_keys elem } | |
when Hash | |
Hash[ | |
arg.map { |key, value| | |
k = key.is_a?(String) ? key.to_sym : key | |
v = symbolize_keys value | |
[k,v] | |
}] | |
else | |
arg | |
end | |
end | |
__END__ | |
@@ layout | |
%html | |
%head | |
%title xkcd mini: #{@data[:safe_title]} | |
%body | |
= yield | |
@@ error | |
%h1 Not Found | |
%p | |
That comic was not found. | |
%p | |
%a{:href => "/"}Home | |
@@ comic | |
%h1= @data[:safe_title] | |
%p | |
- unless @data[:previous].nil? | |
%a{:href => "/1"}< | |
<< First | |
| | |
%a{:href => "/#{@data[:previous]}"}< | |
< Previous | |
- else | |
<< First | |
| | |
< Previous | |
| | |
%a{:href => "/random"}< | |
Random | |
| | |
- unless @data[:next].nil? | |
%a{:href => "/#{@data[:next]}"}< | |
Next > | |
| | |
%a{:href => "/"}< | |
Last >> | |
- else | |
Next > | |
| | |
Last >> | |
%p | |
%img{:src => @data[:img]} | |
%p= @data[:alt] | |
%hr | |
%p | |
Read this comic on | |
%a{:href => "http://xkcd.com/#{@data[:num]}"}xkcd.com |
Yeah, it looks like it creates a hash, using symbols created from whatever's after @@
as the key and all the lines up to the next line that matches /^@@\s*(.*\S)\s*$/
as the value. The haml
call just wraps a call to render
and passes in :haml
as the rendering engine to use. https://github.com/sinatra/sinatra/blob/aa06ed/lib/sinatra/base.rb#L377-379
Cool!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So I'm guessing sinatra defines the :comic symbol on line 39 when it parses the template and sees "@@ comic"? Sorry if my line number is off...there is a rendering bug in Firefox that causes the line number gutter to be vertically offset.