Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Todd Fisher committed Mar 2, 2010
0 parents commit b80f0f4
Show file tree
Hide file tree
Showing 13 changed files with 364 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Sinatra Static Pages
--------------------

Sinatra makes websites easy, but when it's time to deploy running ruby can be a pain.

ContentPack makes it easy. Just export your sinatra application as static html and upload to any webserver - Done!

All the power of ruby, but really how many times are you changing that content and why can't you traverse your content store
before deploying. Do you really have so many pages you need a database for every request?
32 changes: 32 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'fileutils'
require 'app'

$:.unshift File.expand_path(File.join(File.dirname(__FILE__),"lib"))
require 'sitepack'

SiteDir = "site".freeze
DistFiles = Dir["public/**"].freeze
SiteDomain = "test.domain.com".freeze

task :default => :package

desc "Update Static Pages"
task :package => :clean do
FileUtils.mkdir_p(SiteDir) unless File.exist?(SiteDir)

bundler = SitePack::Builder.new(App, SiteDomain, SiteDir)
bundler.content('content') do|path|
bundler.save(path)
end

DistFiles.each do|f|
system("cp -r #{f} #{SiteDir}")
end

system("tar -zcf site.tar.gz #{SiteDir}")
end

desc "Delete Site dir"
task :clean do
system("rm -rf #{SiteDir}")
end
28 changes: 28 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'rubygems'
require 'sinatra'
$:.unshift File.expand_path(File.join(File.dirname(__FILE__),"lib"))
require 'sitepack'

class App < Sinatra::Application
include SitePack::Content
set :content_path, 'content'
set :public, 'public'

get '/' do
halt 302, {'Location' => '/index.html'}, ['']
end

get '/*.html' do
erb site_content(options.content_path, params)
end

not_found do
erb site_content(options.content_path, {:splat => ['404']})
end

end

if $0 == __FILE__
App.run! :port => 4567
exit(1)
end
16 changes: 16 additions & 0 deletions content/404.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<page>
<title>Missing page</title>
<body>
h1. That page is missing

A *simple* paragraph with
a line break, some _emphasis_ and a "link":http://redcloth.org

* an item
* and another

# one
# two
</body>
</page>
15 changes: 15 additions & 0 deletions content/badcontent.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<page>
<body
h1. Give RedCloth a try!

A *simple* paragraph with
a line break, some _emphasis_ and a "link":http://redcloth.org

* an item
* and another

# one
# two
</body>
</page>
16 changes: 16 additions & 0 deletions content/index.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<page>
<title>Home Page</title>
<body>
h1. Give RedCloth a try!

A *simple* paragraph with
a line break, some _emphasis_ and a "link":http://redcloth.org

* an item
* and another

# one
# two
</body>
</page>
16 changes: 16 additions & 0 deletions content/page2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<page>
<title>Home Page</title>
<body template="wizbang">
h1. Give RedCloth a try!

A *simple* paragraph with
a line break, some _emphasis_ and a "link":http://redcloth.org

* an item
* and another

# one
# two
</body>
</page>
16 changes: 16 additions & 0 deletions content/services/foo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<page>
<title>Service Foo</title>
<body template="wizbang">
h1. The Foo Services

A *simple* paragraph with
a line break, some _emphasis_ and a "link":http://redcloth.org

* an item
* and another

# one
# two
</body>
</page>
150 changes: 150 additions & 0 deletions lib/sitepack.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
require 'stringio'
require 'pathname'

require 'hpricot'
require 'redcloth'

module SitePack
RackDefaultEnv = {
'REQUEST_METHOD' => 'GET',
'SCRIPT_NAME' => 'app.rb',
'SERVER_NAME' => 'localhost',
'SERVER_PORT' => 9999,
'rack.url_scheme' => 'http',
'rack.version' => [1,1],
'rack.input' => StringIO.new,
'rack.errors' => StringIO.new,
'rack.run_once' => true,
'rack.multiprocess' => false,
'rack.multithread' => false
}.freeze

#
# Generate a static site using sinatra
#
# Given a content root folder, Builder will auto generate a site.
#
# builder = SitePack::Builder.new(MyAppKlass, 'mydomain.com', './site/')
#
# # walk all .xml files in the './content/' directory
# # calling builder.save with the computed path will
# # write out a rendered .html file into the ./site/ directory at the path
# # ./content/#{path}.html
#
# builder.content('./content/') do|path|
# builder.save(path)
# end
#
class Builder

