georgi-shinmun 0.4.1 → 0.5

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.
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'