georgi-shinmun 0.4.1 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/README.md +23 -31
  2. data/assets/print.css +76 -0
  3. data/assets/styles.css +91 -0
  4. data/bin/shinmun +16 -8
  5. data/config.ru +16 -0
  6. data/lib/shinmun.rb +1 -4
  7. data/lib/shinmun/blog.rb +110 -100
  8. data/lib/shinmun/comment.rb +1 -1
  9. data/lib/shinmun/handlers.rb +19 -0
  10. data/lib/shinmun/helpers.rb +1 -1
  11. data/lib/shinmun/routes.rb +25 -36
  12. data/templates/404.rhtml +4 -0
  13. data/templates/_comment_form.rhtml +21 -0
  14. data/{test/templates → templates}/_comments.rhtml +0 -0
  15. data/{example/templates → templates}/archive.rhtml +0 -1
  16. data/{example/templates → templates}/category.rhtml +1 -2
  17. data/{example/templates → templates}/category.rxml +0 -0
  18. data/{example/templates → templates}/index.rhtml +0 -1
  19. data/{example/templates → templates}/index.rxml +0 -0
  20. data/templates/layout.rhtml +44 -0
  21. data/{example/templates → templates}/page.rhtml +0 -2
  22. data/{example/templates → templates}/post.rhtml +6 -21
  23. data/test/blog_spec.rb +48 -81
  24. metadata +17 -44
  25. data/example/Rakefile +0 -41
  26. data/example/assets/images/favicon.ico +0 -0
  27. data/example/assets/images/loading.gif +0 -0
  28. data/example/assets/javascripts/1-jquery.min.js +0 -32
  29. data/example/assets/javascripts/2-jquery-form.min.js +0 -5
  30. data/example/assets/javascripts/3-comments.js +0 -45
  31. data/example/assets/javascripts/4-coderay.js +0 -13
  32. data/example/assets/print.css +0 -76
  33. data/example/assets/stylesheets/1-reset.css +0 -23
  34. data/example/assets/stylesheets/2-typo.css +0 -40
  35. data/example/assets/stylesheets/3-table.css +0 -23
  36. data/example/assets/stylesheets/4-article.css +0 -15
  37. data/example/assets/stylesheets/5-comments.css +0 -20
  38. data/example/assets/stylesheets/6-diff.css +0 -25
  39. data/example/assets/stylesheets/7-blog.css +0 -33
  40. data/example/config.ru +0 -6
  41. data/example/config/blog.yml +0 -10
  42. data/example/pages/about.md +0 -7
  43. data/example/templates/_comment_form.rhtml +0 -90
  44. data/example/templates/_comments.rhtml +0 -11
  45. data/example/templates/_pagination.rhtml +0 -10
  46. data/example/templates/comments.rhtml +0 -1
  47. data/example/templates/layout.rhtml +0 -82
  48. data/lib/shinmun/aggregations/delicious.rb +0 -57
  49. data/lib/shinmun/aggregations/flickr.rb +0 -81
  50. data/lib/shinmun/post_handler.rb +0 -16
  51. data/test/templates/archive.rhtml +0 -6
  52. data/test/templates/category.rhtml +0 -6
  53. data/test/templates/category.rxml +0 -20
  54. data/test/templates/index.rhtml +0 -4
  55. data/test/templates/index.rxml +0 -21
  56. data/test/templates/layout.rhtml +0 -9
  57. data/test/templates/page.rhtml +0 -2
  58. data/test/templates/post.rhtml +0 -3
@@ -1,7 +1,7 @@
1
1
  module Shinmun
2
2
 
3
3
  class Comment
4
-
4
+
5
5
  attr_accessor :time, :name, :email, :website, :text
6
6
 
7
7
  def initialize(attributes)
@@ -0,0 +1,19 @@
1
+ module Shinmun
2
+
3
+ class ERBHandler
4
+ def read(data)
5
+ ERB.new(data)
6
+ end
7
+ end
8
+
9
+ class PostHandler
10
+ def read(data)
11
+ Post.new(:src => data)
12
+ end
13
+
14
+ def write(post)
15
+ post.dump
16
+ end
17
+ end
18
+
19
+ end
@@ -35,7 +35,7 @@ module Shinmun
35
35
 
36
36
  def post_path(post)
37
37
  "#{base_path}/#{post.year}/#{post.month}/#{post.name}"
38
- end
38
+ end
39
39
 
40
40
  def archive_path(year, month)
41
41
  "#{base_path}/#{year}/#{month}"
@@ -9,12 +9,27 @@ Shinmun::Blog.map do
9
9
  end
10
10
 
11
11
  tag '/tags/(.*)' do |tag|
12
- render 'category.rhtml', :name => "Tag: #{tag}", :posts => posts.select { |p| p.tag_list.include?(tag) }
12
+ render 'category.rhtml', :name => "Tag: #{tag}", :posts => posts_with_tags(tag)
13
+ end
14
+
15
+ comments '/(\d+)/(\d+)/(.*)/comments' do |year, month, name|
16
+ post = find_post(year.to_i, month.to_i, name) or raise "post not found #{request.path_info}"
17
+
18
+ if params['preview']
19
+ comments = comments_for(post).push(Shinmun::Comment.new(params))
20
+ render 'post.rhtml', :post => post, :comments => comments
21
+ else
22
+ create_comment(post, params)
23
+ redirect post_path(post)
24
+ end
13
25
  end
14
26
 
15
27
  post '/(\d+)/(\d+)/(.*)' do |year, month, name|
16
- post = find_post(year.to_i, month.to_i, name)
17
- render 'post.rhtml', :post => post, :comments => comments_for(post.path)
28
+ if post = find_post(year.to_i, month.to_i, name)
29
+ render 'post.rhtml', :post => post, :comments => comments_for(post)
30
+ else
31
+ render '404.rhtml', :path => request.path_info
32
+ end
18
33
  end
19
34
 
20
35
  archive '/(\d+)/(\d+)' do |year, month|
@@ -25,47 +40,21 @@ Shinmun::Blog.map do
25
40
  render 'index.rxml', :layout => false
26
41
  end
27
42
 
28
- comments '/comments' do
29
- if params['preview'] == 'true'
30
- render 'comments.rhtml', :comments => [Shinmun::Comment.new(params)], :layout => false
31
- else
32
- post_comment(params['path'], params)
33
- render 'comments.rhtml', :comments => comments_for(params['path']), :layout => false
34
- end
35
- end
36
-
37
- javascripts '/assets/javascripts\.js' do
38
- scripts = assets['javascripts'].to_a.join
39
- if_none_match(etag(scripts)) do
40
- text scripts
41
- end
42
- end
43
-
44
- stylesheets '/assets/stylesheets\.css' do
45
- styles = assets['stylesheets'].to_a.join
46
- if_none_match(etag(styles)) do
47
- text styles
48
- end
49
- end
50
-
51
- assets '/assets/(.*)' do |path|
52
- file = assets[path] or raise "#{path} not found"
53
- if_none_match(etag(file)) do
54
- text file
55
- end
56
- end
57
-
58
- get '/$' do
43
+ index '/$' do
59
44
  render 'index.rhtml'
60
45
  end
61
46
 
62
- get '/(.*)' do |path|
47
+ page '/(.*)' do |path|
48
+ path = path.gsub('..', '')
63
49
  page = find_page(path)
64
50
 
65
51
  if page
66
52
  render 'page.rhtml', :page => page
53
+
54
+ elsif file = store[path]
55
+ text file
67
56
  else
68
- raise "page '#{path}' not found"
57
+ render '404.rhtml', :path => path
69
58
  end
70
59
  end
71
60
 
@@ -0,0 +1,4 @@
1
+ <h2>Not Found</h2>
2
+ <p>
3
+ The page <%= @path %> was not found.
4
+ </p>
@@ -0,0 +1,21 @@
1
+ <div class="comment-form">
2
+ <form action="<%= post_path @post %>/comments" method="POST">
3
+ <p>
4
+ <label>Name</label><br/>
5
+ <input type="text" name="name" size="40" value="<%= @params['name'] %>"/>
6
+ </p>
7
+ <p>
8
+ <label>Website</label><br/>
9
+ <input type="text" name="website" size="40" value="<%= @params['website'] %>"/>
10
+ </p>
11
+ <p>
12
+ <label>Comment</label><br/>
13
+ <textarea name="text" cols="60" rows="10"><%= @params['text'] %></textarea>
14
+ </p>
15
+ <p>
16
+ <input type="submit" value="Post comment"/>
17
+ <input type="checkbox" name="preview" value="1"/>
18
+ Preview
19
+ </p>
20
+ </form>
21
+ </div>
File without changes
@@ -7,6 +7,5 @@
7
7
  <h2><%= post_link post %></h2>
