lib/jekyll/post.rb in jekyll-0.12.1 vs lib/jekyll/post.rb in jekyll-1.0.0.beta1
- old
+ new
@@ -1,21 +1,21 @@
module Jekyll
-
class Post
include Comparable
include Convertible
class << self
attr_accessor :lsi
end
+ # Valid post name regex.
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
# Post name validator. Post filenames must be like:
- # 2008-11-05-my-awesome-post.textile
+ # 2008-11-05-my-awesome-post.textile
#
- # Returns <Bool>
+ # Returns true if valid, false if not.
def self.valid?(name)
name =~ MATCHER
end
attr_accessor :site
@@ -23,31 +23,31 @@
attr_accessor :date, :slug, :published, :tags, :categories
attr_reader :name
# Initialize this Post instance.
- # +site+ is the Site
- # +base+ is the String path to the dir containing the post file
- # +name+ is the String filename of the post file
- # +categories+ is an Array of Strings for the categories for this post
#
- # Returns <Post>
+ # site - The Site.
+ # base - The String path to the dir containing the post file.
+ # name - The String filename of the post file.
+ #
+ # Returns the new Post.
def initialize(site, source, dir, name)
@site = site
- @base = File.join(source, dir, '_posts')
+ @base = self.containing_dir(source, dir)
@name = name
self.categories = dir.split('/').reject { |x| x.empty? }
self.process(name)
begin
self.read_yaml(@base, name)
rescue Exception => msg
- raise FatalException.new("#{msg} in #{@base}/#{name}")
+ raise FatalException.new("#{msg} in #{@base}/#{name}")
end
- #If we've added a date and time to the yaml, use that instead of the filename date
- #Means we'll sort correctly.
+ # If we've added a date and time to the YAML, use that instead of the
+ # filename date. Means we'll sort correctly.
if self.data.has_key?('date')
# ensure Time via to_s and reparse
self.date = Time.parse(self.data["date"].to_s)
end
@@ -62,25 +62,46 @@
if self.categories.empty?
self.categories = self.data.pluralized_array('category', 'categories')
end
end
- # Spaceship is based on Post#date, slug
+ # Get the full path to the directory containing the post files
+ def containing_dir(source, dir)
+ return File.join(source, dir, '_posts')
+ end
+
+ # Read the YAML frontmatter.
#
+ # base - The String path to the dir containing the file.
+ # name - The String filename of the file.
+ #
+ # Returns nothing.
+ def read_yaml(base, name)
+ super(base, name)
+ self.data['layout'] = 'post' unless self.data.has_key?('layout')
+ self.data
+ end
+
+ # Compares Post objects. First compares the Post date. If the dates are
+ # equal, it compares the Post slugs.
+ #
+ # other - The other Post we are comparing to.
+ #
# Returns -1, 0, 1
def <=>(other)
cmp = self.date <=> other.date
if 0 == cmp
cmp = self.slug <=> other.slug
end
return cmp
end
- # Extract information from the post filename
- # +name+ is the String filename of the post file
+ # Extract information from the post filename.
#
- # Returns nothing
+ # name - The String filename of the post file.
+ #
+ # Returns nothing.
def process(name)
m, cats, date, slug, ext = *name.match(MATCHER)
self.date = Time.parse(date)
self.slug = slug
self.ext = ext
@@ -89,22 +110,21 @@
end
# The generated directory into which the post will be placed
# upon generation. This is derived from the permalink or, if
# permalink is absent, set to the default date
- # e.g. "/2008/11/05/" if the permalink style is :date, otherwise nothing
+ # e.g. "/2008/11/05/" if the permalink style is :date, otherwise nothing.
#
- # Returns <String>
+ # Returns the String directory.
def dir
File.dirname(url)
end
- # The full path and filename of the post.
- # Defined in the YAML of the post body
- # (Optional)
+ # The full path and filename of the post. Defined in the YAML of the post
+ # body (optional).
#
- # Returns <String>
+ # Returns the String permalink.
def permalink
self.data && self.data['permalink']
end
def template
@@ -118,14 +138,14 @@
else
self.site.permalink_style.to_s
end
end
- # The generated relative url of this post
+ # The generated relative url of this post.
# e.g. /2008/11/05/my-awesome-post.html
#
- # Returns <String>
+ # Returns the String URL.
def url
return @url if @url
url = if permalink
permalink
@@ -135,11 +155,11 @@
"month" => date.strftime("%m"),
"day" => date.strftime("%d"),
"title" => CGI.escape(slug),
"i_day" => date.strftime("%d").to_i.to_s,
"i_month" => date.strftime("%m").to_i.to_s,
- "categories" => categories.map { |c| URI.escape(c) }.join('/'),
+ "categories" => categories.map { |c| URI.escape(c.to_s) }.join('/'),
"output_ext" => self.output_ext
}.inject(template) { |result, token|
result.gsub(/:#{Regexp.escape token.first}/, token.last)
}.gsub(/\/\//, "/")
end
@@ -148,29 +168,32 @@
@url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
@url += "/" if url =~ /\/$/
@url
end
- # The UID for this post (useful in feeds)
+ # The UID for this post (useful in feeds).
# e.g. /2008/11/05/my-awesome-post
#
- # Returns <String>
+ # Returns the String UID.
def id
File.join(self.dir, self.slug)
end
# Calculate related posts.
#
- # Returns [<Post>]
+ # Returns an Array of related Posts.
def related_posts(posts)
return [] unless posts.size > 1
if self.site.lsi
self.class.lsi ||= begin
- puts "Running the classifier... this could take a while."
- lsi = Classifier::LSI.new
+ puts "Starting the classifier..."
+ lsi = Classifier::LSI.new(:auto_rebuild => false)
+ $stdout.print(" Populating LSI... ");$stdout.flush
posts.each { |x| $stdout.print(".");$stdout.flush;lsi.add_item(x) }
+ $stdout.print("\n Rebuilding LSI index... ")
+ lsi.build_index
puts ""
lsi
end
related = self.class.lsi.find_related(self.content, 11)
@@ -178,15 +201,16 @@
else
(posts - [self])[0..9]
end
end
- # Add any necessary layouts to this post
- # +layouts+ is a Hash of {"name" => "layout"}
- # +site_payload+ is the site payload hash
+ # Add any necessary layouts to this post.
#
- # Returns nothing
+ # layouts - A Hash of {"name" => "layout"}.
+ # site_payload - The site payload hash.
+ #
+ # Returns nothing.
def render(layouts, site_payload)
# construct payload
payload = {
"site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
"page" => self.to_liquid
@@ -194,35 +218,37 @@
do_layout(payload, layouts)
end
# Obtain destination path.
- # +dest+ is the String path to the destination dir
#
- # Returns destination file path.
+ # dest - The String path to the destination dir.
+ #
+ # Returns destination file path String.
def destination(dest)
# The url needs to be unescaped in order to preserve the correct filename
path = File.join(dest, CGI.unescape(self.url))
path = File.join(path, "index.html") if template[/\.html$/].nil?
path
end
# Write the generated post file to the destination directory.
- # +dest+ is the String path to the destination dir
#
- # Returns nothing
+ # dest - The String path to the destination dir.
+ #
+ # Returns nothing.
def write(dest)
path = destination(dest)
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'w') do |f|
f.write(self.output)
end
end
# Convert this post into a Hash for use in Liquid templates.
#
- # Returns <Hash>
+ # Returns the representative Hash.
def to_liquid
self.data.deep_merge({
"title" => self.data["title"] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' '),
"url" => self.url,
"date" => self.date,
@@ -232,10 +258,11 @@
"previous" => self.previous,
"tags" => self.tags,
"content" => self.content })
end
+ # Returns the shorthand String identifier of this Post.
def inspect
"<Post: #{self.id}>"
end
def next
@@ -255,7 +282,6 @@
else
nil
end
end
end
-
end