ace/lib/ace.rb

196 lines
4.5 KiB
Ruby
Raw Permalink Normal View History

2010-10-20 15:42:17 +02:00
# encoding: utf-8
# === The boot process === #
# 1) load the app
# 2) load the rules (controllers / globs mapping)
# 3) load & instantiate all the renderable items
# 4) render all the items (here the filters & layouting run)
# 5) match the routes, write the files
require "yaml"
require "fileutils"
2011-03-17 13:21:14 +01:00
require "ace/filters/sass"
2011-03-14 12:26:40 +01:00
require "digest/sha1"
require "date"
2010-10-20 15:42:17 +02:00
module Ace
2011-02-23 05:51:06 +01:00
module Helpers
# include your helpers here
end
2010-10-20 15:42:17 +02:00
class RawItem
attr_accessor :path, :metadata, :content
def initialize(path)
2011-08-16 20:11:50 +02:00
@path = path
2010-10-20 15:42:17 +02:00
@data = File.read(path)
self.metadata = Hash.new
2010-10-20 15:42:17 +02:00
end
def parse
pieces = @data.split(/^-{3,5}\s*$/)
2011-08-16 20:11:50 +02:00
if pieces.length == 1 || @data.empty?
self.metadata = Hash.new
self.content = pieces.first
else
self.metadata = begin
YAML.load(pieces[1]).inject(Hash.new) { |metadata, pair| metadata.merge(pair[0].to_sym => pair[1]) } || Hash.new
end
self.content = pieces[2..-1].join.strip
end
2011-08-16 21:17:19 +02:00
set_timestamps_in_metadata
end
def set_timestamps_in_metadata
2011-08-16 20:11:50 +02:00
self.metadata[:created_at] ||= File.ctime(self.path)
self.metadata[:updated_at] ||= File.mtime(self.path)
2010-10-20 15:42:17 +02:00
end
end
# This class represents the items which will be
# eventually rendered like concrete posts, tags etc.
class Item
def self.inherited(subclass)
2011-02-17 06:40:09 +01:00
self.subclasses << subclass
self.before_filters.each do |instance|
subclass.before_filters << instance.dup
end
self.after_filters.each do |instance|
subclass.after_filters << instance.dup
end
2011-02-17 06:40:09 +01:00
end
def self.subclasses
@subclasses ||= [self]
2010-10-20 15:42:17 +02:00
end
def self.instances
2011-02-17 06:40:09 +01:00
@instances ||= Array.new
end
def self.all_subclasses
self.subclasses + self.subclasses.map(&:subclasses).flatten
end
def self.all_instances
self.all_subclasses.map(&:instances).flatten
2010-10-20 15:42:17 +02:00
end
def self.before_filters
@before_filters ||= Array.new
end
def self.before(filter, *args)
self.before_filters << filter.new(*args)
end
def self.after_filters
@after_filters ||= Array.new
end
def self.after(filter, *args)
self.after_filters << filter.new(*args)
end
2011-08-16 21:17:19 +02:00
def self.create(*args)
self.new(*args).tap(&:register)
2010-10-20 15:42:17 +02:00
end
# Content can be anything, not just a string.
attr_accessor :metadata, :content
attr_accessor :original_path
2011-08-16 21:17:19 +02:00
def initialize(metadata, content, original_path)
@metadata = metadata
@content = content
@original_path = original_path
2010-10-20 15:42:17 +02:00
end
def config
@config ||= begin
YAML::load_file("config.yml").inject(Hash.new) do |hash, pair|
hash.merge!(pair[0].to_sym => pair[1])
end
end
end
def register
instances = self.class.instances
unless instances.include?(self)
self.class.instances << self
end
end
def unregister
self.class.instances.delete(self)
end
def render
output = self.class.before_filters.inject(self.content) do |buffer, filter|
filter.call(self, buffer)
end
self.class.after_filters.inject(output) do |buffer, filter|
filter.call(self, buffer)
end
end
def server_path
2013-01-21 14:09:09 +01:00
absolute = self.output_path.sub(/^output\//, "").sub %r<(\.[^./]+)\.[^/]+$>, '\1'
"/#{absolute}"
end
def base_url
self.config[:base_url]
end
def permalink
if self.config[:base_url].nil?
raise "You have to add :base_url into config.yml or redefine #base_url method!"
end
"#{self.base_url}#{self.server_path}"
end
2011-03-14 12:26:40 +01:00
def digest(data)
Digest::SHA1.hexdigest(data)
end
2010-10-20 15:42:17 +02:00
attr_writer :output_path
def output_path
@output_path ||= begin
unless self.original_path.nil?
self.original_path.sub("content", "output")
end
end
end
def save!
puts "~ [RENDER] #{self.output_path}"
2011-03-14 12:26:40 +01:00
content = self.render # so filters can influence output_path
2011-03-14 12:26:40 +01:00
begin
old_content = File.open(self.output_path, "rb") { |f| f.read }
rescue
old_content = ''
end
if self.digest(content) != self.digest(old_content)
warn "~ CRC isn't same, save new content into #{self.output_path}"
# puts old_content.inspect
# puts content.inspect
FileUtils.mkdir_p File.dirname(self.output_path)
File.open(self.output_path, "w") do |file|
file.puts(content)
end
2010-10-20 15:42:17 +02:00
end
end
end
class Asset < Item
2011-03-17 13:21:14 +01:00
before Ace::SassFilter
2010-10-20 15:42:17 +02:00
end
end