8
8
  <%= post.summary %>
9
9
  </div>
10
- <hr/>
11
10
  <% end %>
12
11
  </div>
@@ -1,12 +1,11 @@
1
1
  <h1><%= @name %></h1>
2
2
 
3
3
  <div class="articles">
4
- <% for post in @posts[0, 20] %>
4
+ <% for post in @posts %>
5
5
  <div class="article">
6
6
  <div class="date"><%= human_date post.date %></div>
7
7
  <h2><%= post_link post %></h2>
8
8
  <%= post.summary %>
9
9
  </div>
10
- <hr/>
11
10
  <% end %>
12
11
  </div>
File without changes
@@ -7,6 +7,5 @@
7
7
  <h2><%= post_link post %></h2>
8
8
  <%= post.summary %>
9
9
  </div>
10
- <hr/>
11
10
  <% end %>
12
11
  </div>
File without changes
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <title><%= @blog.title %></title>
5
+ <meta http-equiv="Content-Language" content="English" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
7
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="/index.rss" />
8
+ <link rel="stylesheet" media="screen" type="text/css" href="/assets/styles.css" />
9
+ <link rel="stylesheet" media="print" type="text/css" href="/assets/print.css" />
10
+ </head>
11
+ <body>
12
+ <div class="container">
13
+ <h3><a href="/"><%= @blog.title %></a> - <%= @blog.description %></h3>
14
+
15
+ <div class="menu">
16
+ <%= link_to 'Home', '/' %> -
17
+ <%= link_to 'About', '/about' %> -
18
+ <%= link_to 'Subscribe RSS', '/index.rss' %>
19
+ </div>
20
+
21
+ <%= @content %>
22
+
23
+ <hr/>
24
+
25
+ <p>
26
+ <h4>Categories</h4>
27
+ <ul>
28
+ <li><%= link_to 'Ruby', '/categories/ruby' %></li>
29
+ <li><%= link_to 'Javascript', '/categories/javascript' %></li>
30
+ </ul>
31
+ </p>
32
+
33
+ <p>
34
+ <h4>Archive</h4>
35
+ <ul>
36
+ <% for year, month in @blog.archives %>
37
+ <li><%= archive_link year, month %></li>
38
+ <% end %>
39
+ </ul>
40
+ </p>
41
+
42
+ </div>
43
+ </body>
44
+ </html>
@@ -3,5 +3,3 @@
3
3
  <div class="article">
4
4
  <%= @page.body_html %>
5
5
  </div>
6
-
7
- <hr/>
@@ -8,28 +8,15 @@
8
8
 
9
9
  <%= @post.body_html %>
10
10
 
11
- <hr/>
12
-
13
- <div style="margin:1em 0em 1em 0em; color:#666">
11
+ <p>
14
12
  <% if @post.category %>
15
- Posted in category <%= link_to @post.category, "/categories/#{urlify @post.category}" %> by <%= @blog.author %>.
13
+ Posted in category <%= link_to @post.category, "/categories/#{urlify @post.category}" %>.
16
14
  <% end %>
17
- Tagged with <%= @post.tag_list.map {|tag| link_to tag, "/tags/#{tag}" }.join(', ') %>.
18
- </div>
19
-
20
- <h6>Similar Posts</h6>
21
15
 
22
- <ul>
23
-
24
- <% for post in @blog.posts_with_tags(@post.tags) %>
25
- <% if post != @post %>
26
- <li><%= post_link post %></li>
27
- <% end %>
28
- <% end %>
29
-
30
- </ul>
31
-
32
- <hr/>
16
+ <% unless @post.tag_list.empty? %>
17
+ Tagged with <%= @post.tag_list.map {|tag| link_to tag, "/tags/#{tag}" }.join(', ') %>.
18
+ <% end %>
19
+ </p>
33
20
 
34
21
  <% if @comments %>
35
22
  <h2>Comments</h2>
@@ -44,5 +31,3 @@
44
31
  <%= render '_comment_form.rhtml', :post => @post %>
45
32
 
46
33
  </div>
47
-
48
- <hr/>
data/test/blog_spec.rb CHANGED
@@ -1,70 +1,53 @@
1
1
  require 'shinmun'
2
2
  require 'rack/mock'
3
+ require 'rexml/document'
3
4
  require 'rexml/xpath'
4
5
  require 'pp'
5
6
 
6
7
  describe Shinmun::Blog do
7
8
 
