frontmatter can control whether a page is ignored

This commit is contained in:
Thomas Reynolds 2012-01-07 17:21:26 -08:00
parent 0ac9c0b662
commit c473181167
3 changed files with 73 additions and 12 deletions

View file

@ -2,9 +2,9 @@ Feature: Setting page settings through frontmatter
Scenario: Setting layout, ignoring, and disabling directory indexes through frontmatter
Given a successfully built app at "frontmatter-settings-app"
Then the following files should exist:
| build/proxied/index.html |
| build/no_index.html |
| build/proxied/index.html |
| build/no_index.html |
And the file "build/alternate_layout/index.html" should contain "Alternate layout"
And the following files should not exist:
| build/ignored/index.html |
| build/no_index/index.html |
| build/ignored/index.html |
| build/no_index/index.html |

View file

@ -1,8 +1,16 @@
# Parsing YAML frontmatter
require "yaml"
# Looking up Tilt extensions
require "tilt"
# Frontmatter namespace
module Middleman::CoreExtensions::FrontMatter
# Setup extension
class << self
# Once registered
def registered(app)
app.set :frontmatter_extensions, %w(.htm .html .php)
app.extend ClassMethods
@ -12,7 +20,12 @@ module Middleman::CoreExtensions::FrontMatter
alias :included :registered
end
# Frontmatter class methods
module ClassMethods
# Register callback on frontmatter updates
# @param [Regexp] matcher
# @return [Array<Array<Proc, Regexp>>]
def frontmatter_changed(matcher=nil, &block)
@_frontmatter_changed ||= []
@_frontmatter_changed << [block, matcher] if block_given?
@ -20,22 +33,25 @@ module Middleman::CoreExtensions::FrontMatter
end
end
# Frontmatter instance methods
module InstanceMethods
# Override init
def initialize
super
exts = frontmatter_extensions.join("|").gsub(".", "\.")
static_path = source_dir.sub(self.root, "").sub(/^\//, "").sub(/\/$/, "") + "/"
static_path = source_dir.sub(root, "").sub(/^\//, "").sub(/\/$/, "") + "/"
matcher = %r{#{static_path}.*(#{exts})}
self.files.changed matcher do |file|
self.frontmatter_extension.touch_file(file)
files.changed matcher do |file|
frontmatter_extension.touch_file(file)
end
self.files.deleted matcher do |file|
self.frontmatter_extension.remove_file(file)
files.deleted matcher do |file|
frontmatter_extension.remove_file(file)
end
provides_metadata matcher do |path|
@ -56,6 +72,9 @@ module Middleman::CoreExtensions::FrontMatter
end
end
# Notify callbacks that the frontmatter changed
# @param [String] path
# @return [void]
def frontmatter_did_change(path)
frontmatter_changed.each do |callback, matcher|
next if path.match(%r{^#{build_dir}/})
@ -64,26 +83,58 @@ module Middleman::CoreExtensions::FrontMatter
end
end
# Get the frontmatter object
# @return [Middleman::CoreExtensions::FrontMatter::FrontMatter]
def frontmatter_extension
@_frontmatter_extension ||= FrontMatter.new(self)
end
# Get the frontmatter for the given params
# @param [String] path
# @return [Hash, nil]
def frontmatter(*args)
frontmatter_extension.data(*args)
end
end
# Core Frontmatter class
class FrontMatter
# Initialize frontmatter with current app
# @param [Middleman::Base] app
def initialize(app)
@app = app
@source = File.expand_path(@app.source, @app.root)
@local_data = {}
# Setup ignore callback
@app.ignore do |path|
p = @app.sitemap.page(path)
file_path = p.source_file.sub(@app.source_dir, "")
if has_data?(file_path)
d = data(file_path)
if d && d[0]
d[0].has_key?("ignored") && d[0]["ignored"] == true
else
false
end
else
false
end
end
end
# Whether the frontmatter knows about a path
# @param [String] path
# @return [Boolean]
def has_data?(path)
@local_data.has_key?(path.to_s)
end
# Update frontmatter if a file changes
# @param [String] file
# @return [void]
def touch_file(file)
extension = File.extname(file).sub(/\./, "")
return unless ::Tilt.mappings.has_key?(extension)
@ -104,16 +155,23 @@ module Middleman::CoreExtensions::FrontMatter
end
end
# Update frontmatter if a file is delted
# @param [String] file
# @return [void]
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)
path = File.join(@app.source_dir, file)
@app.cache.remove(:raw_template, path)
@local_data.delete(file)
end
end
# Get the frontmatter for a given path
# @param [String] path
# @return [Hash, nil]
def data(path)
if @local_data.has_key?(path.to_s)
@local_data[path.to_s]
@ -123,6 +181,9 @@ module Middleman::CoreExtensions::FrontMatter
end
private
# Parse frontmatter out of a string
# @param [String] content
# @return [Array<Hash, String>]
def parse_front_matter(content)
yaml_regex = /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
if content =~ yaml_regex

View file

@ -64,8 +64,8 @@ module Middleman::CoreExtensions::Sitemap
# Ignore a path, regex or callback
# @param [String, Regexp]
# @return [void]
def ignore(*args)
sitemap.ignore(*args)
def ignore(*args, &block)
sitemap.ignore(*args, &block)
end
# Proxy one path to another