From c97c65d65576d20befc0134943d1aa6687284faf Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 2 May 2015 13:22:36 -0700 Subject: [PATCH] Add shorthand resources to extensions --- CHANGELOG.md | 1 + .../lib/middleman-core/extension.rb | 75 +++++++++++++++++++ .../lib/middleman-core/extension_manager.rb | 7 +- .../lib/middleman-core/sitemap/store.rb | 11 +-- 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5d0c05e..4173cb0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ master === +* Add `resources` class method to extensions to allow simple string-based resource generation. * rename `app.add_to_instance` to `Extension.expose_to_application` for adding extension-local methods to the shared app instance. * rename `app.add_to_config_context` to `Extension.expose_to_config` for adding extension-local methods to the sandboxed scope of `config.rb` * Add `Extension.expose_to_templates`, which auto binds copies of extension-local methods into a Template context. diff --git a/middleman-core/lib/middleman-core/extension.rb b/middleman-core/lib/middleman-core/extension.rb index aba6f4c3..ab9daea1 100644 --- a/middleman-core/lib/middleman-core/extension.rb +++ b/middleman-core/lib/middleman-core/extension.rb @@ -100,6 +100,12 @@ module Middleman # @return [Hash] a list of all the methods modules this extension exposes to templates. Set these using {#expose_to_template}. class_attribute :exposed_to_template, instance_reader: false, instance_writer: false + # @!attribute exposed_to_template + # @!scope class + # @api private + # @return [Array] a list of method generators. + class_attribute :resources_generators, instance_reader: false, instance_writer: false + # @!attribute ext_name # @!scope class # @return [Symbol] the name this extension is registered under. This is the symbol used to activate the extension. @@ -129,6 +135,19 @@ module Middleman config.define_setting(key, default, description, options) end + # Short-hand for simple Sitemap manipulation + # @example A generator which returns an array of resources + # resources :make_resources + # @example A generator which maps a path to a method + # resources make_resource: :make_it + # @example A generator which maps a path to a string + # resources make_resource: 'Hello' + # @param [Array] generators The generator definitions + def resources(*generators) + self.resources_generators ||= [] + self.resources_generators += generators + end + # Declare helpers to be added the global Middleman application. # This accepts either a list of modules to add on behalf # of this extension, or a block whose contents will all @@ -279,6 +298,7 @@ module Middleman bind_after_configuration bind_before_build bind_after_build + bind_ready end # @!method before_configuration @@ -298,6 +318,10 @@ module Middleman # Respond to the `after_build` event. # If an `after_build` method is implemented, that method will be run after the builder runs. + # @!method ready + # Respond to the `ready` event. + # If an `ready` method is implemented, that method will be run after the app has finished booting up. + # @!method manipulate_resource_list(resources) # Manipulate the resource list by transforming or adding {Sitemap::Resource}s. # Sitemap manipulation is a powerful way of interacting with a project, since it can modify each {Sitemap::Resource} or generate new {Sitemap::Resources}. This method is used in a pipeline where each sitemap manipulator is run in turn, with each one being fed the output of the previous manipulator. See the source of built-in Middleman extensions like {Middleman::Extensions::DirectoryIndexes} and {Middleman::Extensions::AssetHash} for examples of how to use this. @@ -362,6 +386,53 @@ module Middleman if ext.respond_to?(:manipulate_resource_list) ext.app.sitemap.register_resource_list_manipulator(ext.class.ext_name, ext, ext.class.resource_list_manipulator_priority) end + + if ext.class.resources_generators && !ext.class.resources_generators.empty? + ext.app.sitemap.register_resource_list_manipulator( + :"#{ext.class.ext_name}_generator", + ext, + ext.class.resource_list_manipulator_priority, + :generate_resources + ) + end + end + end + + def generate_resources(resources) + generator_defs = self.class.resources_generators.reduce({}) do |sum, g| + resource_definitions = if g.is_a? Hash + g + elsif g.is_a? Symbol + definition = method(g) + + if definition.arity === 0 + send(g) + else + send(g, resources) + end + else + {} + end + + sum.merge(resource_definitions) + end + + resources + generator_defs.map do |path, g| + if g.is_a? Symbol + definition = method(g) + + g = if definition.arity === 0 + send(g) + else + send(g, resources) + end + end + + ::Middleman::Sitemap::StringResource.new( + app.sitemap, + path, + g + ) end end @@ -392,5 +463,9 @@ module Middleman end end end + + def bind_ready + @app.ready(&method(:ready)) if respond_to?(:ready) + end end end diff --git a/middleman-core/lib/middleman-core/extension_manager.rb b/middleman-core/lib/middleman-core/extension_manager.rb index 2fdef893..6b1fbe93 100644 --- a/middleman-core/lib/middleman-core/extension_manager.rb +++ b/middleman-core/lib/middleman-core/extension_manager.rb @@ -55,7 +55,7 @@ module Middleman def activate_all logger.debug 'Loaded extensions:' - instances = @activated.each_with_object([]) do |(ext_name, ext), sum| + @instances = @activated.each_with_object([]) do |(ext_name, ext), sum| if ext.is_a?(Hash) ext.each do |instance_key, instance| logger.debug "== Extension: #{ext_name} #{instance_key}" @@ -67,16 +67,15 @@ module Middleman end end - instances.each do |ext| + @instances.each do |ext| ::Middleman::Extension.activated_extension(ext) end end def add_exposed_to_context(context) - @activated.each do |(_, ext)| + @instances.each do |ext| ext.add_exposed_to_context(context) end end - end end diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index 04ffd9b9..b454ecf9 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -74,12 +74,13 @@ module Middleman # @param [Symbol] name Name of the manipulator for debugging # @param [#manipulate_resource_list] manipulator Resource list manipulator # @param [Numeric] priority Sets the order of this resource list manipulator relative to the rest. By default this is 50, and manipulators run in the order they are registered, but if a priority is provided then this will run ahead of or behind other manipulators. + # @param [Symbol] custom_name The method name to execute. # @return [void] - Contract Symbol, RespondTo['manipulate_resource_list'], Maybe[Num] => Any - def register_resource_list_manipulator(name, manipulator, priority=50) + Contract Symbol, RespondTo['manipulate_resource_list'], Maybe[Num], Maybe[Symbol] => Any + def register_resource_list_manipulator(name, manipulator, priority=50, custom_name=nil) # The third argument used to be a boolean - handle those who still pass one priority = 50 unless priority.is_a? Numeric - @resource_list_manipulators << [name, manipulator, priority] + @resource_list_manipulators << [name, manipulator, priority, custom_name] # The index trick is used so that the sort is stable - manipulators with the same priority # will always be ordered in the same order as they were registered. n = 0 @@ -177,8 +178,8 @@ module Middleman @app.logger.debug '== Rebuilding resource list' - @resources = @resource_list_manipulators.reduce([]) do |result, (_, manipulator, _)| - newres = manipulator.manipulate_resource_list(result) + @resources = @resource_list_manipulators.reduce([]) do |result, (_, manipulator, _, custom_name)| + newres = manipulator.send(custom_name || :manipulate_resource_list, result) # Reset lookup cache reset_lookup_cache!