middleman/lib/middleman/core_extensions/front_matter.rb
2011-11-18 00:34:56 -08:00

121 lines
No EOL
2.7 KiB
Ruby

require "yaml"
require "tilt"
module Middleman::CoreExtensions::FrontMatter
class << self
def registered(app)
app.send :include, InstanceMethods
end
alias :included :registered
end
module InstanceMethods
def initialize
file_changed FrontMatter.matcher do |file|
frontmatter.touch_file(file)
end
file_deleted do |file|
frontmatter.remove_file(file)
end
provides_metadata FrontMatter.matcher do |path|
relative_path = path.sub(source_dir, "")
data = if frontmatter.has_data?(relative_path)
frontmatter.data(relative_path).first
else
{}
end
# Forward remaining data to helpers
data_content("page", data)
%w(layout layout_engine).each do |opt|
if data.has_key?(opt)
data[opt.to_sym] = data.delete(opt)
end
end
data
end
super
end
def frontmatter
@frontmatter ||= FrontMatter.new(self)
end
end
class FrontMatter
def self.matcher
%r{source/.*\.html}
end
def initialize(app)
@app = app
@source = File.expand_path(@app.views, @app.root)
@local_data = {}
end
def has_data?(path)
@local_data.has_key?(path.to_s)
end
def touch_file(file)
extension = File.extname(file).sub(/\./, "")
return unless ::Tilt.mappings.has_key?(extension)
file = File.expand_path(file, @app.root)
content = File.read(file)
file = file.sub(@app.source_dir, "")
# @app.logger.debug :frontmatter_update, Time.now, file if @app.logging?
result = parse_front_matter(content)
if result
@local_data[file] = result
path = @app.extensionless_path(file)
@app.raw_templates_cache[path] = result[1]
end
end
def remove_file(file)
file = File.expand_path(file, @app.root)
file = file.sub(@app.source_dir, "")
# @app.logger.debug :frontmatter_remove, Time.now, file if @app.logging?
if @local_data.has_key?(file)
@local_data.delete(file)
end
end
def data(path)
if @local_data.has_key?(path.to_s)
@local_data[path.to_s]
else
nil
end
end
private
def parse_front_matter(content)
yaml_regex = /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
if content =~ yaml_regex
begin
data = YAML.load($1)
rescue => e
puts "YAML Exception: #{e.message}"
return false
end
content = content.split(yaml_regex).last
else
return false
end
[data, content]
end
end
end