ceilingfish-toto 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.3.6
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ceilingfish-toto}
8
- s.version = "0.3.5"
8
+ s.version = "0.3.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["cloudhead", "ceilingfish"]
12
- s.date = %q{2010-02-12}
12
+ s.date = %q{2010-02-13}
13
13
  s.description = %q{the tiniest blog-engine in Oz.}
14
14
  s.email = %q{ceilingfish@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -24,8 +24,6 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "ceilingfish-toto.gemspec",
27
- "lib/ceilingfish/ext/ext.rb",
28
- "lib/ceilingfish/toto.rb",
29
27
  "test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt",
30
28
  "test/articles/2001-01-01-two-thousand-and-one.txt",
31
29
  "test/articles/2009-04-01-tilt-factor.txt",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ceilingfish-toto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - cloudhead
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2010-02-12 00:00:00 +00:00
13
+ date: 2010-02-13 00:00:00 +00:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -70,8 +70,6 @@ files:
70
70
  - Rakefile
71
71
  - VERSION
72
72
  - ceilingfish-toto.gemspec
73
- - lib/ceilingfish/ext/ext.rb
74
- - lib/ceilingfish/toto.rb
75
73
  - test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt
76
74
  - test/articles/2001-01-01-two-thousand-and-one.txt
77
75
  - test/articles/2009-04-01-tilt-factor.txt
@@ -1,36 +0,0 @@
1
- class Object
2
- def meta_def name, &blk
3
- (class << self; self; end).instance_eval do
4
- define_method(name, &blk)
5
- end
6
- end
7
- end
8
-
9
- class String
10
- def slugize
11
- self.downcase.gsub(/&/, 'and').gsub(/\s+/, '-').gsub(/[^a-z0-9-]/, '')
12
- end
13
-
14
- def humanize
15
- self.capitalize.gsub(/[-_]+/, ' ')
16
- end
17
- end
18
-
19
- class Fixnum
20
- def ordinal
21
- # 1 => 1st
22
- # 2 => 2nd
23
- # 3 => 3rd
24
- # ...
25
- case self % 100
26
- when 11..13; "#{self}th"
27
- else
28
- case self % 10
29
- when 1; "#{self}st"
30
- when 2; "#{self}nd"
31
- when 3; "#{self}rd"
32
- else "#{self}th"
33
- end
34
- end
35
- end
36
- end
@@ -1,351 +0,0 @@
1
- require 'yaml'
2
- require 'time'
3
- require 'erb'
4
- require 'rack'
5
- require 'digest'
6
- require 'open-uri'
7
-
8
- require 'rdiscount'
9
- require 'builder'
10
-
11
- $:.unshift File.dirname(__FILE__)
12
-
13
- require 'ext/ext'
14
-
15
- module Toto
16
- Paths = {
17
- :templates => "templates",
18
- :pages => "templates/pages",
19
- :articles => "articles"
20
- }
21
-
22
- def self.env
23
- ENV['RACK_ENV'] || 'production'
24
- end
25
-
26
- def self.env= env
27
- ENV['RACK_ENV'] = env
28
- end
29
-
30
- module Template
31
- def to_html page, &blk
32
- path = ([:layout, :repo].include?(page) ? Paths[:templates] : Paths[:pages])
33
- ERB.new(File.read("#{path}/#{page}.rhtml")).result(binding)
34
- end
35
-
36
- def markdown text
37
- if (options = @config[:markdown])
38
- Markdown.new(text.to_s.strip, *(options.eql?(true) ? [] : options)).to_html
39
- else
40
- text.strip
41
- end
42
- end
43
-
44
- def method_missing m, *args, &blk
45
- self.keys.include?(m) ? self[m] : super
46
- end
47
-
48
- def self.included obj
49
- obj.class_eval do
50
- define_method(obj.to_s.split('::').last.downcase) { self }
51
- end
52
- end
53
- end
54
-
55
- module ConfigHelpers
56
- def [] *args
57
- @config[*args]
58
- end
59
-
60
- def []= key, value
61
- @config.set key, value
62
- end
63
- end
64
-
65
- module PageHelpers
66
- include ConfigHelpers
67
-
68
- def archives filter = ""
69
- entries = ! self.articles.empty??
70
- self.articles.select do |a|
71
- filter !~ /^\d{4}/ || File.basename(a) =~ /^#{filter}/
72
- end.reverse.map do |article|
73
- Article.new File.new(article), @config
74
- end : []
75
-
76
- return Archives.new(entries)
77
- end
78
-
79
- def title
80
- self[:title]
81
- end
82
-
83
- def articles ext = self[:ext]
84
- Dir["#{Paths[:articles]}/*.#{ext}"]
85
- end
86
- end
87
-
88
- class Site
89
- include PageHelpers
90
-
91
- def initialize config
92
- @config = config
93
- end
94
-
95
- def index type = :html
96
- case type
97
- when :html
98
- {:articles => articles.reverse.map do |article|
99
- Article.new File.new(article), @config
100
- end }.merge(:archives => archives)
101
- when :xml, :json
102
- return :articles => articles.map do |article|
103
- Article.new File.new(article), @config
104
- end
105
- else return {}
106
- end
107
- end
108
-
109
- def article route
110
- Article.new(File.new("#{Paths[:articles]}/#{route.join('-')}.#{self[:ext]}"), @config).load
111
- end
112
-
113
- def /
114
- self[:root]
115
- end
116
-
117
- def go route, type = :html
118
- route << self./ if route.empty?
119
- type, path = type =~ /html|xml|json/ ? type.to_sym : :html, route.join('/')
120
- context = lambda do |data, page|
121
- Context.new(data, @config, path).render(page, type)
122
- end
123
-
124
- body, status = if Context.new.respond_to?(:"to_#{type}")
125
- if route.first =~ /\d{4}/
126
- case route.size
127
- when 1..3
128
- context[{:archives => archives(route * '-')}, :archives]
129
- when 4
130
- context[article(route), :article]
131
- else http 400
132
- end
133
- elsif respond_to?(path)
134
- context[send(path, type), path.to_sym]
135
- elsif (repo = @config[:github][:repos].grep(/#{path}/).first) &&
136
- !@config[:github][:user].empty?
137
- context[Repo.new(repo, @config), :repo]
138
- else
139
- context[{}, path.to_sym]
140
- end
141
- else
142
- http 400
143
- end
144
-
145
- rescue Errno::ENOENT => e
146
- return :body => http(404).first, :type => :html, :status => 404
147
- else
148
- return :body => body || "", :type => type, :status => status || 200
149
- end
150
-
151
- protected
152
-
153
- def http code
154
- return ["<font style='font-size:300%'>toto, we're not in Kansas anymore (#{code})</font>", code]
155
- end
156
-
157
- class Context
158
- include Template
159
- include PageHelpers
160
-
161
- def initialize ctx = {}, config = {}, path = "/"
162
- @config, @context, @path = config, ctx, path
163
- @articles = articles(@config[:ext]).reverse.map do |a|
164
- Article.new(File.new(a), @config)
165
- end
166
-
167
- ctx.each do |k, v|
168
- meta_def(k) { ctx.instance_of?(Hash) ? v : ctx.send(k) }
169
- end
170
- end
171
-
172
- def render page, type
173
- type == :html ? to_html(:layout, &Proc.new { to_html page }) : send(:"to_#{type}", :feed)
174
- end
175
-
176
- def to_xml page
177
- xml = Builder::XmlMarkup.new(:indent => 2)
178
- instance_eval File.read("#{Paths[:templates]}/#{page}.builder")
179
- end
180
- alias :to_atom to_xml
181
-
182
- def method_missing m, *args, &blk
183
- @context.respond_to?(m) ? @context.send(m) : super
184
- end
185
- end
186
- end
187
-
188
- class Repo < Hash
189
- include Template
190
-
191
- README = "http://github.com/%s/%s/raw/master/README.%s"
192
-
193
- def initialize name, config
194
- self[:name], @config = name, config
195
- end
196
-
197
- def readme
198
- markdown open(README %
199
- [@config[:github][:user], self[:name], @config[:github][:ext]]).read
200
- rescue Timeout::Error, OpenURI::HTTPError => e
201
- "This page isn't available."
202
- end
203
- alias :content readme
204
- end
205
-
206
- class Archives < Array
207
- include Template
208
-
209
- def initialize articles
210
- self.replace articles
211
- end
212
-
213
- def to_html
214
- super(:archives)
215
- end
216
- alias :to_s to_html
217
- alias :archive archives
218
- end
219
-
220
- class Article < Hash
221
- include Template
222
-
223
- def initialize obj, config = {}
224
- @obj, @config = obj, config
225
- self.load if obj.is_a? Hash
226
- end
227
-
228
- def load
229
- data = if @obj.is_a? File
230
- meta, self[:body] = @obj.read.split(/\n\n/, 2)
231
- @obj.close
232
- YAML.load(meta)
233
- elsif @obj.is_a? Hash
234
- @obj
235
- end.inject({}) {|h, (k,v)| h.merge(k.to_sym => v) }
236
-
237
- self.taint
238
- self.update data
239
- self[:date] = Time.parse(self[:date].gsub('/', '-')) rescue Time.now
240
- self
241
- end
242
-
243
- def [] key
244
- self.load unless self.tainted?
245
- super
246
- end
247
-
248
- def slug
249
- self[:slug] || self[:title].slugize
250
- end
251
-
252
- def summary length = nil
253
- config = @config[:summary]
254
- sum = if self[:body] =~ config[:delim]
255
- self[:body].split(config[:delim]).first
256
- else
257
- self[:body].match(/(.{1,#{length || config[:length] || config[:max]}}.*?)(\n|\Z)/m).to_s
258
- end
259
- markdown(sum.length == self[:body].length ? sum : sum.strip.sub(/\.\Z/, '&hellip;'))
260
- end
261
-
262
- def url
263
- "http://#{(@config[:url].sub("http://", '') + self.path).squeeze('/')}"
264
- end
265
- alias :permalink url
266
-
267
- def body
268
- markdown self[:body].sub(@config[:summary][:delim], '') rescue markdown self[:body]
269
- end
270
-
271
- def title() self[:title] || "an article" end
272
- def date() @config[:date, self[:date]] end
273
- def path() self[:date].strftime("/%Y/%m/%d/#{slug}/") end
274
- def author() self[:author] || @config[:author] end
275
- def to_html() self.load; super(:article) end
276
-
277
- alias :to_s to_html
278
-
279
- end
280
-
281
- class Config < Hash
282
- Defaults = {
283
- :author => ENV['USER'], # blog author
284
- :title => Dir.pwd.split('/').last, # site title
285
- :root => "index", # site index
286
- :url => "http://127.0.0.1",
287
- :date => lambda {|now| now.strftime("%d/%m/%Y") }, # date function
288
- :markdown => :smart, # use markdown
289
- :disqus => false, # disqus name
290
- :summary => {:max => 150, :delim => /~\n/}, # length of summary and delimiter
291
- :ext => 'txt', # extension for articles
292
- :cache => 28800, # cache duration (seconds)
293
- :github => {:user => "", :repos => [], :ext => 'md'}# Github username and list of repos
294
- }
295
- def initialize obj
296
- self.update Defaults
297
- self.update obj
298
- end
299
-
300
- def set key, val
301
- if val.is_a? Hash
302
- self[key].update val
303
- else
304
- self[key] = val
305
- end
306
- end
307
-
308
- def [] key, *args
309
- val = super(key)
310
- val.respond_to?(:call) ? val.call(*args) : val
311
- end
312
- end
313
-
314
- class Server
315
- attr_reader :config
316
-
317
- def initialize config = {}, &blk
318
- @config = config.is_a?(Config) ? config : Config.new(config)
319
- @config.instance_eval(&blk) if block_given?
320
- end
321
-
322
- def call env
323
- @request = Rack::Request.new env
324
- @response = Rack::Response.new
325
-
326
- return [400, {}, []] unless @request.get?
327
-
328
- path, mime = @request.path_info.split('.')
329
- route = (path || '/').split('/').reject {|i| i.empty? }
330
-
331
- response = Toto::Site.new(@config).go(route, *(mime ? mime : []))
332
-
333
- @response.body = [response[:body]]
334
- @response['Content-Length'] = response[:body].length.to_s unless response[:body].empty?
335
- @response['Content-Type'] = Rack::Mime.mime_type(".#{response[:type]}")
336
-
337
- # Set http cache headers
338
- @response['Cache-Control'] = if Toto.env == 'production'
339
- "public, max-age=#{@config[:cache]}"
340
- else
341
- "no-cache, must-revalidate"
342
- end
343
-
344
- @response['Etag'] = Digest::SHA1.hexdigest(response[:body])
345
-
346
- @response.status = response[:status]
347
- @response.finish
348
- end
349
- end
350
- end
351
-