aerial 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -1
- data/README.md +23 -28
- data/Rakefile +27 -52
- data/VERSION +1 -1
- data/aerial.gemspec +134 -0
- data/articles/congratulations/congratulations-aerial-is-configured-correctly.article +6 -0
- data/bin/aerial +5 -0
- data/config/config.sample.ru +19 -0
- data/config/config.sample.yml +29 -0
- data/config/config.test.yml +49 -0
- data/config/config.yml +3 -3
- data/config/thin.sample.yml +13 -0
- data/examples/articles/congratulations/congratulations-aerial-is-configured-correctly.article +6 -0
- data/{lib/spec/fixtures → examples}/public/javascripts/application.js +0 -0
- data/{lib/spec/fixtures → examples}/public/javascripts/jquery-1.3.1.min.js +0 -0
- data/{lib/spec/fixtures → examples}/public/javascripts/jquery.template.js +0 -0
- data/{lib/spec/fixtures → examples}/views/article.haml +1 -1
- data/{lib/spec/fixtures → examples}/views/articles.haml +0 -0
- data/{lib/spec/fixtures → examples}/views/comment.haml +1 -1
- data/{lib/spec/fixtures → examples}/views/home.haml +0 -0
- data/{lib/spec/fixtures → examples}/views/layout.haml +1 -1
- data/examples/views/not_found.haml +1 -0
- data/{lib/spec/fixtures → examples}/views/post.haml +0 -0
- data/{lib/spec/fixtures → examples}/views/rss.haml +2 -2
- data/{lib/spec/fixtures → examples}/views/sidebar.haml +8 -0
- data/{lib/spec/fixtures → examples}/views/style.sass +0 -0
- data/{lib/features → features}/article.feature +0 -0
- data/features/home.feature +16 -0
- data/{lib/features → features}/step_definitions/article_steps.rb +0 -0
- data/{lib/features → features}/step_definitions/home_steps.rb +0 -0
- data/{lib/features → features}/support/env.rb +0 -0
- data/{lib/features → features}/support/pages/article.rb +0 -0
- data/{lib/features → features}/support/pages/homepage.rb +0 -0
- data/index.html +164 -0
- data/lib/aerial.rb +38 -87
- data/lib/aerial/app.rb +93 -0
- data/lib/aerial/article.rb +28 -30
- data/lib/aerial/base.rb +24 -32
- data/lib/aerial/comment.rb +10 -19
- data/lib/aerial/content.rb +12 -21
- data/lib/aerial/installer.rb +119 -0
- data/public/javascripts/application.js +109 -0
- data/public/javascripts/jquery-1.3.1.min.js +19 -0
- data/public/javascripts/jquery.template.js +255 -0
- data/spec/aerial_spec.rb +19 -0
- data/{lib/spec/aerial_spec.rb → spec/app_spec.rb} +32 -40
- data/{lib/spec → spec}/article_spec.rb +21 -21
- data/{lib/spec → spec}/base_spec.rb +1 -5
- data/{lib/spec → spec}/comment_spec.rb +8 -8
- data/{lib/spec → spec}/config_spec.rb +0 -0
- data/spec/fixtures/articles/congratulations-aerial-is-configured-correctly/congratulations-aerial-is-configured-correctly.article +6 -0
- data/spec/fixtures/articles/sample-article/sample-article.article +6 -0
- data/spec/fixtures/articles/test-article-one/test-article.article +7 -0
- data/spec/fixtures/articles/test-article-three/test-article.article +7 -0
- data/spec/fixtures/articles/test-article-two/comment-missing-fields.comment +8 -0
- data/spec/fixtures/articles/test-article-two/test-article.article +7 -0
- data/spec/fixtures/articles/test-article-two/test-comment.comment +10 -0
- data/{lib/spec → spec}/fixtures/config.yml +0 -0
- data/spec/fixtures/public/javascripts/application.js +109 -0
- data/spec/fixtures/public/javascripts/jquery-1.3.1.min.js +19 -0
- data/spec/fixtures/public/javascripts/jquery.template.js +255 -0
- data/spec/fixtures/views/article.haml +19 -0
- data/spec/fixtures/views/articles.haml +2 -0
- data/spec/fixtures/views/comment.haml +8 -0
- data/spec/fixtures/views/home.haml +2 -0
- data/spec/fixtures/views/layout.haml +22 -0
- data/spec/fixtures/views/not_found.haml +1 -0
- data/spec/fixtures/views/post.haml +27 -0
- data/spec/fixtures/views/rss.haml +15 -0
- data/spec/fixtures/views/sidebar.haml +29 -0
- data/spec/fixtures/views/style.sass +163 -0
- data/{lib/spec → spec}/spec_helper.rb +15 -3
- data/views/article.haml +19 -0
- data/views/articles.haml +2 -0
- data/views/comment.haml +8 -0
- data/views/home.haml +2 -0
- data/views/layout.haml +22 -0
- data/views/not_found.haml +1 -0
- data/views/post.haml +27 -0
- data/views/rss.haml +15 -0
- data/views/sidebar.haml +29 -0
- data/views/style.sass +163 -0
- metadata +86 -40
- data/lib/features/home.feature +0 -16
- data/lib/spec/fixtures/articles/sample-article/sample-article.article +0 -6
- data/lib/spec/fixtures/articles/test-article-one/test-article.article +0 -7
- data/lib/spec/fixtures/articles/test-article-three/test-article.article +0 -7
- data/lib/spec/fixtures/articles/test-article-two/comment-missing-fields.comment +0 -8
- data/lib/spec/fixtures/articles/test-article-two/test-article.article +0 -7
- data/lib/spec/fixtures/articles/test-article-two/test-comment.comment +0 -10
data/lib/aerial/app.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
module Aerial
|
2
|
+
class App < Sinatra::Default
|
3
|
+
include Aerial
|
4
|
+
|
5
|
+
before do
|
6
|
+
# kill trailing slashes for all requests except '/'
|
7
|
+
request.env['PATH_INFO'].gsub!(/\/$/, '') if request.env['PATH_INFO'] != '/'
|
8
|
+
end
|
9
|
+
|
10
|
+
# Helpers
|
11
|
+
helpers do
|
12
|
+
include Rack::Utils
|
13
|
+
include Sinatra::Cache::Helpers
|
14
|
+
include Aerial::Helper
|
15
|
+
alias_method :h, :escape_html
|
16
|
+
end
|
17
|
+
|
18
|
+
# Homepage
|
19
|
+
get '/' do
|
20
|
+
@articles = Aerial::Article.recent(:limit => 10)
|
21
|
+
cache haml(Aerial.config.views.default.to_sym)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Articles
|
25
|
+
get '/articles' do
|
26
|
+
@content_for_sidebar = partial(:sidebar)
|
27
|
+
@articles = Aerial::Article.recent(:limit => 10)
|
28
|
+
cache haml(:articles)
|
29
|
+
end
|
30
|
+
|
31
|
+
get '/feed*' do
|
32
|
+
content_type 'text/xml', :charset => 'utf-8'
|
33
|
+
@articles = Aerial::Article.all
|
34
|
+
cache haml(:rss, :layout => false)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sassy!
|
38
|
+
get '/style.css' do
|
39
|
+
content_type 'text/css', :charset => 'utf-8'
|
40
|
+
cache sass(:style)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Single page
|
44
|
+
get '/:page' do
|
45
|
+
cache haml(params[:page])
|
46
|
+
end
|
47
|
+
|
48
|
+
# Single article page
|
49
|
+
get '/:year/:month/:day/:article' do
|
50
|
+
link = [params[:year], params[:month], params[:day], params[:article]].join("/")
|
51
|
+
@content_for_sidebar = partial(:sidebar)
|
52
|
+
@article = Aerial::Article.with_permalink("/#{link}")
|
53
|
+
throw :halt, [404, not_found ] unless @article
|
54
|
+
@page_title = @article.title
|
55
|
+
cache haml(:post)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Article tags
|
59
|
+
get '/tags/:tag' do
|
60
|
+
@content_for_sidebar = partial(:sidebar)
|
61
|
+
@articles = Aerial::Article.with_tag(params[:tag])
|
62
|
+
cache haml(:articles)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Article archives
|
66
|
+
get '/archives/:year/:month' do
|
67
|
+
@content_for_sidebar = partial(:sidebar)
|
68
|
+
@articles = Aerial::Article.with_date(params[:year], params[:month])
|
69
|
+
cache haml(:articles)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add comment
|
73
|
+
post '/article/:id/comments' do
|
74
|
+
@article = Aerial::Article.find(params[:id])
|
75
|
+
throw :halt, [404, not_found ] unless @article
|
76
|
+
|
77
|
+
comment = Aerial::Comment.new(params.merge!({:referrer => request.referrer,
|
78
|
+
:user_agent => request.user_agent,
|
79
|
+
:ip => request.ip
|
80
|
+
}))
|
81
|
+
|
82
|
+
@article.comments << comment.save(@article.archive_name)
|
83
|
+
cache_expire( @article.permalink )
|
84
|
+
status 204
|
85
|
+
end
|
86
|
+
|
87
|
+
not_found do
|
88
|
+
@content_for_sidebar = partial(:sidebar)
|
89
|
+
cache haml(:not_found)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
data/lib/aerial/article.rb
CHANGED
@@ -3,7 +3,7 @@ module Aerial
|
|
3
3
|
class Article < Content
|
4
4
|
|
5
5
|
attr_reader :comments, :id, :tags, :archive_name, :body_html,
|
6
|
-
:meta, :updated_on, :
|
6
|
+
:meta, :updated_on, :publish_date, :file_name
|
7
7
|
|
8
8
|
# =============================================================================================
|
9
9
|
# PUBLIC CLASS METHODS
|
@@ -14,19 +14,19 @@ module Aerial
|
|
14
14
|
self.find_all
|
15
15
|
end
|
16
16
|
|
17
|
-
# A quick way to load an article
|
17
|
+
# A quick way to load an article by blob id
|
18
18
|
# +id+ of the blob
|
19
19
|
def self.open(id, options = {})
|
20
20
|
self.find_by_blob_id(id, options)
|
21
21
|
end
|
22
22
|
|
23
|
-
# Find a single article
|
23
|
+
# Find a single article by id
|
24
24
|
# +id+ of the blob
|
25
25
|
def self.find(id, options={})
|
26
26
|
self.find_by_id(id, options)
|
27
27
|
end
|
28
28
|
|
29
|
-
# Find a single article
|
29
|
+
# Find a single article by name
|
30
30
|
# +name+ of the article file
|
31
31
|
def self.with_name(name, options={})
|
32
32
|
self.find_by_name(name, options)
|
@@ -58,6 +58,7 @@ module Aerial
|
|
58
58
|
end
|
59
59
|
|
60
60
|
# Return true if the article file exists
|
61
|
+
# +id+
|
61
62
|
def self.exists?(id)
|
62
63
|
self.find_by_name(id) ? true : false
|
63
64
|
end
|
@@ -67,7 +68,7 @@ module Aerial
|
|
67
68
|
self.find_tags
|
68
69
|
end
|
69
70
|
|
70
|
-
# Calculate the
|
71
|
+
# Calculate the archives
|
71
72
|
def self.archives
|
72
73
|
self.find_archives
|
73
74
|
end
|
@@ -79,21 +80,21 @@ module Aerial
|
|
79
80
|
# Add a comment to the list of this Article's comments
|
80
81
|
# +comment new comment
|
81
82
|
def add_comment(comment)
|
82
|
-
self.comments << comment.save(self.archive_name) # should we overload the << method?
|
83
|
+
self.comments << comment.save(self.archive_name) # TODO: should we overload the << method?
|
83
84
|
end
|
84
85
|
|
85
|
-
#
|
86
|
+
# Make a permanent link for the article
|
86
87
|
def permalink
|
87
|
-
link = self.file_name.gsub(
|
88
|
-
"/#{
|
88
|
+
link = self.file_name.gsub(/\.article$|\.markdown$|\.md$|\.mdown$|\.mkd$|\.mkdn$/, '')
|
89
|
+
"/#{publish_date.year}/#{publish_date.month}/#{publish_date.day}/#{escape(link)}"
|
89
90
|
end
|
90
91
|
|
91
|
-
# Returns the absolute path
|
92
|
+
# Returns the absolute path to the article file
|
92
93
|
def expand_path
|
93
94
|
return "#{self.archive_expand_path}/#{self.file_name}"
|
94
95
|
end
|
95
96
|
|
96
|
-
# Returns the full path
|
97
|
+
# Returns the full path to the article archive (directory)
|
97
98
|
def archive_expand_path
|
98
99
|
return unless archive = self.archive_name
|
99
100
|
return "#{Aerial.repo.working_dir}/#{Aerial.config.articles.dir}/#{archive}"
|
@@ -113,7 +114,7 @@ module Aerial
|
|
113
114
|
end
|
114
115
|
end
|
115
116
|
|
116
|
-
# Find
|
117
|
+
# Find a single article by id
|
117
118
|
# +id+ the blob id
|
118
119
|
# +options+
|
119
120
|
def self.find_by_id(article_id, options = {})
|
@@ -126,8 +127,8 @@ module Aerial
|
|
126
127
|
raise "Article not found"
|
127
128
|
end
|
128
129
|
|
129
|
-
# Find
|
130
|
-
# This is a more efficient way of
|
130
|
+
# Find an article by blob id
|
131
|
+
# This is a more efficient way of finding an article
|
131
132
|
# However, we won't know anything else about the article such as the filename, tree, etc
|
132
133
|
# +id+ of the blob
|
133
134
|
def self.find_by_blob_id(id, options = {})
|
@@ -139,7 +140,7 @@ module Aerial
|
|
139
140
|
raise "Article doesn't exists"
|
140
141
|
end
|
141
142
|
|
142
|
-
# Returns
|
143
|
+
# Returns all articles by tag
|
143
144
|
# +tag+ the article category
|
144
145
|
def self.find_by_tag(tag, options = {})
|
145
146
|
articles = []
|
@@ -151,7 +152,8 @@ module Aerial
|
|
151
152
|
return articles
|
152
153
|
end
|
153
154
|
|
154
|
-
# Find a single article
|
155
|
+
# Find a single article by permalink
|
156
|
+
# +link+
|
155
157
|
def self.find_by_permalink(link, options={})
|
156
158
|
if blog = Aerial.repo.tree/"#{Aerial.config.articles.dir}/"
|
157
159
|
blog.contents.each do |entry|
|
@@ -162,19 +164,19 @@ module Aerial
|
|
162
164
|
return false
|
163
165
|
end
|
164
166
|
|
165
|
-
# Find all the articles
|
167
|
+
# Find all the articles by year and month
|
166
168
|
def self.find_by_date(year, month, options ={})
|
167
169
|
articles = []
|
168
170
|
self.find_all.each do |article|
|
169
|
-
if article.
|
170
|
-
article.
|
171
|
+
if article.publish_date.year == year.to_i &&
|
172
|
+
article.publish_date.month == month.to_i
|
171
173
|
articles << article
|
172
174
|
end
|
173
175
|
end
|
174
176
|
return articles
|
175
177
|
end
|
176
178
|
|
177
|
-
# Find all the articles in the
|
179
|
+
# Find all the articles in the repository
|
178
180
|
def self.find_all(options={})
|
179
181
|
articles = []
|
180
182
|
if blog = Aerial.repo.tree/"#{Aerial.config.articles.dir}/"
|
@@ -183,7 +185,7 @@ module Aerial
|
|
183
185
|
articles << self.find_article(entry, options) if article
|
184
186
|
end
|
185
187
|
end
|
186
|
-
return articles.sort_by { |article| article.
|
188
|
+
return articles.sort_by { |article| article.publish_date}.reverse
|
187
189
|
end
|
188
190
|
|
189
191
|
# Look in the given tree, find the article
|
@@ -217,23 +219,19 @@ module Aerial
|
|
217
219
|
def self.find_archives
|
218
220
|
dates = []
|
219
221
|
self.all.each do |article|
|
220
|
-
date = article.
|
222
|
+
date = article.publish_date
|
221
223
|
dates << [date.strftime("%Y/%m"), date.strftime("%B %Y")]
|
222
224
|
end
|
223
225
|
return dates.inject(Hash.new(0)) { |h,x| h[x] += 1; h }
|
224
226
|
end
|
225
227
|
|
226
228
|
# Extract the Article attributes from the file
|
229
|
+
# +blob+
|
227
230
|
def self.extract_article(blob, options={})
|
228
|
-
|
229
|
-
article = Hash.new
|
231
|
+
article = self.extract_attributes(blob.data)
|
230
232
|
article[:id] = blob.id
|
231
|
-
article[:
|
232
|
-
article[:
|
233
|
-
article[:tags] = self.extract_header("tags", file).split(/, /)
|
234
|
-
article[:published_at] = DateTime.parse(self.extract_header("published", file))
|
235
|
-
article[:body] = self.scan_for_field(file, self.body_field)
|
236
|
-
article[:body_html] = RDiscount::new( article[:body] ).to_html
|
233
|
+
article[:tags] = article[:tags].split(/, /)
|
234
|
+
article[:body_html] = RDiscount::new(article[:body]).to_html
|
237
235
|
return article
|
238
236
|
end
|
239
237
|
|
data/lib/aerial/base.rb
CHANGED
@@ -1,51 +1,43 @@
|
|
1
|
-
CONFIG = YAML.load_file( File.join(AERIAL_ROOT, 'config', 'config.yml') ) unless defined?(CONFIG)
|
2
|
-
|
3
|
-
require 'aerial/content'
|
4
|
-
require 'aerial/article'
|
5
|
-
require 'aerial/comment'
|
6
|
-
require 'aerial/vendor/cache'
|
7
|
-
require 'aerial/vendor/akismetor'
|
8
|
-
require 'aerial/config'
|
9
|
-
|
10
1
|
module Aerial
|
11
2
|
|
12
|
-
VERSION = '0.1.0'
|
13
|
-
|
14
|
-
class << self
|
15
|
-
attr_accessor :debug, :logger, :repo, :config
|
16
|
-
|
17
|
-
def log(str)
|
18
|
-
logger.debug { str } if debug
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Make sure git is added to the env path
|
23
|
-
ENV['PATH'] = "#{ENV['PATH']}:/usr/local/bin"
|
24
|
-
@logger ||= ::Logger.new(STDOUT)
|
25
|
-
@config ||= Aerial::Config.new(CONFIG)
|
26
|
-
@repo ||= Grit::Repo.new(File.join(AERIAL_ROOT, '.'))
|
27
|
-
@debug ||= false
|
28
|
-
|
29
3
|
module Helper
|
30
4
|
|
31
|
-
#
|
32
|
-
def
|
5
|
+
# Returns the current url
|
6
|
+
def url() request.url end
|
7
|
+
|
8
|
+
# Returns the request host
|
9
|
+
# TODO: just use request.host (http://rack.lighthouseapp.com/projects/22435/tickets/77-requesthost-should-answer-the-forwarded-host)
|
10
|
+
def host
|
33
11
|
if request.env['HTTP_X_FORWARDED_SERVER'] =~ /[a-z]*/
|
34
12
|
request.env['HTTP_X_FORWARDED_SERVER']
|
35
13
|
else
|
36
|
-
request.
|
14
|
+
request.host
|
37
15
|
end
|
38
16
|
end
|
39
17
|
|
40
|
-
# Returns the
|
18
|
+
# Returns the path
|
41
19
|
def path
|
42
20
|
base = "#{request.env['REQUEST_URI']}".scan(/\w+/).first
|
43
21
|
return base.blank? ? "index" : base
|
44
22
|
end
|
45
23
|
|
46
|
-
#
|
24
|
+
# Returns the absolute base url
|
25
|
+
def base_url
|
26
|
+
scheme = request.scheme
|
27
|
+
port = request.port
|
28
|
+
url = "#{scheme}://#{host}"
|
29
|
+
if scheme == "http" && port != 80 || scheme == "https" && port != 443
|
30
|
+
url << ":#{port}"
|
31
|
+
end
|
32
|
+
url << request.script_name
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates an absolute link
|
36
|
+
# +link+ link to append to the baseurl
|
37
|
+
# TODO: should we add more value to this? it seems like we might as well
|
38
|
+
# just take care of this by appending the link to base_url in the app
|
47
39
|
def full_hostname(link = "")
|
48
|
-
"
|
40
|
+
"#{base_url}#{link}"
|
49
41
|
end
|
50
42
|
|
51
43
|
# Display the page titles in proper format
|
data/lib/aerial/comment.rb
CHANGED
@@ -4,8 +4,8 @@ module Aerial
|
|
4
4
|
class Comment < Content
|
5
5
|
|
6
6
|
attr_reader :id, :permalink, :article, :spam, :file_path
|
7
|
-
attr_accessor :archive_name, :spam, :
|
8
|
-
:email, :homepage, :
|
7
|
+
attr_accessor :archive_name, :spam, :publish_date, :name, :referrer,
|
8
|
+
:email, :homepage, :ip, :user_agent, :file_name
|
9
9
|
|
10
10
|
def initialize(atts = {})
|
11
11
|
super
|
@@ -81,12 +81,12 @@ module Aerial
|
|
81
81
|
def to_s
|
82
82
|
me = ""
|
83
83
|
me << "Author: #{self.author} \n" if self.author
|
84
|
-
me << "
|
84
|
+
me << "Publish Date: #{self.publish_date} \n" if self.publish_date.to_s
|
85
85
|
me << "Email: #{self.email} \n" if self.email
|
86
86
|
me << "Homepage: #{self.homepage} \n" if self.homepage
|
87
|
-
me << "User IP: #{self.
|
87
|
+
me << "User IP: #{self.ip} \n" if self.ip
|
88
88
|
me << "User Agent: #{self.user_agent} \n" if self.user_agent
|
89
|
-
me << "Spam?: #{self.spam} \n" if self.
|
89
|
+
me << "Spam?: #{self.spam} \n" if self.spam
|
90
90
|
me << "\n#{self.body}" if self.body
|
91
91
|
return me
|
92
92
|
end
|
@@ -100,17 +100,8 @@ module Aerial
|
|
100
100
|
# Create a new Comment instance with data from the given file
|
101
101
|
def self.extract_comment_from(data, options = {})
|
102
102
|
comment_file = data.to_s
|
103
|
-
comment =
|
104
|
-
comment
|
105
|
-
comment[:user_ip] = self.extract_header("ip", comment_file)
|
106
|
-
comment[:user_agent] = self.extract_header("user-agent", comment_file)
|
107
|
-
comment[:referrer] = self.extract_header("referrer", comment_file)
|
108
|
-
comment[:permalink] = self.extract_header("permalink", comment_file)
|
109
|
-
comment[:author] = self.extract_header("author", comment_file)
|
110
|
-
comment[:email] = self.extract_header("email", comment_file)
|
111
|
-
comment[:homepage] = self.extract_header("homepage", comment_file)
|
112
|
-
comment[:published_at]= DateTime.parse(self.extract_header("published", comment_file))
|
113
|
-
comment[:body] = self.scan_for_field(comment_file, self.body_field)
|
103
|
+
comment = self.extract_attributes(comment_file)
|
104
|
+
comment.merge!(options)
|
114
105
|
return comment
|
115
106
|
end
|
116
107
|
|
@@ -118,7 +109,7 @@ module Aerial
|
|
118
109
|
def self.save_new(comment)
|
119
110
|
return false unless comment && comment.archive_name
|
120
111
|
comment.generate_name!
|
121
|
-
comment.
|
112
|
+
comment.publish_date = DateTime.now
|
122
113
|
path = File.join(Aerial.config.articles.dir, comment.archive_name, comment.name)
|
123
114
|
Dir.chdir(Aerial.repo.working_dir) do
|
124
115
|
File.open(path, 'w') do |file|
|
@@ -136,7 +127,7 @@ module Aerial
|
|
136
127
|
# Make sure the url is cleaned
|
137
128
|
def sanitize_url
|
138
129
|
return unless self.homepage
|
139
|
-
homepage.gsub!(/^(.*)/, 'http://\1') unless homepage =~ %r{^http://} or homepage.empty?
|
130
|
+
homepage.gsub!(/^(.*)/, 'http://\1') unless homepage =~ %r{^(http://|https://)} or homepage.empty?
|
140
131
|
end
|
141
132
|
|
142
133
|
# Try to prevent spam with akismet
|
@@ -144,7 +135,7 @@ module Aerial
|
|
144
135
|
{
|
145
136
|
:key => Aerial.config.akismet.key,
|
146
137
|
:blog => Aerial.config.akismet.url,
|
147
|
-
:user_ip => self.
|
138
|
+
:user_ip => self.ip,
|
148
139
|
:user_agent => self.user_agent,
|
149
140
|
:referrer => self.referrer,
|
150
141
|
:permalink => self.permalink,
|
data/lib/aerial/content.rb
CHANGED
@@ -6,7 +6,7 @@ module Aerial
|
|
6
6
|
# Base class for all the site's content
|
7
7
|
class Content
|
8
8
|
|
9
|
-
attr_reader :id, :author, :title, :body, :
|
9
|
+
attr_reader :id, :author, :title, :body, :publish_date, :archive_name, :file_name
|
10
10
|
|
11
11
|
def initialize(atts = {})
|
12
12
|
atts.each_pair { |key, value| instance_variable_set("@#{key}", value) if self.respond_to? key}
|
@@ -18,26 +18,17 @@ module Aerial
|
|
18
18
|
# PROTECTED CLASS METHODS
|
19
19
|
# =============================================================================================
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
# Returns the regular expression pattern for the header fields
|
34
|
-
def self.header_field_for(header)
|
35
|
-
exp = Regexp.new('^'+header+'\s*:(.*)$', Regexp::IGNORECASE)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns the regular expression pattern for the body field
|
39
|
-
def self.body_field
|
40
|
-
exp = Regexp.new('^\n(.*)$', Regexp::MULTILINE)
|
21
|
+
def self.extract_attributes(content, options={})
|
22
|
+
attributes = Hash.new
|
23
|
+
header, body = content.split(/\n\n/, 2)
|
24
|
+
attributes[:body] = body.strip if body
|
25
|
+
header.each do |line|
|
26
|
+
field, data = line.split(/:/, 2)
|
27
|
+
field = field.downcase.strip.gsub(' ', '_').gsub('-', '_')
|
28
|
+
attributes[field.to_sym] = data.to_s.strip
|
29
|
+
end
|
30
|
+
attributes[:publish_date] = DateTime.parse(attributes[:publish_date]) if attributes[:publish_date]
|
31
|
+
return attributes
|
41
32
|
end
|
42
33
|
|
43
34
|
# Look for <code> blocks and convert it for syntax highlighting
|