tiny_site 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/tiny_site.rb +119 -0
  2. data/lib/tiny_site/version.rb +3 -0
  3. metadata +100 -0
@@ -0,0 +1,119 @@
1
+ require 'open-uri'
2
+ require 'RedCloth'
3
+ require 'yaml'
4
+ require 'haml'
5
+
6
+ class TextileParts
7
+ def self.parse(tp, image_path='')
8
+ vars, *parts = tp.split(/^\+\+\+\+|\+\+\+\+$/)
9
+
10
+ vars = YAML.load(vars) || {}
11
+ parts = Hash[*parts]
12
+ parts.each{|k,v| parts[k] = textilize(v,image_path)}
13
+
14
+ return vars, parts
15
+ end
16
+ def self.textilize(string, image_path)
17
+ string.gsub!(%r{!([\w\d\-\._]+)!}){ |a| "!#{image_path}/#{$1}!" }
18
+
19
+ RedCloth.new(string).to_html
20
+ end
21
+ end
22
+
23
+ class CachedHttpFile
24
+ def initialize(url, expires_in=3600)
25
+ @url, @expires_in = url, expires_in
26
+ end
27
+
28
+ def fetch
29
+ puts "fetching #{@url}"
30
+ @body = open(@url).read
31
+ store
32
+ return 200, @body
33
+ rescue OpenURI::HTTPError => error
34
+ puts "OpenURI::HTTPError: #{error.message}"
35
+ return error.message.to_i, nil
36
+ end
37
+
38
+ def cached?
39
+ self.class.files[@url] && self.class.files[@url][:expires_at] > Time.now
40
+ end
41
+ def cached
42
+ return 200, self.class.files[@url][:content]
43
+ end
44
+
45
+ def store
46
+ puts "storing body of #{@url}"
47
+ self.class.files[@url] = {:content => @body, :expires_at => Time.now + @expires_in}
48
+ end
49
+
50
+ def get
51
+ (cached? && cached) || fetch
52
+ end
53
+
54
+ class << self
55
+ def files
56
+ @files ||= {}
57
+ end
58
+ def get(url, expires_in=3600)
59
+ (new url, expires_in).get
60
+ end
61
+ def bust
62
+ puts 'busting cache'
63
+ @files = {}
64
+ end
65
+ end
66
+ end
67
+
68
+ class TinySite
69
+ def initialize(opts)
70
+ @file_path = opts[:file_path]
71
+ @image_path = opts[:image_path] || File.join(@file_path, 'images')
72
+ @cache_buster = opts[:cache_buster] || 'bust'
73
+ end
74
+
75
+ def remote_file_url_for(filename)
76
+ File.join @file_path, "#{filename}.textile"
77
+ end
78
+
79
+ def render
80
+ global_file_fetch_tread = Thread.new{
81
+ _, @global_file = CachedHttpFile.get remote_file_url_for('__global') } # get __global in background
82
+ @status, page_file = CachedHttpFile.get remote_file_url_for(@path)
83
+ _, page_file = CachedHttpFile.get remote_file_url_for(@status) if @status != 200
84
+ global_file_fetch_tread.join
85
+
86
+ global_vars, global_parts = TextileParts.parse @global_file, @image_path
87
+ page_vars, page_parts = TextileParts.parse page_file, @image_path
88
+
89
+ render_layout :global_vars => global_vars, :global_parts => global_parts,
90
+ :page_vars => page_vars, :page_parts => page_parts
91
+ end
92
+
93
+ def render_layout(params)
94
+ layout = params[:page_vars][:layout] || params[:global_vars][:layout] || 'layout'
95
+
96
+ puts "rendering layout '#{layout}'"
97
+ haml = Haml::Engine.new File.open("#{layout}.haml").read, :format => :html5
98
+ haml.render Object.new, params
99
+ end
100
+
101
+ def caching_header
102
+ return { 'Cache-Control' => 'public, max-age=3600' } unless @query_string == @cache_buster
103
+
104
+ CachedHttpFile.bust and return { 'Cache-Control' => 'no-cache' }
105
+ end
106
+
107
+ def call(env)
108
+ @path, @query_string = env['PATH_INFO'], env['QUERY_STRING']
109
+ @path = '/index' if @path == '/'
110
+
111
+ return [301, {'Location' => @path}, ''] if @path.gsub!(/\/$/,'')
112
+
113
+ body = render # render the body first to set @status
114
+ [@status, caching_header, body]
115
+ rescue => e
116
+ puts "#{e.class}: #{e.message} #{e.backtrace}"
117
+ [500, {}, 'Sorry, but something went wrong']
118
+ end
119
+ end
@@ -0,0 +1,3 @@
1
+ class TinySite
2
+ VERSION = "0.1.1"
3
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiny_site
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.1
6
+ platform: ruby
7
+ authors:
8
+ - Niko Dittmann
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-27 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rack
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: RedCloth
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: haml
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ type: :development
59
+ version_requirements: *id004
60
+ description: A static small site engine with Heroku and DropBox in mind
61
+ email: mail+git@niko-dittmann.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - lib/tiny_site/version.rb
70
+ - lib/tiny_site.rb
71
+ has_rdoc: true
72
+ homepage: http://github.com/niko/tiny_site
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ requirements: []
93
+
94
+ rubyforge_project: "[none]"
95
+ rubygems_version: 1.5.0
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: A static small site engine with Heroku and DropBox in mind
99
+ test_files: []
100
+