def initialize(appklass, domain, sitedir)
@appklass = appklass
@domain = domain
@sitedir = sitedir
end

#
# yield each sub path of each content file within the content directory
# or return an array of all paths
#
def content(dir)
dir_path = Pathname.new(File.expand_path(dir))
paths = Dir["#{dir}/**/**.xml"].map{|p| Pathname.new(File.expand_path(p)).relative_path_from(dir_path) }
paths.each {|p| yield p } if block_given?
paths
end

#
# save a given url into the site URL
#
def save(path)
html_path = path.sub(/\.xml$/,'.html')
file = "#{@sitedir}/#{html_path}"
url = "http://#{@domain}/#{html_path}"
env = RackDefaultEnv.dup
uri = URI.parse(url)
env['PATH_INFO'] = uri.path
env['QUERY_STRING'] = uri.query || ''
req = Rack::Request.new(env) #Rack::MockRequest.env_for(url, env)
status, headers, body = @appklass.call(req.env)
res = Rack::MockResponse.new(status, headers, body, req.env["rack.errors"].flush)

case status
when 200
puts "render: #{url} as #{file}"
FileUtils.mkdir_p(File.dirname(file)) unless File.exist?(File.dirname(file))
File.open(file,'wb') { |f| f << res.body }
else
raise "error #{status} status code: #{status} when requesting: #{url}\n#{res.body}"
end
end
end

#
# enable content by including this module in your sinatra application
#
# class MyApp < Sinatra::Application
# include SitePack::Content
# set :content_path, 'content'
# set :public, 'public'
#
# get '/:page.html' do
# erb site_content(options.content_path, params)
# end
# end
#
# sample page content format:
#
# <?xml version="1.0"?>
# <page>
# <title>Title Content</title>
# <body template="special" filter="redcloth">
# h1. Foo Bar
#
# A *simple* paragraph with
# a line break, some _emphasis_ and a "link":http://redcloth.org
#
# * an item
# * and another
#
# # one
# # two
#
# </body>
# </page>
#
# template = by default is page, e.g. views/page.erb
# filter = by default is redcloth, but can be html -> in which case use <![CDATA[ html ]]>
#
module Content

def site_content(content_path, params)
if params[:splat].nil?
file_path = "#{content_path}/index.xml"
else
file_path = "#{content_path}/#{params[:splat].join('/')}.xml"
end
halt 404, "page not found: #{file_path.inspect}" unless File.exists?(file_path)
doc = Hpricot.XML(File.read(file_path))
@title = doc.at(:title) ? doc.at(:title).inner_html : nil
@body = doc.at(:body)
if @body
template = @body[:template] || 'page'
filter = @body[:filter] || 'redcloth'
case filter
when 'redcloth'
@body = RedCloth.new(@body.inner_html).to_html
when 'html'
@body = @body.inner_html
else
halt 500, "Unsupported filter: #{filter} when rendering #{file_path}"
end
else
halt 500, "Missing body tag!"
end
template.to_sym
end

end

end
47 changes: 47 additions & 0 deletions test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

require 'app'
require 'test/unit'
require 'rack/test'

class TestApp < Test::Unit::TestCase
include Rack::Test::Methods

def app
App
end

def test_index_redirect
get '/'
assert_equal 302, last_response.status
end

def test_404
get '/foobar.html'
assert_equal 404, last_response.status
assert_match /That page is missing/, last_response.body
end

def test_500
get '/badcontent.html'
assert_equal 500, last_response.status
assert_match /Missing body tag/, last_response.body
end

def test_200
get '/index.html'
assert_equal 200, last_response.status
assert_match /Home Page/, last_response.body
end

def test_package
system("mv content/badcontent.xml .")
system("rake package")
assert File.exist?("site/index.html")
assert File.exist?("site/page2.html")
assert File.exist?("site/services/foo.html")
assert File.exist?("site/404.html")
ensure
system("mv badcontent.xml content/badcontent.xml")
end

end
10 changes: 10 additions & 0 deletions views/layout.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><%= @title %></title>
</head>
<body>
<%= yield %>
</body>
</html>
7 changes: 7 additions & 0 deletions views/page.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<%= @body %>
<div id="sidebar">
<ul>
<li>link1</li>
<li>link2</li>
</ul>
</div>
2 changes: 2 additions & 0 deletions views/wizbang.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%= @body %>
cool

0 comments on commit b80f0f4

Please sign in to comment.