shinmun 0.2 → 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.
- data/README.md +145 -210
- data/Rakefile +21 -53
- data/assets/print.css +76 -0
- data/assets/styles.css +91 -0
- data/bin/shinmun +24 -7
- data/config.ru +16 -0
- data/lib/shinmun/blog.rb +113 -251
- data/lib/shinmun/bluecloth_coderay.rb +21 -0
- data/lib/shinmun/comment.rb +3 -30
- data/lib/shinmun/handlers.rb +19 -0
- data/lib/shinmun/helpers.rb +46 -80
- data/lib/shinmun/post.rb +67 -98
- data/lib/shinmun/routes.rb +61 -0
- data/lib/shinmun.rb +8 -14
- data/templates/404.rhtml +4 -0
- data/templates/_comment_form.rhtml +21 -0
- data/templates/_comments.rhtml +11 -0
- data/templates/archive.rhtml +11 -0
- data/templates/category.rhtml +11 -0
- data/templates/category.rxml +20 -0
- data/templates/index.rhtml +11 -0
- data/templates/index.rxml +21 -0
- data/templates/layout.rhtml +44 -0
- data/templates/page.rhtml +5 -0
- data/templates/post.rhtml +33 -0
- data/test/blog_spec.rb +156 -0
- data/test/post_spec.rb +32 -0
- metadata +51 -16
- data/.gitignore +0 -3
- data/LICENSE +0 -18
- data/lib/shinmun/admin_controller.rb +0 -161
- data/lib/shinmun/aggregations/delicious.rb +0 -57
- data/lib/shinmun/aggregations/flickr.rb +0 -81
- data/lib/shinmun/cache.rb +0 -59
- data/lib/shinmun/controller.rb +0 -135
- data/lib/shinmun/template.rb +0 -39
data/lib/shinmun/helpers.rb
CHANGED
@@ -2,85 +2,6 @@ module Shinmun
|
|
2
2
|
|
3
3
|
module Helpers
|
4
4
|
|
5
|
-
# Render a hash as attributes for a HTML tag.
|
6
|
-
def attributes(attributes)
|
7
|
-
attributes.map { |k, v| %Q{#{k}="#{v}"} }.join(' ')
|
8
|
-
end
|
9
|
-
|
10
|
-
# Render a HTML tag with given name.
|
11
|
-
# The last argument specifies the attributes of the tag.
|
12
|
-
# The second argument may be the content of the tag.
|
13
|
-
def tag(name, *args)
|
14
|
-
text, attributes = args.first.is_a?(Hash) ? [nil, args.first] : args
|
15
|
-
"<#{name} #{attributes(attributes)}>#{text}</#{name}>"
|
16
|
-
end
|
17
|
-
|
18
|
-
# Render stylesheet link tag
|
19
|
-
def stylesheet_link_tag(*names)
|
20
|
-
options = names.last.is_a?(Hash) ? names.pop : {}
|
21
|
-
options[:media] ||= 'screen'
|
22
|
-
names.map { |name|
|
23
|
-
mtime = File.mtime("assets/#{blog.stylesheets_path}/#{name}.css").to_i
|
24
|
-
path = "/#{blog.stylesheets_path}/#{name}.css?#{mtime}"
|
25
|
-
tag :link, :href => path, :rel => 'stylesheet', :media => options[:media]
|
26
|
-
}.join("\n")
|
27
|
-
end
|
28
|
-
|
29
|
-
# Render javascript tag
|
30
|
-
def javascript_tag(*names)
|
31
|
-
names.map { |name|
|
32
|
-
mtime = File.mtime("assets/#{blog.javascripts_path}/#{name}.js").to_i
|
33
|
-
path = "/#{blog.javascripts_path}/#{name}.js?#{mtime}"
|
34
|
-
tag :script, :src => path, :type => 'text/javascript'
|
35
|
-
}.join("\n")
|
36
|
-
end
|
37
|
-
|
38
|
-
# Render an image tag
|
39
|
-
def image_tag(file, options = {})
|
40
|
-
mtime = File.mtime("assets/#{blog.images_path}/#{file}").to_i
|
41
|
-
path = "/#{blog.images_path}/#{file}?#{mtime}"
|
42
|
-
tag :img, options.merge(:src => path)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Render a link
|
46
|
-
def link_to(text, path, options = {})
|
47
|
-
tag :a, text, options.merge(:href => path)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Render a link to a post
|
51
|
-
def post_link(post)
|
52
|
-
link_to post.title, "#{blog.base_path}/#{post.path}.html"
|
53
|
-
end
|
54
|
-
|
55
|
-
# Render a link to an archive page.
|
56
|
-
def archive_link(year, month)
|
57
|
-
link_to "#{Date::MONTHNAMES[month]} #{year}", "#{blog.base_path}/#{year}/#{month}/index.html"
|
58
|
-
end
|
59
|
-
|
60
|
-
# Render a date or time in a nice human readable format.
|
61
|
-
def date(time)
|
62
|
-
"%s %d, %d" % [Date::MONTHNAMES[time.month], time.day, time.year]
|
63
|
-
end
|
64
|
-
|
65
|
-
# Render a date or time in rfc822 format. This will be used for rss rendering.
|
66
|
-
def rfc822(time)
|
67
|
-
time.strftime("%a, %d %b %Y %H:%M:%S %z")
|
68
|
-
end
|
69
|
-
|
70
|
-
def markdown(text, *args)
|
71
|
-
BlueCloth.new(text, *args).to_html
|
72
|
-
rescue => e
|
73
|
-
"#{text}<br/><br/><strong style='color:red'>#{e.message}</strong>"
|
74
|
-
end
|
75
|
-
|
76
|
-
def strip_tags(str)
|
77
|
-
str.gsub(/<\/?[^>]*>/, "")
|
78
|
-
end
|
79
|
-
|
80
|
-
def urlify(string)
|
81
|
-
string.downcase.gsub(/[ -]+/, '-').gsub(/[^-a-z0-9_]+/, '')
|
82
|
-
end
|
83
|
-
|
84
5
|
# taken form ActionView::Helpers
|
85
6
|
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
|
86
7
|
from_time = from_time.to_time if from_time.respond_to?(:to_time)
|
@@ -111,6 +32,51 @@ module Shinmun
|
|
111
32
|
else "over #{(distance_in_minutes / 525600).round} years"
|
112
33
|
end
|
113
34
|
end
|
35
|
+
|
36
|
+
def post_path(post)
|
37
|
+
"#{base_path}/#{post.year}/#{post.month}/#{post.name}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def archive_path(year, month)
|
41
|
+
"#{base_path}/#{year}/#{month}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Render a link to a post
|
45
|
+
def post_link(post)
|
46
|
+
link_to post.title, post_path(post)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Render a link to an archive page.
|
50
|
+
def archive_link(year, month)
|
51
|
+
link_to "#{Date::MONTHNAMES[month]} #{year}", archive_path(year, month)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Render a date or time in a nice human readable format.
|
55
|
+
def human_date(time)
|
56
|
+
"%s %d, %d" % [Date::MONTHNAMES[time.month], time.day, time.year]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Render a date or time in rfc822 format.
|
60
|
+
def rfc822(time)
|
61
|
+
time.strftime("%a, %d %b %Y %H:%M:%S %z")
|
62
|
+
end
|
63
|
+
|
64
|
+
# Render a link for the navigation bar. If the text of the link
|
65
|
+
# matches the @header variable, the css class will be set to acitve.
|
66
|
+
def navi_link(text, path)
|
67
|
+
link_to text, path, :class => (request.path_info == path) ? 'active' : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def html_escape(s)
|
71
|
+
s.to_s.gsub(/>/, '>').gsub(/</n, '<')
|
72
|
+
end
|
73
|
+
|
74
|
+
def diff_line_class(line)
|
75
|
+
case line[0, 1]
|
76
|
+
when '+' then 'added'
|
77
|
+
when '-' then 'deleted'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
114
81
|
end
|
115
|
-
|
116
82
|
end
|
data/lib/shinmun/post.rb
CHANGED
@@ -7,35 +7,50 @@ module Shinmun
|
|
7
7
|
# ---
|
8
8
|
# category: Ruby
|
9
9
|
# date: 2008-09-05
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# =============================
|
13
|
-
#
|
10
|
+
# title: BlueCloth, a Markdown library
|
11
|
+
# ---
|
14
12
|
# This is the summary, which is by definition the first paragraph of the
|
15
13
|
# article. The summary shows up in list views and rss feeds.
|
16
14
|
#
|
17
15
|
class Post
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
name = name.to_s
|
23
|
-
define_method(name) { @head[name] }
|
24
|
-
define_method("#{name}=") {|v| @head[name] = v }
|
25
|
-
end
|
17
|
+
%w[title author date category tags].each do |name|
|
18
|
+
define_method(name) { head[name] }
|
19
|
+
define_method("#{name}=") {|v| head[name] = v }
|
26
20
|
end
|
27
21
|
|
28
|
-
attr_accessor :
|
29
|
-
head_accessor :author, :date, :category, :tags, :languages, :header
|
22
|
+
attr_accessor :dirname, :name, :type, :src, :head, :body, :summary, :body_html, :tag_list
|
30
23
|
|
31
24
|
# Initialize empty post and set specified attributes.
|
32
25
|
def initialize(attributes={})
|
33
26
|
@head = {}
|
34
27
|
@body = ''
|
35
28
|
|
36
|
-
|
29
|
+
attributes.each do |k, v|
|
37
30
|
send "#{k}=", v
|
38
31
|
end
|
32
|
+
|
33
|
+
@type ||= 'md'
|
34
|
+
|
35
|
+
parse(src) if src
|
36
|
+
|
37
|
+
raise "post without a title" if title.nil?
|
38
|
+
|
39
|
+
@name ||= title.downcase.gsub(/[ -]+/, '-').gsub(/[^-a-z0-9_]+/, '')
|
40
|
+
@dirname = date ? "posts/#{year}/#{month}" : 'pages'
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(id, *args)
|
44
|
+
key = id.to_s
|
45
|
+
if @head.has_key?(key)
|
46
|
+
@head[key]
|
47
|
+
else
|
48
|
+
raise NoMethodError, "undefined method `#{id}' for #{self}", caller(1)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def date=(date)
|
53
|
+
@head['date'] = String === date ? Date.parse(date) : date
|
39
54
|
end
|
40
55
|
|
41
56
|
# Shortcut for year of date
|
@@ -46,111 +61,51 @@ module Shinmun
|
|
46
61
|
# Shortcut for month of date
|
47
62
|
def month
|
48
63
|
date.month
|
49
|
-
end
|
64
|
+
end
|
50
65
|
|
51
66
|
def filename
|
52
|
-
"#{
|
67
|
+
"#{name}.#{type}"
|
53
68
|
end
|
54
69
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
70
|
+
def filename=(filename)
|
71
|
+
self.name, self.type = filename.split('.')
|
72
|
+
end
|
73
|
+
|
74
|
+
def path
|
75
|
+
dirname.to_s.empty? ? filename : "#{dirname}/#{filename}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def path=(path)
|
79
|
+
list = path.split('/')
|
80
|
+
self.dirname = list[0..-2].join('/')
|
81
|
+
self.filename = list[-1]
|
64
82
|
end
|
65
83
|
|
66
84
|
# Split up the source into header and body. Load the header as
|
67
|
-
# yaml document.
|
85
|
+
# yaml document.
|
68
86
|
def parse(src)
|
69
|
-
|
70
|
-
if src =~ /---.*?\n(.*?)\n\n(.*)/m
|
87
|
+
if src =~ /\A---(.*?)---(.*)/m
|
71
88
|
@head = YAML.load($1)
|
72
89
|
@body = $2
|
73
90
|
else
|
74
|
-
|
91
|
+
raise ArgumentError, "yaml header not found in src"
|
75
92
|
end
|
76
93
|
|
77
|
-
@
|
78
|
-
@body_html = transform(body, type)
|
94
|
+
@body_html = transform(@body)
|
79
95
|
@summary = body_html.split("\n\n")[0]
|
96
|
+
@tag_list = tags.to_s.split(",").map { |s| s.strip }
|
97
|
+
@dirname = date ? "posts/#{year}/#{month}" : 'pages'
|
80
98
|
|
81
99
|
self
|
82
100
|
end
|
83
101
|
|
84
|
-
#
|
85
|
-
def parse_title
|
86
|
-
lines = body.split("\n")
|
87
|
-
|
88
|
-
case type
|
89
|
-
when 'md'
|
90
|
-
@title = lines.shift.sub(/(^#+|#+$)/,'').strip
|
91
|
-
lines.shift if lines.first.match(/^(=|-)+$/)
|
92
|
-
|
93
|
-
when 'html'
|
94
|
-
@title = lines.shift.sub(/(<h1>|\<\/h1>)/,'').strip
|
95
|
-
|
96
|
-
when 'tt'
|
97
|
-
@title = lines.shift.sub(/(^h1.)/,'').strip
|
98
|
-
end
|
99
|
-
|
100
|
-
@body = lines.join("\n")
|
101
|
-
end
|
102
|
-
|
103
|
-
# Convert to yaml for caching.
|
104
|
-
def to_yaml
|
105
|
-
head.merge('author' => author,
|
106
|
-
'path' => path,
|
107
|
-
'type' => type,
|
108
|
-
'title' => title,
|
109
|
-
'summary' => summary,
|
110
|
-
'body_html' => body_html).to_yaml
|
111
|
-
end
|
112
|
-
|
113
|
-
# Convert to string representation, used to create new posts.
|
102
|
+
# Convert to string representation
|
114
103
|
def dump
|
115
|
-
head
|
116
|
-
body = self.body.dup
|
117
|
-
|
118
|
-
if type == 'md'
|
119
|
-
body = title + "\n" + ("=" * title.size) + "\n\n" + body
|
120
|
-
end
|
121
|
-
|
122
|
-
head.each do |k, v|
|
123
|
-
head.delete(k) if v.nil? || v.empty?
|
124
|
-
end
|
125
|
-
|
126
|
-
if head.empty?
|
127
|
-
body
|
128
|
-
else
|
129
|
-
head.to_yaml + "\n\n" + body
|
130
|
-
end
|
104
|
+
head.to_yaml + "---" + body
|
131
105
|
end
|
132
106
|
|
133
|
-
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
def save
|
138
|
-
FileUtils.mkdir_p(File.dirname(filename))
|
139
|
-
File.open(filename, "w") { |io| io << dump }
|
140
|
-
self
|
141
|
-
end
|
142
|
-
|
143
|
-
# Variables used for templates.
|
144
|
-
def variables
|
145
|
-
head.merge(:author => author,
|
146
|
-
:path => path,
|
147
|
-
:title => title,
|
148
|
-
:body => body_html)
|
149
|
-
end
|
150
|
-
|
151
|
-
# Transform the body of this post according to given type.
|
152
|
-
# Defaults to Markdown.
|
153
|
-
def transform(src, type)
|
107
|
+
# Transform the body of this post. Defaults to Markdown.
|
108
|
+
def transform(src)
|
154
109
|
case type
|
155
110
|
when 'html'
|
156
111
|
RubyPants.new(src).to_html
|
@@ -161,6 +116,20 @@ module Shinmun
|
|
161
116
|
end
|
162
117
|
end
|
163
118
|
|
119
|
+
def eql?(obj)
|
120
|
+
self == obj
|
121
|
+
end
|
122
|
+
|
123
|
+
def ==(obj)
|
124
|
+
if Post === obj
|
125
|
+
if date
|
126
|
+
year == obj.year and month == obj.month and name == obj.name
|
127
|
+
else
|
128
|
+
name == obj.name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
164
133
|
end
|
165
134
|
|
166
135
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
Shinmun::Blog.map do
|
2
|
+
|
3
|
+
category_feed '/categories/(.*)\.rss' do |category|
|
4
|
+
render 'category.rxml', find_category(category).merge(:layout => false)
|
5
|
+
end
|
6
|
+
|
7
|
+
category '/categories/(.*)' do |category|
|
8
|
+
render 'category.rhtml', find_category(category)
|
9
|
+
end
|
10
|
+
|
11
|
+
tag '/tags/(.*)' do |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
|
25
|
+
end
|
26
|
+
|
27
|
+
post '/(\d+)/(\d+)/(.*)' do |year, month, name|
|
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
|
33
|
+
end
|
34
|
+
|
35
|
+
archive '/(\d+)/(\d+)' do |year, month|
|
36
|
+
render 'archive.rhtml', :year => year.to_i, :month => month.to_i, :posts => posts_for_month(year.to_i, month.to_i)
|
37
|
+
end
|
38
|
+
|
39
|
+
feed '/index\.rss' do
|
40
|
+
render 'index.rxml', :layout => false
|
41
|
+
end
|
42
|
+
|
43
|
+
index '/$' do
|
44
|
+
render 'index.rhtml'
|
45
|
+
end
|
46
|
+
|
47
|
+
page '/(.*)' do |path|
|
48
|
+
path = path.gsub('..', '')
|
49
|
+
page = find_page(path)
|
50
|
+
|
51
|
+
if page
|
52
|
+
render 'page.rhtml', :page => page
|
53
|
+
|
54
|
+
elsif file = store[path]
|
55
|
+
text file
|
56
|
+
else
|
57
|
+
render '404.rhtml', :path => path
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/lib/shinmun.rb
CHANGED
@@ -1,23 +1,17 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'fileutils'
|
3
|
-
require 'erb'
|
4
|
-
require 'yaml'
|
5
|
-
require 'time'
|
6
|
-
|
7
3
|
require 'bluecloth'
|
8
4
|
require 'rubypants'
|
5
|
+
require 'coderay'
|
6
|
+
require 'kontrol'
|
7
|
+
require 'git_store'
|
9
8
|
|
10
9
|
begin; require 'redcloth'; rescue LoadError; end
|
11
|
-
begin; require 'packr'; rescue LoadError; end
|
12
10
|
|
13
|
-
require 'shinmun/
|
14
|
-
require 'shinmun/post'
|
15
|
-
require 'shinmun/comment'
|
16
|
-
require 'shinmun/template'
|
11
|
+
require 'shinmun/bluecloth_coderay'
|
17
12
|
require 'shinmun/helpers'
|
13
|
+
require 'shinmun/handlers'
|
18
14
|
require 'shinmun/blog'
|
19
|
-
|
20
|
-
require 'shinmun/
|
21
|
-
require 'shinmun/
|
22
|
-
require 'shinmun/aggregations/flickr'
|
23
|
-
require 'shinmun/aggregations/fortythree'
|
15
|
+
require 'shinmun/routes'
|
16
|
+
require 'shinmun/post'
|
17
|
+
require 'shinmun/comment'
|
data/templates/404.rhtml
ADDED
@@ -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>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% for comment in @comments %>
|
2
|
+
<div class="comment">
|
3
|
+
<div class="top">
|
4
|
+
<%= comment.website.to_s.empty? ? comment.name : link_to(comment.name, comment.website) %> said
|
5
|
+
<%= distance_of_time_in_words(comment.time, Time.now, true) %> ago:
|
6
|
+
</div>
|
7
|
+
<div class="body">
|
8
|
+
<%= markdown(comment.text, :filter_html, :filter_styles) %>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<h1><%= "#{Date::MONTHNAMES[@month]} #{@year}" %></h1>
|
2
|
+
|
3
|
+
<div class="articles">
|
4
|
+
<% for post in @blog.posts_for_month(@year, @month) %>
|
5
|
+
<div class="article">
|
6
|
+
<div class="date"><%= human_date post.date %></div>
|
7
|
+
<h2><%= post_link post %></h2>
|
8
|
+
<%= post.summary %>
|
9
|
+
</div>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<rss version="2.0">
|
3
|
+
<channel>
|
4
|
+
<title><%= @name %></title>
|
5
|
+
<link><%= @blog.url %>/categories/<%= urlify @name %></link>
|
6
|
+
<language><%= @blog.language %></language>
|
7
|
+
<copyright><%= @blog.author %></copyright>
|
8
|
+
<pubDate><%= rfc822 Time.now %></pubDate>
|
9
|
+
<% for post in @posts[0, 20] %>
|
10
|
+
<item>
|
11
|
+
<title><%= post.title %></title>
|
12
|
+
<category><%= post.category %></category>
|
13
|
+
<description><%= strip_tags post.summary %></description>
|
14
|
+
<author><%= @author || @blog.author %></author>
|
15
|
+
<link><%= @blog.url %><%= post_path post %></link>
|
16
|
+
<pubDate><%= rfc822 post.date %></pubDate>
|
17
|
+
</item>
|
18
|
+
<% end %>
|
19
|
+
</channel>
|
20
|
+
</rss>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<rss version="2.0">
|
3
|
+
<channel>
|
4
|
+
<title><%= @blog.title %></title>
|
5
|
+
<link><%= @blog.url %></link>
|
6
|
+
<description><%= @blog.description %></description>
|
7
|
+
<language><%= @blog.language %></language>
|
8
|
+
<copyright><%= @blog.author %></copyright>
|
9
|
+
<pubDate><%= rfc822 Time.now %></pubDate>
|
10
|
+
<% for post in @blog.recent_posts %>
|
11
|
+
<item>
|
12
|
+
<title><%= post.title %></title>
|
13
|
+
<category><%= post.category %></category>
|
14
|
+
<description><%= strip_tags post.summary %></description>
|
15
|
+
<author><%= @author || @blog.author %></author>
|
16
|
+
<link><%= @blog.url %><%= post_path post %></link>
|
17
|
+
<pubDate><%= rfc822 post.date %></pubDate>
|
18
|
+
</item>
|
19
|
+
<% end %>
|
20
|
+
</channel>
|
21
|
+
</rss>
|
@@ -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>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<div class="article">
|
2
|
+
|
3
|
+
<h1><%= @post.title %></h1>
|
4
|
+
|
5
|
+
<div class="date">
|
6
|
+
<%= human_date @post.date %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<%= @post.body_html %>
|
10
|
+
|
11
|
+
<p>
|
12
|
+
<% if @post.category %>
|
13
|
+
Posted in category <%= link_to @post.category, "/categories/#{urlify @post.category}" %>.
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% unless @post.tag_list.empty? %>
|
17
|
+
Tagged with <%= @post.tag_list.map {|tag| link_to tag, "/tags/#{tag}" }.join(', ') %>.
|
18
|
+
<% end %>
|
19
|
+
</p>
|
20
|
+
|
21
|
+
<% if @comments %>
|
22
|
+
<h2>Comments</h2>
|
23
|
+
|
24
|
+
<div class="comments">
|
25
|
+
<%= render '_comments.rhtml', :comments => @comments %>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<h2>Leave a comment</h2>
|
30
|
+
|
31
|
+
<%= render '_comment_form.rhtml', :post => @post %>
|
32
|
+
|
33
|
+
</div>
|