diff --git a/lib/autoblog.rb b/lib/autoblog.rb index f4edafbf..0852ec38 100644 --- a/lib/autoblog.rb +++ b/lib/autoblog.rb @@ -15,8 +15,9 @@ require 'redcloth' # internal requires require 'autoblog/site' -require 'autoblog/post' +require 'autoblog/convertible' require 'autoblog/page' +require 'autoblog/post' require 'autoblog/filters' module AutoBlog diff --git a/lib/autoblog/convertible.rb b/lib/autoblog/convertible.rb new file mode 100644 index 00000000..768913cf --- /dev/null +++ b/lib/autoblog/convertible.rb @@ -0,0 +1,28 @@ +module AutoBlog + module Convertible + # Read the YAML frontmatter + # +base+ is the String path to the dir containing the file + # +name+ is the String filename of the file + # + # Returns nothing + def read_yaml(base, name) + self.content = File.read(File.join(base, name)) + + if self.content =~ /^(---\n.*?)\n---\n/ + self.content = self.content[($1.size + 5)..-1] + + self.data = YAML.load($1) + end + end + + # Transform the contents based on the file extension. + # + # Returns nothing + def transform + if self.ext == ".textile" + self.ext = ".html" + self.content = RedCloth.new(self.content).to_html + end + end + end +end \ No newline at end of file diff --git a/lib/autoblog/page.rb b/lib/autoblog/page.rb index ce42dd58..924ae2bf 100644 --- a/lib/autoblog/page.rb +++ b/lib/autoblog/page.rb @@ -1,9 +1,17 @@ module AutoBlog class Page + include Convertible + attr_accessor :ext attr_accessor :data, :content + # Initialize a new Page. + # +base+ is the String path to the + # +dir+ is the String path between and the file + # +name+ is the String filename of the post file + # + # Returns def initialize(base, dir, name) @base = base @dir = dir @@ -12,36 +20,31 @@ module AutoBlog self.data = {} self.process(name) - self.read_yaml(base, dir, name) + self.read_yaml(File.join(base, dir), name) self.set_defaults self.transform end + # Extract information from the post filename + # +name+ is the String filename of the post file + # + # Returns nothing def process(name) self.ext = File.extname(name) end - def read_yaml(base, dir, name) - self.content = File.read(File.join(base, dir, name)) - - if self.content =~ /^(---\n.*?)\n---\n/ - self.content = self.content[($1.size + 5)..-1] - - self.data = YAML.load($1) - end - end - + # Set the data defaults. + # + # Returns nothing def set_defaults self.data["layout"] ||= "default" end - def transform - if self.ext == ".textile" - self.ext = ".html" - self.content = RedCloth.new(self.content).to_html - end - end - + # Add any necessary layouts to this post + # +layouts+ is a Hash of {"name" => "layout"} + # +site_payload+ is the site payload hash + # + # Returns nothing def add_layout(layouts, site_payload) payload = {"page" => self.data}.merge(site_payload) self.content = Liquid::Template.parse(self.content).render(payload, [AutoBlog::Filters]) @@ -52,6 +55,10 @@ module AutoBlog self.content = Liquid::Template.parse(layout).render(payload, [AutoBlog::Filters]) end + # Write the generated page file to the destination directory. + # +dest+ is the String path to the destination dir + # + # Returns nothing def write(dest) FileUtils.mkdir_p(File.join(dest, @dir)) diff --git a/lib/autoblog/post.rb b/lib/autoblog/post.rb index 2b12f9c5..6a21acac 100644 --- a/lib/autoblog/post.rb +++ b/lib/autoblog/post.rb @@ -2,9 +2,14 @@ module AutoBlog class Post include Comparable + include Convertible - MATCHER = /^(\d+-\d+-\d+)-(.*)\.([^.]+)$/ + MATCHER = /^(\d+-\d+-\d+)-(.*)(\.[^.]+)$/ + # Post name validator. Post filenames must be like: + # 2008-11-05-my-awesome-post.textile + # + # Returns def self.valid?(name) name =~ MATCHER end @@ -12,6 +17,11 @@ module AutoBlog attr_accessor :date, :slug, :ext attr_accessor :data, :content, :output + # Initialize this Post instance. + # +base+ is the String path to the dir containing the post file + # +name+ is the String filename of the post file + # + # Returns def initialize(base, name) @base = base @name = name @@ -22,10 +32,17 @@ module AutoBlog self.transform end + # Spaceship is based on Post#date + # + # Returns -1, 0, 1 def <=>(other) self.date <=> other.date end + # Extract information from the post filename + # +name+ is the String filename of the post file + # + # Returns nothing def process(name) m, date, slug, ext = *name.match(MATCHER) self.date = Time.parse(date) @@ -33,40 +50,49 @@ module AutoBlog self.ext = ext end + # The generated directory into which the post will be placed + # upon generation. e.g. "/2008/11/05/" + # + # Returns def dir self.date.strftime("/%Y/%m/%d/") end + # The generated relative url of this post + # e.g. /2008/11/05/my-awesome-post.html + # + # Returns def url self.dir + self.slug + ".html" end + # The UID for this post (useful in feeds) + # e.g. /2008/11/05/my-awesome-post + # + # Returns def id self.dir + self.slug end - def read_yaml(base, name) - self.content = File.read(File.join(base, name)) - - if self.content =~ /^(---\n.*?)\n---\n/ - self.content = self.content[($1.size + 5)..-1] - - self.data = YAML.load($1) - end - end - + # Set the data defaults. + # + # Returns nothing def set_defaults self.data["layout"] ||= "default" end - def transform - self.content = RedCloth.new(self.content).to_html - end - + # Calculate related posts. + # + # Returns [] def related_posts(posts) related = posts - [self] end + # Add any necessary layouts to this post + # +layouts+ is a Hash of {"name" => "layout"} + # +site_payload+ is the site payload hash + # + # Returns nothing def add_layout(layouts, site_payload) related = related_posts(site_payload["site"]["posts"]) @@ -79,6 +105,10 @@ module AutoBlog self.output = Liquid::Template.parse(layout).render(payload, [AutoBlog::Filters]) end + # Write the generated post file to the destination directory. + # +dest+ is the String path to the destination dir + # + # Returns nothing def write(dest) FileUtils.mkdir_p(File.join(dest, self.dir)) @@ -88,6 +118,9 @@ module AutoBlog end end + # Convert this post into a Hash for use in Liquid templates. + # + # Returns def to_liquid { "title" => self.data["title"] || "", "url" => self.url, diff --git a/lib/autoblog/site.rb b/lib/autoblog/site.rb index 4d3286cd..b2864a48 100644 --- a/lib/autoblog/site.rb +++ b/lib/autoblog/site.rb @@ -4,6 +4,13 @@ module AutoBlog attr_accessor :source, :dest attr_accessor :layouts, :posts + # Initialize the site + # +source+ is String path to the source directory containing + # the proto-site + # +dest+ is the String path to the directory where the generated + # site should be written + # + # Returns def initialize(source, dest) self.source = source self.dest = dest @@ -11,6 +18,10 @@ module AutoBlog self.posts = [] end + # Do the actual work of processing the site and generating the + # real deal. + # + # Returns nothing def process self.read_layouts self.read_posts @@ -18,6 +29,10 @@ module AutoBlog self.transform_pages end + # Read all the files in /_layouts into memory for + # later use. + # + # Returns nothing def read_layouts base = File.join(self.source, "_layouts") entries = Dir.entries(base) @@ -31,6 +46,10 @@ module AutoBlog # ignore missing layout dir end + # Read all the files in /posts and create a new Post + # object with each one. + # + # Returns nothing def read_posts base = File.join(self.source, "posts") entries = Dir.entries(base) @@ -45,6 +64,9 @@ module AutoBlog # ignore missing layout dir end + # Write each post to //// + # + # Returns nothing def write_posts self.posts.each do |post| post.add_layout(self.layouts, site_payload) @@ -52,6 +74,11 @@ module AutoBlog end end + # Recursively transform and write all non-post pages to / + # +dir+ is the String path part representing the path from + # to the currently processing dir (default '') + # + # Returns nothing def transform_pages(dir = '') base = File.join(self.source, dir) entries = Dir.entries(base) @@ -74,6 +101,9 @@ module AutoBlog end end + # The Hash payload containing site-wide data + # + # Returns {"site" => {"time" =>