2014-05-11 04:06:51 +02:00
require 'middleman-core/extension'
2012-04-14 22:51:02 +02:00
module Middleman
2014-05-11 04:06:51 +02:00
# The Extensions module is used to handle global registration and loading of Middleman Extensions.
#
2014-05-23 06:48:37 +02:00
# The application-facing extension API ({Middleman::CoreExtensions::Extensions#activate activate}, etc) is in {Middleman::CoreExtensions::Extensions} in
# `middleman-core/core_extensions/extensions.rb`.
2012-04-14 22:51:02 +02:00
module Extensions
2014-05-23 06:48:37 +02:00
@registered = { }
2014-05-26 06:06:25 +02:00
@auto_activate = {
# Activate before the Sitemap is instantiated
2014-07-10 21:35:47 +02:00
before_sitemap : Set . new ,
2014-05-26 06:06:25 +02:00
# Activate the extension before `config.rb` and the `:before_configuration` hook.
2014-07-10 21:35:47 +02:00
before_configuration : Set . new
2014-05-26 06:06:25 +02:00
}
2014-05-23 06:48:37 +02:00
2014-06-07 00:32:00 +02:00
AutoActivation = Struct . new ( :name , :modes )
2012-04-14 22:51:02 +02:00
class << self
2014-05-23 08:05:42 +02:00
# @api private
2014-05-23 06:48:37 +02:00
# A hash of all registered extensions. Registered extensions are not necessarily active - this
# is the set of all extensions that are known to Middleman.
# @return [Hash{Symbol => Class<Middleman::Extension>, Proc}] A directory of known extensions indexed by the name they were registered under. The value may be a Proc, which can be lazily called to return an extension class.
attr_reader :registered
2012-04-14 22:51:02 +02:00
# Register a new extension. Choose a name which will be
2014-05-23 06:48:37 +02:00
# used to activate the extension in `config.rb`, like this:
2012-04-14 22:51:02 +02:00
#
# activate :my_extension
#
2014-05-23 06:48:37 +02:00
# Provide your extension class either as the second parameter:
2014-03-29 22:29:42 +01:00
#
# Middleman::Extensions.register(:my_extension, MyExtension)
#
2014-05-23 06:48:37 +02:00
# Or better, return it from a block, which allows you to lazily require the implementation:
2014-03-29 22:29:42 +01:00
#
2014-05-23 06:48:37 +02:00
# Middleman::Extensions.register :my_extension do
2014-03-29 22:29:42 +01:00
# require 'my_extension'
# MyExtension
# end
2012-04-14 22:51:02 +02:00
#
# @param [Symbol] name The name of the extension
2014-05-23 06:48:37 +02:00
# @param [Class<Middleman::Extension>] extension_class The extension class (Must inherit from {Middleman::Extension})
2014-05-26 06:06:25 +02:00
# @option options [Boolean] :auto_activate If this is set to a lifecycle event (:before_configuration or :before_sitemap), this extension will be automatically activated at that point.
2014-05-23 08:05:42 +02:00
# This is intended for use with built-in Middleman extensions and should not be used by third-party extensions.
2014-03-25 19:00:43 +01:00
# @yield Instead of passing a module in namespace, you can provide
2014-05-23 06:48:37 +02:00
# a block which returns your extension class. This gives
2014-03-25 19:00:43 +01:00
# you the ability to require other files only when the
2014-05-23 06:48:37 +02:00
# extension is first activated.
# @return [void]
2014-05-23 08:05:42 +02:00
def register ( name , extension_class = nil , options = { } , & block )
2014-05-23 07:36:01 +02:00
raise 'Extension name must be a symbol' unless name . is_a? ( Symbol )
2014-03-29 22:29:42 +01:00
# If we've already got an extension registered under this name, bail out
2014-05-23 06:48:37 +02:00
raise " There is already an extension registered with the name ' #{ name } ' " if registered . key? ( name )
2014-03-25 19:00:43 +01:00
2014-05-23 08:05:42 +02:00
# If the extension is defined with a block, grab options out of the "extension_class" parameter.
if extension_class && block_given? && options . empty? && extension_class . is_a? ( Hash )
options = extension_class
extension_class = nil
end
2014-05-23 06:48:37 +02:00
registered [ name ] = if block_given?
2014-03-25 19:00:43 +01:00
block
2014-05-23 06:48:37 +02:00
elsif extension_class && extension_class . ancestors . include? ( :: Middleman :: Extension )
extension_class
2014-03-29 22:29:42 +01:00
else
2014-04-29 19:50:21 +02:00
raise 'You must provide a Middleman::Extension or a block that returns a Middleman::Extension'
2014-03-25 19:00:43 +01:00
end
2014-05-23 08:05:42 +02:00
2014-07-02 20:05:57 +02:00
return unless options [ :auto_activate ]
descriptor = AutoActivation . new ( name , options [ :modes ] || :all )
@auto_activate [ options [ :auto_activate ] ] << descriptor
2014-03-25 19:00:43 +01:00
end
2014-05-23 06:48:37 +02:00
# @api private
# Load an extension by name, lazily evaluating the block provided to {#register} if necessary.
# @param [Symbol] name The name of the extension
# @return [Class<Middleman::Extension>] A {Middleman::Extension} class implementing the extension
#
2014-03-25 19:00:43 +01:00
def load ( name )
2014-05-23 07:36:01 +02:00
raise 'Extension name must be a symbol' unless name . is_a? ( Symbol )
2014-03-29 22:29:42 +01:00
2014-04-29 19:50:21 +02:00
unless registered . key? ( name )
2014-03-29 22:29:42 +01:00
raise " Unknown Extension: #{ name } . Check the name and make sure you have referenced the extension's gem in your Gemfile. "
end
2014-03-25 19:00:43 +01:00
2014-05-23 06:48:37 +02:00
extension_class = registered [ name ]
if extension_class . is_a? ( Proc )
extension_class = extension_class . call
registered [ name ] = extension_class
2012-04-14 22:51:02 +02:00
end
2014-03-25 19:00:43 +01:00
2014-05-23 06:48:37 +02:00
unless extension_class . ancestors . include? ( :: Middleman :: Extension )
2014-03-29 22:29:42 +01:00
raise " Tried to activate old-style extension: #{ name } . They are no longer supported. "
end
# Set the extension's name to whatever it was registered as.
2014-05-23 06:48:37 +02:00
extension_class . ext_name = name
2014-03-29 22:29:42 +01:00
2014-05-23 06:48:37 +02:00
extension_class
2012-04-14 22:51:02 +02:00
end
2014-05-26 06:06:25 +02:00
# @api private
# A flattened list of all extensions which are automatically activated
# @return [Array<Symbol>] A list of extension names which are automatically activated.
def auto_activated
2014-06-07 00:32:00 +02:00
@auto_activate . values . map ( & :name ) . flatten
end
# @api private
# Load autoactivatable extensions for the given env.
# @param [Symbol] group The name of the auto_activation group.
# @param [Middleman::Application] app An instance of the app.
def auto_activate ( group , app )
@auto_activate [ group ] . each do | descriptor |
2014-07-02 20:05:57 +02:00
next unless descriptor [ :modes ] == :all || descriptor [ :modes ] . include? ( app . config [ :mode ] )
2014-07-05 21:51:41 +02:00
app . extensions . activate descriptor [ :name ]
2014-06-07 00:32:00 +02:00
end
2014-05-26 06:06:25 +02:00
end
2012-04-14 22:51:02 +02:00
end
end
2012-08-14 00:39:06 +02:00
end