toto 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -9,6 +9,14 @@ introduction
9
9
  toto is a git-powered, minimalist blog engine for the hackers of Oz. The engine weights around ~300 sloc at its worse.
10
10
  There is no toto client, at least for now; everything goes through git.
11
11
 
12
+ blog in 10 seconds
13
+ ------------------
14
+
15
+ $ git clone git://github.com/cloudhead/dorothy.git myblog
16
+ $ cd myblog
17
+ $ heroku create myblog
18
+ $ git push heroku master
19
+
12
20
  philosophy
13
21
  ----------
14
22
 
@@ -24,7 +32,7 @@ Oh, and everything that can be done with git, _is_.
24
32
  how it works
25
33
  ------------
26
34
 
27
- - content is entirely managed trough **git**; you get full fledged version control for free.
35
+ - content is entirely managed through **git**; you get full fledged version control for free.
28
36
  - articles are stored as _.txt_ files, with embeded metadata (in yaml format).
29
37
  - articles are processed through a markdown converter (rdiscount) by default.
30
38
  - templating is done through **ERB**.
@@ -38,14 +46,21 @@ how it works
38
46
  - summaries are generated intelligently by toto, following the `:max` setting you give it.
39
47
  - you can also define how long your summary is, by adding `~` at the end of it (`:delim`).
40
48
 
49
+ dorothy
50
+ -------
51
+
52
+ Dorothy is toto's default template, you can get it at <http://github.com/cloudhead/dorothy>. It
53
+ comes with a very minimalistic but functional template, and a _config.ru_ file to get you started.
54
+ It also includes a _.gems_ file, for heroku.
55
+
41
56
  synopsis
42
57
  --------
43
58
 
44
- One would start by forking or cloning the `dorothy` repo, to get a basic skeleton:
59
+ One would start by installing _toto_, with `sudo gem install toto`, and then forking or
60
+ cloning the `dorothy` repo, to get a basic skeleton:
45
61
 
46
- $ mkdir weblog/
62
+ $ git clone git://github.com/cloudhead/dorothy.git weblog
47
63
  $ cd weblog/
48
- $ git clone git://github.com/cloudhead/dorothy.git .
49
64
 
50
65
  One would then edit the template at will, it has the following structure:
51
66
 