8
- TEMPLATES_DIR = File.expand_path(File.dirname(__FILE__) + '/templates')
9
- REPO = '/tmp/shinmun-test'
9
+ DIR = '/tmp/shinmun-test'
10
10
 
11
- before do
12
- FileUtils.rm_rf REPO
13
- Dir.mkdir REPO
14
- Dir.chdir REPO
15
- initialize_blog
16
- end
17
-
18
- def file(file, data)
19
- FileUtils.mkpath(File.dirname(file))
20
- open(file, 'w') { |io| io << data }
21
- `git add #{file}`
22
- end
23
-
24
- def initialize_blog
25
- `git init`
26
-
27
- file 'config/blog.yml', {
28
- 'title' => 'Title',
29
- 'description' => 'Description',
30
- 'language' => 'en',
31
- 'author' => 'The Author',
32
- 'url' => 'http://www.my-blog-url.com',
33
- 'categories' => ['Ruby', 'Javascript']
34
- }.to_yaml
11
+ attr_reader :blog
35
12
 
13
+ before do
36
14
  ENV['RACK_ENV'] = 'production'
37
- @blog = Shinmun::Blog.new(REPO)
38
- @request = Rack::MockRequest.new(@blog)
39
-
40
- Dir.mkdir 'templates'
41
15
 
42
- Dir[TEMPLATES_DIR + '/*'].each do |path|
43
- unless path.include?('~')
44
- file 'templates/' + File.basename(path), File.read(path)
45
- end
46
- end
16
+ FileUtils.rm_rf DIR
47
17
 
48
- `git commit -m 'spec'`
18
+ Shinmun::Blog.init(DIR)
19
+
20
+ @blog = Shinmun::Blog.new(DIR)
21
+
22
+ blog.config = {
23
+ :title => 'Title',
24
+ :description => 'Description',
25
+ :language => 'en',
26
+ :author => 'The Author',
27
+ :categories => ['Ruby', 'Javascript']
28
+ }
49
29
 
50
- @blog.store.load
30
+ @posts = [blog.create_post(:title => 'New post', :date => '2008-10-10', :category => 'Ruby', :body => 'Body1'),
31
+ blog.create_post(:title => 'And this', :date => '2008-10-11', :category => 'Ruby', :body => 'Body2'),
32
+ blog.create_post(:title => 'Again', :date => '2008-11-10', :category => 'Javascript', :body => 'Body3')]
51
33
 
52
- @posts = [@blog.create_post(:title => 'New post', :date => '2008-10-10', :category => 'Ruby', :body => 'Body1'),
53
- @blog.create_post(:title => 'And this', :date => '2008-10-11', :category => 'Ruby', :body => 'Body2'),
54
- @blog.create_post(:title => 'Again', :date => '2008-11-10', :category => 'Javascript', :body => 'Body3')]
34
+ @pages = [blog.create_page(:title => 'Page 1', :body => 'Body1'),
35
+ blog.create_page(:title => 'Page 2', :body => 'Body2')]
55
36
 
56
- @pages = [@blog.create_post(:title => 'Page 1', :body => 'Body1'),
57
- @blog.create_post(:title => 'Page 2', :body => 'Body2')]
37
+ blog.store.load
38
+ end
58
39
 
59
- @blog.store.load
40
+ def request(method, uri, options={})
41
+ @request = Rack::MockRequest.new(blog)
42
+ @response = @request.request(method, uri, options)
60
43
  end
61
44
 
62
45
  def get(*args)
63
- @request.get(*args)
46
+ request(:get, *args)
64
47
  end
65
48
 
66
49
  def post(*args)
67
- @request.post(*args)
50
+ request(:post, *args)
68
51
  end
69
52
 
70
53
  def xpath(xml, path)
@@ -83,51 +66,35 @@ describe Shinmun::Blog do
83
66
  titles[i].text.should == title
84
67
  summaries[i].text.to_s.strip.should == summary
85
68
  end
86
- end
69
+ end
70
+
71
+ it "should load templates" do
72
+ blog.load_template("index.rhtml").should be_kind_of(ERB)
73
+ end
87
74
 
88
75
  it "should find posts for a category" do
89
- category = @blog.find_category('ruby')
76
+ category = blog.find_category('ruby')
90
77
  category[:name].should == 'Ruby'
91
78
 
92
79
  category[:posts].should include(@posts[0])
93
80
  category[:posts].should include(@posts[1])
94
81
 
