add comments and refactor out common page/post methods into Convertible module
This commit is contained in:
parent
d8bdb6d366
commit
e4d07dc547
|
@ -15,8 +15,9 @@ require 'redcloth'
|
||||||
|
|
||||||
# internal requires
|
# internal requires
|
||||||
require 'autoblog/site'
|
require 'autoblog/site'
|
||||||
require 'autoblog/post'
|
require 'autoblog/convertible'
|
||||||
require 'autoblog/page'
|
require 'autoblog/page'
|
||||||
|
require 'autoblog/post'
|
||||||
require 'autoblog/filters'
|
require 'autoblog/filters'
|
||||||
|
|
||||||
module AutoBlog
|
module AutoBlog
|
||||||
|
|
|
@ -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
|
|
@ -1,9 +1,17 @@
|
||||||
module AutoBlog
|
module AutoBlog
|
||||||
|
|
||||||
class Page
|
class Page
|
||||||
|
include Convertible
|
||||||
|
|
||||||
attr_accessor :ext
|
attr_accessor :ext
|
||||||
attr_accessor :data, :content
|
attr_accessor :data, :content
|
||||||
|
|
||||||
|
# Initialize a new Page.
|
||||||
|
# +base+ is the String path to the <source>
|
||||||
|
# +dir+ is the String path between <source> and the file
|
||||||
|
# +name+ is the String filename of the post file
|
||||||
|
#
|
||||||
|
# Returns <Page>
|
||||||
def initialize(base, dir, name)
|
def initialize(base, dir, name)
|
||||||
@base = base
|
@base = base
|
||||||
@dir = dir
|
@dir = dir
|
||||||
|
@ -12,36 +20,31 @@ module AutoBlog
|
||||||
self.data = {}
|
self.data = {}
|
||||||
|
|
||||||
self.process(name)
|
self.process(name)
|
||||||
self.read_yaml(base, dir, name)
|
self.read_yaml(File.join(base, dir), name)
|
||||||
self.set_defaults
|
self.set_defaults
|
||||||
self.transform
|
self.transform
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Extract information from the post filename
|
||||||
|
# +name+ is the String filename of the post file
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def process(name)
|
def process(name)
|
||||||
self.ext = File.extname(name)
|
self.ext = File.extname(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_yaml(base, dir, name)
|
# Set the data defaults.
|
||||||
self.content = File.read(File.join(base, dir, name))
|
#
|
||||||
|
# Returns nothing
|
||||||
if self.content =~ /^(---\n.*?)\n---\n/
|
|
||||||
self.content = self.content[($1.size + 5)..-1]
|
|
||||||
|
|
||||||
self.data = YAML.load($1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_defaults
|
def set_defaults
|
||||||
self.data["layout"] ||= "default"
|
self.data["layout"] ||= "default"
|
||||||
end
|
end
|
||||||
|
|
||||||
def transform
|
# Add any necessary layouts to this post
|
||||||
if self.ext == ".textile"
|
# +layouts+ is a Hash of {"name" => "layout"}
|
||||||
self.ext = ".html"
|
# +site_payload+ is the site payload hash
|
||||||
self.content = RedCloth.new(self.content).to_html
|
#
|
||||||
end
|
# Returns nothing
|
||||||
end
|
|
||||||
|
|
||||||
def add_layout(layouts, site_payload)
|
def add_layout(layouts, site_payload)
|
||||||
payload = {"page" => self.data}.merge(site_payload)
|
payload = {"page" => self.data}.merge(site_payload)
|
||||||
self.content = Liquid::Template.parse(self.content).render(payload, [AutoBlog::Filters])
|
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])
|
self.content = Liquid::Template.parse(layout).render(payload, [AutoBlog::Filters])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Write the generated page file to the destination directory.
|
||||||
|
# +dest+ is the String path to the destination dir
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def write(dest)
|
def write(dest)
|
||||||
FileUtils.mkdir_p(File.join(dest, @dir))
|
FileUtils.mkdir_p(File.join(dest, @dir))
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,14 @@ module AutoBlog
|
||||||
|
|
||||||
class Post
|
class Post
|
||||||
include Comparable
|
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 <Bool>
|
||||||
def self.valid?(name)
|
def self.valid?(name)
|
||||||
name =~ MATCHER
|
name =~ MATCHER
|
||||||
end
|
end
|
||||||
|
@ -12,6 +17,11 @@ module AutoBlog
|
||||||
attr_accessor :date, :slug, :ext
|
attr_accessor :date, :slug, :ext
|
||||||
attr_accessor :data, :content, :output
|
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 <Post>
|
||||||
def initialize(base, name)
|
def initialize(base, name)
|
||||||
@base = base
|
@base = base
|
||||||
@name = name
|
@name = name
|
||||||
|
@ -22,10 +32,17 @@ module AutoBlog
|
||||||
self.transform
|
self.transform
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Spaceship is based on Post#date
|
||||||
|
#
|
||||||
|
# Returns -1, 0, 1
|
||||||
def <=>(other)
|
def <=>(other)
|
||||||
self.date <=> other.date
|
self.date <=> other.date
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Extract information from the post filename
|
||||||
|
# +name+ is the String filename of the post file
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def process(name)
|
def process(name)
|
||||||
m, date, slug, ext = *name.match(MATCHER)
|
m, date, slug, ext = *name.match(MATCHER)
|
||||||
self.date = Time.parse(date)
|
self.date = Time.parse(date)
|
||||||
|
@ -33,40 +50,49 @@ module AutoBlog
|
||||||
self.ext = ext
|
self.ext = ext
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The generated directory into which the post will be placed
|
||||||
|
# upon generation. e.g. "/2008/11/05/"
|
||||||
|
#
|
||||||
|
# Returns <String>
|
||||||
def dir
|
def dir
|
||||||
self.date.strftime("/%Y/%m/%d/")
|
self.date.strftime("/%Y/%m/%d/")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The generated relative url of this post
|
||||||
|
# e.g. /2008/11/05/my-awesome-post.html
|
||||||
|
#
|
||||||
|
# Returns <String>
|
||||||
def url
|
def url
|
||||||
self.dir + self.slug + ".html"
|
self.dir + self.slug + ".html"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The UID for this post (useful in feeds)
|
||||||
|
# e.g. /2008/11/05/my-awesome-post
|
||||||
|
#
|
||||||
|
# Returns <String>
|
||||||
def id
|
def id
|
||||||
self.dir + self.slug
|
self.dir + self.slug
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_yaml(base, name)
|
# Set the data defaults.
|
||||||
self.content = File.read(File.join(base, name))
|
#
|
||||||
|
# Returns nothing
|
||||||
if self.content =~ /^(---\n.*?)\n---\n/
|
|
||||||
self.content = self.content[($1.size + 5)..-1]
|
|
||||||
|
|
||||||
self.data = YAML.load($1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_defaults
|
def set_defaults
|
||||||
self.data["layout"] ||= "default"
|
self.data["layout"] ||= "default"
|
||||||
end
|
end
|
||||||
|
|
||||||
def transform
|
# Calculate related posts.
|
||||||
self.content = RedCloth.new(self.content).to_html
|
#
|
||||||
end
|
# Returns [<Post>]
|
||||||
|
|
||||||
def related_posts(posts)
|
def related_posts(posts)
|
||||||
related = posts - [self]
|
related = posts - [self]
|
||||||
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)
|
def add_layout(layouts, site_payload)
|
||||||
related = related_posts(site_payload["site"]["posts"])
|
related = related_posts(site_payload["site"]["posts"])
|
||||||
|
|
||||||
|
@ -79,6 +105,10 @@ module AutoBlog
|
||||||
self.output = Liquid::Template.parse(layout).render(payload, [AutoBlog::Filters])
|
self.output = Liquid::Template.parse(layout).render(payload, [AutoBlog::Filters])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Write the generated post file to the destination directory.
|
||||||
|
# +dest+ is the String path to the destination dir
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def write(dest)
|
def write(dest)
|
||||||
FileUtils.mkdir_p(File.join(dest, self.dir))
|
FileUtils.mkdir_p(File.join(dest, self.dir))
|
||||||
|
|
||||||
|
@ -88,6 +118,9 @@ module AutoBlog
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Convert this post into a Hash for use in Liquid templates.
|
||||||
|
#
|
||||||
|
# Returns <Hash>
|
||||||
def to_liquid
|
def to_liquid
|
||||||
{ "title" => self.data["title"] || "",
|
{ "title" => self.data["title"] || "",
|
||||||
"url" => self.url,
|
"url" => self.url,
|
||||||
|
|
|
@ -4,6 +4,13 @@ module AutoBlog
|
||||||
attr_accessor :source, :dest
|
attr_accessor :source, :dest
|
||||||
attr_accessor :layouts, :posts
|
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 <Site>
|
||||||
def initialize(source, dest)
|
def initialize(source, dest)
|
||||||
self.source = source
|
self.source = source
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
|
@ -11,6 +18,10 @@ module AutoBlog
|
||||||
self.posts = []
|
self.posts = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Do the actual work of processing the site and generating the
|
||||||
|
# real deal.
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def process
|
def process
|
||||||
self.read_layouts
|
self.read_layouts
|
||||||
self.read_posts
|
self.read_posts
|
||||||
|
@ -18,6 +29,10 @@ module AutoBlog
|
||||||
self.transform_pages
|
self.transform_pages
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Read all the files in <source>/_layouts into memory for
|
||||||
|
# later use.
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def read_layouts
|
def read_layouts
|
||||||
base = File.join(self.source, "_layouts")
|
base = File.join(self.source, "_layouts")
|
||||||
entries = Dir.entries(base)
|
entries = Dir.entries(base)
|
||||||
|
@ -31,6 +46,10 @@ module AutoBlog
|
||||||
# ignore missing layout dir
|
# ignore missing layout dir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Read all the files in <source>/posts and create a new Post
|
||||||
|
# object with each one.
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def read_posts
|
def read_posts
|
||||||
base = File.join(self.source, "posts")
|
base = File.join(self.source, "posts")
|
||||||
entries = Dir.entries(base)
|
entries = Dir.entries(base)
|
||||||
|
@ -45,6 +64,9 @@ module AutoBlog
|
||||||
# ignore missing layout dir
|
# ignore missing layout dir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Write each post to <dest>/<year>/<month>/<day>/<slug>
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def write_posts
|
def write_posts
|
||||||
self.posts.each do |post|
|
self.posts.each do |post|
|
||||||
post.add_layout(self.layouts, site_payload)
|
post.add_layout(self.layouts, site_payload)
|
||||||
|
@ -52,6 +74,11 @@ module AutoBlog
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Recursively transform and write all non-post pages to <dest>/
|
||||||
|
# +dir+ is the String path part representing the path from
|
||||||
|
# <source> to the currently processing dir (default '')
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
def transform_pages(dir = '')
|
def transform_pages(dir = '')
|
||||||
base = File.join(self.source, dir)
|
base = File.join(self.source, dir)
|
||||||
entries = Dir.entries(base)
|
entries = Dir.entries(base)
|
||||||
|
@ -74,6 +101,9 @@ module AutoBlog
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The Hash payload containing site-wide data
|
||||||
|
#
|
||||||
|
# Returns {"site" => {"time" => <Time>, "posts" => [<Post>]}}
|
||||||
def site_payload
|
def site_payload
|
||||||
{"site" => {"time" => Time.now, "posts" => self.posts.sort.reverse}}
|
{"site" => {"time" => Time.now, "posts" => self.posts.sort.reverse}}
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ class TestPost < Test::Unit::TestCase
|
||||||
|
|
||||||
assert_equal Time.parse("2008-10-19"), p.date
|
assert_equal Time.parse("2008-10-19"), p.date
|
||||||
assert_equal "foo-bar", p.slug
|
assert_equal "foo-bar", p.slug
|
||||||
assert_equal "textile", p.ext
|
assert_equal ".textile", p.ext
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url
|
def test_url
|
||||||
|
@ -36,6 +36,7 @@ class TestPost < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_transform
|
def test_transform
|
||||||
p = Post.allocate
|
p = Post.allocate
|
||||||
|
p.process("2008-10-18-foo-bar.textile")
|
||||||
p.read_yaml(File.join(File.dirname(__FILE__), *%w[source posts]), "2008-10-18-foo-bar.textile")
|
p.read_yaml(File.join(File.dirname(__FILE__), *%w[source posts]), "2008-10-18-foo-bar.textile")
|
||||||
p.transform
|
p.transform
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue