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