95
- category = @blog.find_category('javascript')
82
+ category = blog.find_category('javascript')
96
83
  category[:name].should == 'Javascript'
97
84
  category[:posts].should include(@posts[2])
98
85
  end
99
86
 
100
87
  it "should create a post" do
101
- @blog.create_post(:title => 'New post', :date => '2008-10-10')
102
- @blog.store.load
103
-
104
- post = @blog.find_post(2008, 10, 'new-post')
88
+ post = blog.create_post(:title => 'New post', :date => '2008-10-10')
89
+ blog.store.load
90
+
91
+ post = blog.find_post(2008, 10, 'new-post')
105
92
  post.should_not be_nil
106
93
  post.title.should == 'New post'
107
94
  post.date.should == Date.new(2008, 10, 10)
108
95
  post.name.should == 'new-post'
109
96
  end
110
97
 
111
- it "should update a post" do
112
- post = @blog.create_post(:title => 'New post', :date => '2008-10-10')
113
- @blog.update_post(post, "---\ndate: 2008-11-11\ntitle: The title\n---")
114
- @blog.store.load
115
-
116
- post = @blog.find_post(2008, 11, 'new-post')
117
- post.should_not be_nil
118
- post.title.should == 'The title'
119
- post.date.should == Date.new(2008, 11, 11)
120
- post.name.should == 'new-post'
121
- end
122
-
123
- it "should delete a post" do
124
- post = @blog.create_post(:title => 'New post', :date => '2008-10-10')
125
- @blog.delete_post(post)
126
- @blog.store.load
127
-
128
- @blog.find_post(2008, 10, 'new-post').should be_nil
129
- end
130
-
131
98
  it "should render posts" do
132
99
  xml = get('/2008/10/new-post').body
133
100
 
@@ -143,17 +110,17 @@ describe Shinmun::Blog do
143
110
  xpath(xml, '/rss/channel/title')[0].text.should == 'Ruby'
144
111
  xpath(xml, '/rss/channel/item/title')[0].text.should == 'And this'
145
112
  xpath(xml, '/rss/channel/item/pubDate')[0].text.should == "Sat, 11 Oct 2008 00:00:00 +0000"
146
- xpath(xml, '/rss/channel/item/link')[0].text.should == "http://www.my-blog-url.com/2008/10/and-this"
113
+ xpath(xml, '/rss/channel/item/link')[0].text.should == "http://example.org/2008/10/and-this"
147
114
  xpath(xml, '/rss/channel/item/title')[1].text.should == 'New post'
148
115
  xpath(xml, '/rss/channel/item/pubDate')[1].text.should == "Fri, 10 Oct 2008 00:00:00 +0000"
149
- xpath(xml, '/rss/channel/item/link')[1].text.should == "http://www.my-blog-url.com/2008/10/new-post"
116
+ xpath(xml, '/rss/channel/item/link')[1].text.should == "http://example.org/2008/10/new-post"
150
117
 
151
118
  assert_listing(get('/categories/ruby').body, [['And this', 'Body2'], ['New post', 'Body1']])
152
119
  end
153
120
 
154
121
  it "should render index and archives" do
155
- @blog.posts_for_month(2008, 10).should_not be_empty
156
- @blog.posts_for_month(2008, 11).should_not be_empty
122
+ blog.posts_for_month(2008, 10).should_not be_empty
123
+ blog.posts_for_month(2008, 11).should_not be_empty
157
124
 
158
125
  assert_listing(get('/2008/10').body, [['And this', 'Body2'], ['New post', 'Body1']])
159
126
  assert_listing(get('/').body, [['Again', 'Body3'], ['And this', 'Body2'], ['New post', 'Body1']])
@@ -170,12 +137,12 @@ describe Shinmun::Blog do
170
137
  end
171
138
 
172
139
  it "should post a comment" do
173
- post "/comments?path=posts/2008/10/new-post.md&name=Hans&text=Hallo"
174
- post "/comments?path=posts/2008/10/new-post.md&name=Peter&text=Servus"
175
-
176
- @blog.store.load
140
+ post "/2008/10/new-post/comments?name=Hans&text=Hallo"
141
+ post "/2008/10/new-post/comments?name=Peter&text=Servus"
177
142
 
178
- comments = @blog.comments_for(@posts[0].path)
143
+ blog.store.load
144
+
145
+ comments = blog.comments_for(@posts[0])
179
146
 
180
147
  comments[0].should_not be_nil
181
148
  comments[0].name.should == 'Hans'