@@ -108,8 +123,7 @@ Toto was designed to work well with [heroku](http://heroku.com), it makes the mo
108
123
  by setting the _Cache-Control_ and _Etag_ HTTP headers. Deploying on Heroku is really easy, just get the heroku gem,
109
124
  create a heroku app with `heroku create`, and push with `git push heroku master`.
110
125
 
111
- $ heroku create
112
- $ heroku rename weblog
126
+ $ heroku create weblog
113
127
  $ git push heroku master
114
128
  $ heroku open
115
129
 
@@ -120,12 +134,14 @@ you could add `set :author, 'John Galt'` inside the `Toto::Server.new` block. He
120
134
 
121
135
  set :author, ENV['USER'] # blog author
122
136
  set :title, Dir.pwd.split('/').last # site title
137
+ set :url, 'http://example.com' # site root URL
123
138
  set :root, "index" # page to load on /
124
139
  set :date, lambda {|now| now.strftime("%d/%m/%Y") } # date format for articles
125
140
  set :markdown, :smart # use markdown + smart-mode
126
141
  set :disqus, false # disqus id, or false
127
142
  set :summary, :max => 150, :delim => /~\n/ # length of article summary and delimiter
128
143
  set :ext, 'txt' # file extension for articles
144
+ set :cache, 28800 # cache site for 8 hours
129
145
 
130
146
  thanks
131
147
  ------
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.7
1
+ 0.2.8
@@ -6,6 +6,16 @@ class Object
6
6
  end
7
7
  end
8
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
+
9
19
  class Fixnum
10
20
  def ordinal
11
21
  # 1 => 1st
@@ -9,7 +9,7 @@ require 'builder'
9
9
 
10
10
  $:.unshift File.dirname(__FILE__)
11
11
 
12
- require 'ext'
12
+ require 'ext/ext'
13
13
 
14
14
  module Toto
15
15
  Paths = {
@@ -18,6 +18,14 @@ module Toto
18
18
  :articles => "articles"
19
19
  }
20
20
 
21
+ def self.env
22
+ ENV['RACK_ENV'] || 'production'
23
+ end
24
+
25
+ def self.env= env
26
+ ENV['RACK_ENV'] = env
27
+ end
28
+
21
29
  module Template
22
30
  def to_html page, &blk
23
31
  path = (page == :layout ? Paths[:templates] : Paths[:pages])
@@ -58,10 +66,10 @@ module Toto
58
66
  end
59
67
  end
60
68
 
61
- def archives filter = //
69
+ def archives filter = ""
62
70
  entries = ! self.articles.empty??
63
71
  self.articles.select do |a|
64
- File.basename(a) =~ /^#{filter}/
72
+ filter !~ /^\d{4}/ || File.basename(a) =~ /^#{filter}/
65
73
  end.reverse.map do |article|
66
74
  Article.new File.new(article), @config
67
75
  end : []
@@ -85,24 +93,24 @@ module Toto
85
93
  if route.first =~ /\d{4}/
86
94
  case route.size
87
95
  when 1..3
88
- [Context.new(archives(route * '-'), @config, path).render(:archives, type), 200]
96
+ Context.new(archives(route * '-'), @config, path).render(:archives, type)
89
97
  when 4
90
- [Context.new(article(route), @config, path).render(:article, type), 200]
98
+ Context.new(article(route), @config, path).render(:article, type)
91
99
  else http 400
92
100
  end
93
101
  elsif respond_to?(route = route.first.to_sym)
94
- [Context.new(send(route, type), @config, path).render(route, type), 200]
102
+ Context.new(send(route, type), @config, path).render(route, type)
95
103
  else
96
- [Context.new({}, @config, path).render(route.to_sym, type), 200]
104
+ Context.new({}, @config, path).render(route.to_sym, type)
97
105
  end
98
106
  else
99
107
  http 400
100
108
  end
101
109
 
102
110
  rescue Errno::ENOENT => e
103
- body, status = http 404
104
- ensure
105
- return :body => body, :type => type, :status => status
111
+ return :body => http(404).first, :type => :html, :status => 404
112
+ else
113
+ return :body => body || "", :type => type, :status => status || 200
106
114
  end
107
115
 
108
116
  protected
@@ -195,17 +203,15 @@ module Toto
195
203
  end
196
204
 
197
205
  def slug
198
- self[:slug] ||
199
- self[:title].downcase.gsub(/&/, 'and').gsub(/\s+/, '-').gsub(/[^a-z0-9-]/, '')
206
+ self[:slug] || self[:title].slugize
200
207
  end
201
208
 
202
209
  def summary length = nil
203
- length ||= (config = @config[:summary]).is_a?(Hash) ? config[:max] : config
204
-
210
+ config = @config[:summary]
205
211
  sum = if self[:body] =~ config[:delim]
206
212
  self[:body].split(config[:delim]).first
207
213
  else
208
- self[:body].match(/(.{1,#{length}}.*?)(\n|\Z)/m).to_s
214
+ self[:body].match(/(.{1,#{length || config[:length]}}.*?)(\n|\Z)/m).to_s
209
215
  end
210
216
  markdown(sum.length == self[:body].length ? sum : sum.strip.sub(/\.\Z/, '&hellip;'))
211
217
  end
@@ -252,7 +258,8 @@ module Toto
252
258
  :markdown => :smart, # use markdown
253
259
  :disqus => false, # disqus name
254
260
  :summary => {:max => 150, :delim => /~\n/}, # length of summary and delimiter
255
- :ext => 'txt' # extension for articles
261
+ :ext => 'txt', # extension for articles
262
+ :cache => 28800 # cache duration (seconds)
256
263
  }
257
264
  def initialize obj
258
265
  self.update Defaults
@@ -287,11 +294,16 @@ module Toto
287
294
  response = Toto::Site.new(@config).go(route, *(mime ? mime : []))
288
295
 
289
296
  @response.body = [response[:body]]
290
- @response['Content-Length'] = response[:body].length.to_s
297
+ @response['Content-Length'] = response[:body].length.to_s unless response[:body].empty?
291
298
  @response['Content-Type'] = Rack::Mime.mime_type(".#{response[:type]}")
292
299
 
293
- # Cache for one day
294
- @response['Cache-Control'] = "public, max-age=86400"
300
+ # Set http cache headers
301
+ @response['Cache-Control'] = if Toto.env == 'production'
302
+ "public, max-age=#{@config[:cache]}"
303
+ else
304
+ "no-cache, must-revalidate"
305
+ end
306
+
295
307
  @response['Etag'] = Digest::SHA1.hexdigest(response[:body])
296
308
 
297
309
  @response.status = response[:status]
@@ -83,7 +83,7 @@ context Toto do
83
83
  setup do
84
84
  @config[:markdown] = true
85
85
  @config[:date] = lambda {|t| "the time is #{t.strftime("%Y/%m/%d %H:%M")}" }
86
- @config[:summary] = 50
86
+ @config[:summary] = {:length => 50}
87
87
  end
88
88
 
89
89
  context "with the bare essentials" do
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{toto}
8
- s.version = "0.2.7"
8
+ s.version = "0.2.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["cloudhead"]
12
- s.date = %q{2010-02-04}
12
+ s.date = %q{2010-02-06}
13
13
  s.description = %q{the tiniest blog-engine in Oz.}
14
14
  s.email = %q{self@cloudhead.net}
15
15
  s.extra_rdoc_files = [
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  "README.md",
24
24
  "Rakefile",
25
25
  "VERSION",
26
- "lib/ext.rb",
26
+ "lib/ext/ext.rb",
27
27
  "lib/toto.rb",
28
28
  "test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt",
29
29
  "test/articles/2001-01-01-two-thousand-and-one.txt",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - cloudhead
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-04 00:00:00 -05:00
12
+ date: 2010-02-06 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,7 +68,7 @@ files:
68
68
  - README.md
69
69
  - Rakefile
70
70
  - VERSION
71
- - lib/ext.rb
71
+ - lib/ext/ext.rb
72
72
  - lib/toto.rb
73
73
  - test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt
74
74
  - test/articles/2001-01-01-two-thousand-and-one.txt