Skip to content

Commit

Permalink
Merge pull request #420 from gpakosz/per-rules-file-preprocessor
Browse files Browse the repository at this point in the history
Permit included rules files to define their own preprocess block
  • Loading branch information
denisdefreyne committed May 1, 2014
2 parents 3fc2f9a + dbd3ab0 commit 6751628
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 19 deletions.
7 changes: 4 additions & 3 deletions lib/nanoc/base/compilation/compiler.rb
Expand Up @@ -190,12 +190,13 @@ def dependency_tracker
end
memoize :dependency_tracker

# Runs the preprocessor.
# Runs the preprocessors.
#
# @api private
def preprocess
return if rules_collection.preprocessor.nil?
preprocessor_context.instance_eval(&rules_collection.preprocessor)
rules_collection.preprocessors.each_value do |preprocessor|
preprocessor_context.instance_eval(&preprocessor)
end
end

# Returns all objects managed by the site (items, layouts, code snippets,
Expand Down
12 changes: 8 additions & 4 deletions lib/nanoc/base/compilation/compiler_dsl.rb
Expand Up @@ -5,6 +5,11 @@ module Nanoc
# Contains methods that will be executed by the site’s `Rules` file.
class CompilerDSL

# The current rules filename.
#
# @return [String] The current rules filename.
attr_accessor :rules_filename

# Creates a new compiler DSL for the given collection of rules.
#
# @api private
Expand All @@ -25,12 +30,11 @@ def initialize(rules_collection, config)
#
# @return [void]
def preprocess(&block)
if @rules_collection.preprocessor
if @rules_collection.preprocessors[rules_filename]
warn 'WARNING: A preprocess block is already defined. Defining ' \
'another preprocess block overrides the previously one.'
end

@rules_collection.preprocessor = block
@rules_collection.preprocessors[rules_filename] = block
end

# Creates a compilation rule for all items whose identifier match the
Expand Down Expand Up @@ -246,7 +250,7 @@ def include_rules(name)
filename = [ "#{name}", "#{name}.rb", "./#{name}", "./#{name}.rb" ].find { |f| File.file?(f) }
raise Nanoc::Errors::NoRulesFileFound.new if filename.nil?

instance_eval(File.read(filename), filename)
@rules_collection.parse(filename)
end

private
Expand Down
35 changes: 24 additions & 11 deletions lib/nanoc/base/compilation/rules_collection.rb
Expand Up @@ -23,17 +23,21 @@ class RulesCollection
# @return [Hash] The layout-to-filter mapping rules
attr_reader :layout_filter_mapping

# @return [Proc] The code block that will be executed after all data is
# loaded but before the site is compiled
attr_accessor :preprocessor
# The hash containing preprocessor code blocks that will be executed after
# all data is loaded but before the site is compiled.
#
# @return [Hash] The hash containing the preprocessor code blocks that will
# be executed after all data is loaded but before the site is compiled
attr_accessor :preprocessors

# @param [Nanoc::Compiler] compiler The site’s compiler
def initialize(compiler)
@compiler = compiler

@item_compilation_rules = []
@item_routing_rules = []
@layout_filter_mapping = OrderedHash.new
@item_compilation_rules = []
@item_routing_rules = []
@layout_filter_mapping = OrderedHash.new
@preprocessors = OrderedHash.new
end

# Add the given rule to the list of item compilation rules.
Expand Down Expand Up @@ -71,20 +75,29 @@ def load
rules_filename = rules_filenames.find { |f| File.file?(f) }
raise Nanoc::Errors::NoRulesFileFound.new if rules_filename.nil?

parse(rules_filename)
end

def parse(rules_filename)
rules_filename = File.absolute_path(rules_filename)

# Get rule data
@data = File.read(rules_filename)

# Load DSL
dsl.instance_eval(@data, "./#{rules_filename}")
old_rules_filename = dsl.rules_filename
dsl.rules_filename = rules_filename
dsl.instance_eval(@data, rules_filename)
dsl.rules_filename = old_rules_filename
end

# Unloads this site’s rules.
#
# @return [void]
def unload
@item_compilation_rules = []
@item_routing_rules = []
@layout_filter_mapping = OrderedHash.new
@item_compilation_rules = []
@item_routing_rules = []
@layout_filter_mapping = OrderedHash.new
@preprocessors = OrderedHash.new
end

# Finds the first matching compilation rule for the given item
Expand Down
34 changes: 34 additions & 0 deletions test/base/test_compiler_dsl.rb
Expand Up @@ -33,6 +33,40 @@ def test_preprocess_twice
assert_match(/WARNING: A preprocess block is already defined./, io[:stderr])
end

def test_per_rules_file_preprocessor
# Create site
Nanoc::CLI.run %w( create_site per-rules-file-preprocessor )
FileUtils.cd('per-rules-file-preprocessor') do
# Create rep
item = Nanoc::Item.new('foo', { :extension => 'bar' }, '/foo/')

# Create a bonus rules file
File.open('more_rules.rb', 'w') { |io| io.write "preprocess { @items['/foo/'][:preprocessed] = true }" }

# Create other necessary stuff
site = Nanoc::Site.new('.')
site.items << item
dsl = site.compiler.rules_collection.dsl
io = capturing_stdio do
dsl.preprocess {}
end
assert_empty io[:stdout]
assert_empty io[:stderr]

# Include rules
dsl.include_rules 'more_rules'

# Check that the two preprocess blocks have been added
assert_equal 2, site.compiler.rules_collection.preprocessors.size
refute_nil site.compiler.rules_collection.preprocessors.first
refute_nil site.compiler.rules_collection.preprocessors.last

# Apply preprocess blocks
site.compiler.preprocess
assert item[:preprocessed]
end
end

def test_include_rules
# Create site
Nanoc::CLI.run %w( create_site with_bonus_rules )
Expand Down
4 changes: 3 additions & 1 deletion test/base/test_site.rb
Expand Up @@ -109,11 +109,13 @@ def test_initialize_with_parent_config_file_cycle
def test_load_rules_with_existing_rules_file
# Mock DSL
dsl = mock
dsl.stubs(:rules_filename)
dsl.stubs(:rules_filename=)
dsl.expects(:compile).with('*')

# Create site
site = Nanoc::Site.new({})
site.compiler.rules_collection.expects(:dsl).returns(dsl)
site.compiler.rules_collection.stubs(:dsl).returns(dsl)

# Create rules file
File.open('Rules', 'w') do |io|
Expand Down

0 comments on commit 6751628

Please sign in to comment.