From d12d8e474138631b27c46fc43d5f0d176a5c2e69 Mon Sep 17 00:00:00 2001 From: LightGuard Date: Mon, 6 Apr 2015 21:48:24 -0600 Subject: [PATCH] Adding new extension hooks There are three new extension hooks in place now: * before_extensions + All extensions added via this method, following the same extension rules, will be run before any other extensions loaded with `extension`. * after_extensions + All extensions added via this method, following the same extension rules, will be run after any other extensions loaded with `extension`. * after_generation + All extensions added via this method, following the same extension rules, will be run after the page generation is completed. This will only run on the first generation, not on reloads. Extensions will now be notified if they are being reloaded. To be notified of this an extension must have an `on_reload(site)` method, which will be called if there is a change. An extension is then free to re-run an initialization logic, clean-up the site variable, or create new state needed for a re-run of the `execute(site)` method. --- lib/awestruct/engine.rb | 18 +++++-- lib/awestruct/extensions/pipeline.rb | 30 ++++++++--- lib/awestruct/pipeline.rb | 50 ++++++++++++++++--- spec/awestruct/pipeline_spec.rb | 31 +++++++++--- .../test-data/pipeline/_ext/extensions.rb | 26 ++++++++++ .../test-data/pipeline/_ext/pipeline.rb | 11 ++++ 6 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 spec/support/test-data/pipeline/_ext/extensions.rb create mode 100644 spec/support/test-data/pipeline/_ext/pipeline.rb diff --git a/lib/awestruct/engine.rb b/lib/awestruct/engine.rb index 74617a7d..f815824d 100644 --- a/lib/awestruct/engine.rb +++ b/lib/awestruct/engine.rb @@ -69,7 +69,7 @@ def run(profile, base_url, default_base_url, force=false, generate=true) load_pages $LOG.debug 'execute_pipeline' if $LOG.debug? $LOG.info 'Excecuting pipeline...' if $LOG.info? - execute_pipeline + execute_pipeline(false) $LOG.debug 'configure_compass' if $LOG.debug? configure_compass $LOG.debug 'set_urls' if $LOG.debug? @@ -246,22 +246,31 @@ def load_pipeline pipeline_file = File.join( ext_dir, 'pipeline.rb' ) if ( File.exists?( pipeline_file ) ) p = eval(File.read( pipeline_file ), nil, pipeline_file, 1) + p.before_pipeline_extensions.each do |e| + pipeline.before_pipeline_extension( e ) + end p.extensions.each do |e| pipeline.extension( e ) end + p.after_pipeline_extensions.each do |e| + pipeline.after_pipeline_extension( e ) + end p.helpers.each do |h| pipeline.helper( h ) end p.transformers.each do |t| pipeline.transformer( t ) end + p.after_generation_extensions.each do |e| + pipeline.after_generation_extension( e ) + end end end - def execute_pipeline + def execute_pipeline(on_reload = false) FileUtils.mkdir_p( site.config.output_dir ) FileUtils.mkdir_p( site.config.tmp_dir ) - pipeline.execute( site ) + pipeline.execute( site, on_reload ) end def configure_compass @@ -356,6 +365,7 @@ def generate_output generate_page( page, generated_path, false ) end end + site.engine.pipeline.execute_after_generation(site) end def generate_page(page, generated_path, produce_output=true) @@ -438,7 +448,7 @@ def run_auto_for_non_page(file, generate = true) @pipeline = Pipeline.new load_yamls load_pipeline - execute_pipeline + execute_pipeline(true) if ( generate ) site.pages.each do |p| diff --git a/lib/awestruct/extensions/pipeline.rb b/lib/awestruct/extensions/pipeline.rb index 545f2e06..dce2c6fa 100644 --- a/lib/awestruct/extensions/pipeline.rb +++ b/lib/awestruct/extensions/pipeline.rb @@ -11,31 +11,45 @@ module Awestruct module Extensions + # Public. Extension declaration class, initialized by the end user to + # declare their extensions, helpers, transformers, etc. class Pipeline - attr_reader :before_extensions + attr_reader :before_pipeline_extensions attr_reader :extensions - attr_reader :after_extensions + attr_reader :after_pipeline_extensions attr_reader :helpers attr_reader :transformers + attr_reader :after_generation_extensions def initialize(&block) - @extensions = [] - @helpers = [] - @transformers = [] + @before_pipeline_extensions = [] + @extensions = [] + @helpers = [] + @transformers = [] + @after_pipeline_extensions = [] + @after_generation_extensions = [] begin - instance_eval &block if block + instance_eval(&block) if block rescue Exception => e abort("Failed to initialize pipeline: #{e}") end end + def before_extensions(ext) + @before_pipeline_extensions << ext + end + def extension(ext) @extensions << ext # TC: why? transformer and extension? ext.transform(@transformers) if ext.respond_to?('transform') end + def after_extensions(ext) + @after_pipeline_extensions << ext + end + def helper(helper) @helpers << helper end @@ -44,6 +58,10 @@ def transformer(transformer) @transformers << transformer end + def after_generation(ext) + @after_generation_extensions << ext + end + def execute(site) extensions.each do |ext| ext.execute( site ) diff --git a/lib/awestruct/pipeline.rb b/lib/awestruct/pipeline.rb index e7d8c2c1..10a30c90 100644 --- a/lib/awestruct/pipeline.rb +++ b/lib/awestruct/pipeline.rb @@ -6,12 +6,25 @@ module Awestruct class Pipeline attr_reader :handler_chains + attr_reader :before_pipeline_extensions + attr_reader :extensions + attr_reader :after_pipeline_extensions + attr_reader :helpers + attr_reader :transformers + attr_reader :after_generation_extensions def initialize() @handler_chains = HandlerChains.new - @extensions = [] - @helpers = [] - @transformers = [] + @before_pipeline_extensions = [] + @extensions = [] + @helpers = [] + @transformers = [] + @after_pipeline_extensions = [] + @after_generation_extensions = [] + end + + def before_pipeline_extension(e) + @before_pipeline_extensions << e end def extension(e) @@ -20,6 +33,10 @@ def extension(e) e.transform(@transformers) if e.respond_to?('transform') end + def after_pipeline_extension(e) + @after_pipeline_extensions << e + end + def helper(h) @helpers << h end @@ -28,12 +45,27 @@ def transformer(t) @transformers << t end - def execute(site) - execute_extensions(site) + def after_generation_extension(e) + @after_generation_extensions << e end - def execute_extensions(site) + def execute(site, on_reload = false) + execute_extensions(site, on_reload) + end + + def execute_extensions(site, on_reload) + @before_pipeline_extensions.each do |e| + e.on_reload(site) if (on_reload && e.respond_to?(:on_reload)) + e.execute(site) + end + @extensions.each do |e| + e.on_reload(site) if (on_reload && e.respond_to?(:on_reload)) + e.execute(site) + end + + @after_pipeline_extensions.each do |e| + e.on_reload(site) if (on_reload && e.respond_to?(:on_reload)) e.execute(site) end end @@ -45,6 +77,12 @@ def apply_transformers(site, page, rendered) rendered end + def execute_after_generation(site) + @after_generation_extensions.each do |e| + e.execute(site) + end + end + def mixin_helpers(context) context.extend( Awestruct::ContextHelper ) @helpers.each do |h| diff --git a/spec/awestruct/pipeline_spec.rb b/spec/awestruct/pipeline_spec.rb index 0b134b92..0bee087e 100644 --- a/spec/awestruct/pipeline_spec.rb +++ b/spec/awestruct/pipeline_spec.rb @@ -1,15 +1,32 @@ - -require 'awestruct/pipeline' - +require 'awestruct/engine' +require 'awestruct/pipeline' describe Awestruct::Pipeline do - before do - dir = Pathname.new( test_data_dir 'engine' ) + before do + dir = Pathname.new( test_data_dir 'pipeline' ) opts = Awestruct::CLI::Options.new opts.source_dir = dir - @site = Hashery::OpenCascade[ { :encoding=>false, :dir=>dir, :config=>Awestruct::Config.new( opts ) } ] - Awestruct::Engine.new(@site.config) + @site = Hashery::OpenCascade[ { :encoding=>false, :dir=>dir, :config=>Awestruct::Config.new( opts ), :pages => [] } ] + @engine = Awestruct::Engine.new(@site.config) + + log = StringIO.new + $LOG = Logger.new(log) + $LOG.level = Logger::DEBUG + + @engine.load_pipeline + @pipeline = @engine.pipeline + end + + context "after pipeline is loaded" do + specify "should have all specified extension points" do + expect(@pipeline.before_pipeline_extensions.size).to eql 1 + expect(@pipeline.extensions.size).to eql 1 + expect(@pipeline.after_pipeline_extensions.size).to eql 1 + expect(@pipeline.helpers.size).to eql 1 + expect(@pipeline.transformers.size).to eql 1 + expect(@pipeline.after_generation_extensions.size).to eql 1 + end end it "should provide a way to find a matching handler chain for a given path" do diff --git a/spec/support/test-data/pipeline/_ext/extensions.rb b/spec/support/test-data/pipeline/_ext/extensions.rb new file mode 100644 index 00000000..c20bc3c8 --- /dev/null +++ b/spec/support/test-data/pipeline/_ext/extensions.rb @@ -0,0 +1,26 @@ +module Awestruct + module Test + module Extensions + class TestBeforeExtension + def execute site + end + end + + class TestAfterExtension + def execute site + end + end + + class TestAfterGenerationExtension + def execute site + end + end + + class LinkTransformer + def transform site, page, content + end + end + end + end +end + diff --git a/spec/support/test-data/pipeline/_ext/pipeline.rb b/spec/support/test-data/pipeline/_ext/pipeline.rb new file mode 100644 index 00000000..737fe407 --- /dev/null +++ b/spec/support/test-data/pipeline/_ext/pipeline.rb @@ -0,0 +1,11 @@ +require 'support/test-data/pipeline/_ext/extensions' + +Awestruct::Extensions::Pipeline.new do + before_extensions Awestruct::Test::Extensions::TestBeforeExtension.new + extension Awestruct::Extensions::Indexifier.new + after_extensions Awestruct::Test::Extensions::TestAfterExtension.new + helper Awestruct::Extensions::Relative + transformer Awestruct::Test::Extensions::LinkTransformer.new + after_generation Awestruct::Test::Extensions::TestAfterGenerationExtension.new +end +