toto 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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