remove old style extension support

This commit is contained in:
Thomas Reynolds 2014-01-01 14:50:42 -08:00
parent b5fec39df8
commit a610608785
17 changed files with 245 additions and 313 deletions

View file

@ -38,5 +38,5 @@ gem 'rubocop', :require => false
# Middleman itself # Middleman itself
gem 'middleman-core', :path => 'middleman-core' gem 'middleman-core', :path => 'middleman-core'
gem 'middleman-sprockets', :github => 'middleman/middleman-sprockets' gem 'middleman-sprockets', :github => 'middleman/middleman-sprockets', :require => false
gem 'middleman', :path => 'middleman' gem 'middleman', :path => 'middleman'

View file

@ -1,20 +0,0 @@
Feature: v3 Modular Extension
Scenario: Registering and overwriting a system config option
Given a fixture app "large-build-app"
And a file named "config.rb" with:
"""
module MyFeature
class << self
def registered(app)
app.set :css_dir, "lib/my/css"
end
alias :included :registered
end
end
::Middleman::Extensions.register(:my_feature, MyFeature)
activate :my_feature
"""
Given a successfully built app at "large-build-app"
When I cd to "build"
Then the file "link_test.html" should contain "lib/my/css/test.css"

View file

@ -135,29 +135,29 @@ module Middleman
include Middleman::CoreExtensions::Extensions include Middleman::CoreExtensions::Extensions
# Basic Rack Request Handling # Basic Rack Request Handling
register Middleman::CoreExtensions::Request include Middleman::CoreExtensions::Request
# Handle exceptions # Handle exceptions
register Middleman::CoreExtensions::ShowExceptions include Middleman::CoreExtensions::ShowExceptions
# Add Watcher Callbacks # Add Watcher Callbacks
register Middleman::CoreExtensions::FileWatcher include Middleman::CoreExtensions::FileWatcher
# Activate Data package # Activate Data package
register Middleman::CoreExtensions::Data include Middleman::CoreExtensions::Data
# Setup custom rendering # Setup custom rendering
register Middleman::CoreExtensions::Rendering include Middleman::CoreExtensions::Rendering
# Parse YAML from templates. Must be before sitemap so sitemap # Parse YAML from templates. Must be before sitemap so sitemap
# extensions see updated frontmatter! # extensions see updated frontmatter!
register Middleman::CoreExtensions::FrontMatter register Middleman::CoreExtensions::FrontMatter
# Sitemap Config options and public api # Sitemap Config options and public api
register Middleman::Sitemap include Middleman::Sitemap
# Setup external helpers # Setup external helpers
register Middleman::CoreExtensions::ExternalHelpers include Middleman::CoreExtensions::ExternalHelpers
# Reference to Logger singleton # Reference to Logger singleton
attr_reader :logger attr_reader :logger
@ -188,11 +188,19 @@ module Middleman
Encoding.default_external = config[:encoding] Encoding.default_external = config[:encoding]
end end
config[:source] = ENV['MM_SOURCE'] if ENV['MM_SOURCE']
# Built-in extensions
activate :default_helpers
activate :lorem
if defined?(Middleman::CoreExtensions::Compass)
activate :compass
end
# Evaluate a passed block if given # Evaluate a passed block if given
@config_context.instance_exec(&block) if block_given? @config_context.instance_exec(&block) if block_given?
config[:source] = ENV['MM_SOURCE'] if ENV['MM_SOURCE']
super super
end end
@ -232,13 +240,3 @@ module Middleman
end end
end end
Middleman::CoreExtensions::DefaultHelpers.activate
Middleman::CoreExtensions::Internationalization.register(:i18n)
if defined?(Middleman::CoreExtensions::Compass)
Middleman::CoreExtensions::Compass.activate
end
Middleman::Extensions::Lorem.activate

View file

@ -8,7 +8,7 @@ module Middleman
# Extension registered # Extension registered
class << self class << self
# @private # @private
def registered(app) def included(app)
# Data formats # Data formats
require 'yaml' require 'yaml'
require 'active_support/json' require 'active_support/json'
@ -16,7 +16,6 @@ module Middleman
app.config.define_setting :data_dir, 'data', 'The directory data files are stored in' app.config.define_setting :data_dir, 'data', 'The directory data files are stored in'
app.send :include, InstanceMethods app.send :include, InstanceMethods
end end
alias :included :registered
end end
# Instance methods # Instance methods

View file

@ -36,7 +36,7 @@ module Middleman
# Register extension # Register extension
class << self class << self
# @private # @private
def registered(app) def included(app)
app.define_hook :initialized app.define_hook :initialized
app.define_hook :instance_available app.define_hook :instance_available
app.define_hook :after_configuration app.define_hook :after_configuration
@ -51,7 +51,6 @@ module Middleman
app.send :include, InstanceMethods app.send :include, InstanceMethods
app.delegate :configure, :to => :"self.class" app.delegate :configure, :to => :"self.class"
end end
alias :included :registered
end end
# Class methods # Class methods
@ -70,18 +69,10 @@ module Middleman
# @param [Hash] options Per-extension options hash # @param [Hash] options Per-extension options hash
# @return [void] # @return [void]
def register(extension, options={}, &block) def register(extension, options={}, &block)
if extension.instance_of?(Class) && extension.ancestors.include?(::Middleman::Extension) if extension.ancestors.include?(::Middleman::Extension)
extension.new(self, options, &block) extension.new(self, options, &block)
else else
extend extension $stderr.puts "!! Tried to register old-style extension: #{extension}"
if extension.respond_to?(:registered)
if extension.method(:registered).arity === 1
extension.registered(self, &block)
else
extension.registered(self, options, &block)
end
end
extension
end end
end end
end end
@ -97,32 +88,26 @@ module Middleman
# @param [Symbol, Module] ext Which extension to activate # @param [Symbol, Module] ext Which extension to activate
# @return [void] # @return [void]
def activate(ext, options={}, &block) def activate(ext, options={}, &block)
ext_module = if ext.is_a?(Module) if extension = ::Middleman::Extensions::registered[ext]
ext if extension.ancestors.include?(::Middleman::Extension)
else logger.debug "== Activating: #{ext}"
::Middleman::Extensions.load(ext)
end
if ext_module.nil? if extension.supports_multiple_instances?
logger.error "== Unknown Extension: #{ext}"
else
logger.debug "== Activating: #{ext}"
if ext_module.instance_of? Module
extensions[ext] = self.class.register(ext_module, options, &block)
elsif ext_module.instance_of?(Class) && ext_module.ancestors.include?(::Middleman::Extension)
if ext_module.supports_multiple_instances?
extensions[ext] ||= {} extensions[ext] ||= {}
key = "instance_#{extensions[ext].keys.length}" key = "instance_#{extensions[ext].keys.length}"
extensions[ext][key] = ext_module.new(self.class, options, &block) extensions[ext][key] = extension.new(self.class, options, &block)
else else
if extensions[ext] if extensions[ext]
logger.error "== #{ext} already activated." logger.error "== #{ext} already activated."
else else
extensions[ext] = ext_module.new(self.class, options, &block) extensions[ext] = extension.new(self.class, options, &block)
end end
end end
else
logger.error "!! Tried to activate old-style extension: #{ext}"
end end
else
logger.error "!! Unknown Extension: #{ext}"
end end
end end

View file

@ -2,37 +2,31 @@
module Middleman module Middleman
module CoreExtensions module CoreExtensions
module ExternalHelpers module ExternalHelpers
# once registered
def self.included(app)
# Setup a default helpers paths
app.config.define_setting :helpers_dir, 'helpers', 'Directory to autoload helper modules from'
app.config.define_setting :helpers_filename_glob, '**.rb', 'Glob pattern for matching helper ruby files'
app.config.define_setting :helpers_filename_to_module_name_proc, Proc.new { |filename|
basename = File.basename(filename, File.extname(filename))
basename.camelcase
}, 'Proc implementing the conversion from helper filename to module name'
# Setup extension # After config
class << self app.after_configuration do
helpers_path = File.join(root, config[:helpers_dir])
next unless File.exists?(helpers_path)
# once registered Dir[File.join(helpers_path, config[:helpers_filename_glob])].each do |filename|
def registered(app) module_name = config[:helpers_filename_to_module_name_proc].call(filename)
# Setup a default helpers paths next unless module_name
app.config.define_setting :helpers_dir, 'helpers', 'Directory to autoload helper modules from'
app.config.define_setting :helpers_filename_glob, '**.rb', 'Glob pattern for matching helper ruby files'
app.config.define_setting :helpers_filename_to_module_name_proc, Proc.new { |filename|
basename = File.basename(filename, File.extname(filename))
basename.camelcase
}, 'Proc implementing the conversion from helper filename to module name'
# After config require filename
app.after_configuration do next unless Object.const_defined?(module_name.to_sym)
helpers_path = File.join(root, config[:helpers_dir])
next unless File.exists?(helpers_path)
Dir[File.join(helpers_path, config[:helpers_filename_glob])].each do |filename| helpers Object.const_get(module_name.to_sym)
module_name = config[:helpers_filename_to_module_name_proc].call(filename)
next unless module_name
require filename
next unless Object.const_defined?(module_name.to_sym)
helpers Object.const_get(module_name.to_sym)
end
end end
end end
alias :included :registered
end end
end end
end end

View file

@ -1,6 +1,3 @@
require 'pathname'
require 'set'
# API for watching file change events # API for watching file change events
module Middleman module Middleman
module CoreExtensions module CoreExtensions
@ -27,7 +24,10 @@ module Middleman
class << self class << self
# Once registered # Once registered
def registered(app) def included(app)
require 'pathname'
require 'set'
app.send :include, InstanceMethods app.send :include, InstanceMethods
app.config.define_setting :file_watcher_ignore, IGNORE_LIST, 'Regexes for paths that should be ignored when they change.' app.config.define_setting :file_watcher_ignore, IGNORE_LIST, 'Regexes for paths that should be ignored when they change.'
@ -46,7 +46,6 @@ module Middleman
files.reload_path('.') files.reload_path('.')
end end
end end
alias :included :registered
end end
# Instance methods # Instance methods

View file

@ -15,7 +15,7 @@ module Middleman
class << self class << self
# Once registered # Once registered
def registered(app) def included(app)
# Include methods # Include methods
app.send :include, InstanceMethods app.send :include, InstanceMethods
@ -29,65 +29,65 @@ module Middleman
# Activate custom renderers # Activate custom renderers
require 'middleman-core/renderers/erb' require 'middleman-core/renderers/erb'
app.register Middleman::Renderers::ERb app.send :include, Middleman::Renderers::ERb
# CoffeeScript Support # CoffeeScript Support
begin begin
require 'middleman-core/renderers/coffee_script' require 'middleman-core/renderers/coffee_script'
app.register Middleman::Renderers::CoffeeScript app.send :include, Middleman::Renderers::CoffeeScript
rescue LoadError rescue LoadError
end end
# Haml Support # Haml Support
begin begin
require 'middleman-core/renderers/haml' require 'middleman-core/renderers/haml'
app.register Middleman::Renderers::Haml app.send :include, Middleman::Renderers::Haml
rescue LoadError rescue LoadError
end end
# Sass Support # Sass Support
begin begin
require 'middleman-core/renderers/sass' require 'middleman-core/renderers/sass'
app.register Middleman::Renderers::Sass app.send :include, Middleman::Renderers::Sass
rescue LoadError rescue LoadError
end end
# Markdown Support # Markdown Support
require 'middleman-core/renderers/markdown' require 'middleman-core/renderers/markdown'
app.register Middleman::Renderers::Markdown app.send :include, Middleman::Renderers::Markdown
# AsciiDoc Support # AsciiDoc Support
begin begin
require 'middleman-core/renderers/asciidoc' require 'middleman-core/renderers/asciidoc'
app.register Middleman::Renderers::AsciiDoc app.send :include, Middleman::Renderers::AsciiDoc
rescue LoadError rescue LoadError
end end
# Liquid Support # Liquid Support
begin begin
require 'middleman-core/renderers/liquid' require 'middleman-core/renderers/liquid'
app.register Middleman::Renderers::Liquid app.send :include, Middleman::Renderers::Liquid
rescue LoadError rescue LoadError
end end
# Slim Support # Slim Support
begin begin
require 'middleman-core/renderers/slim' require 'middleman-core/renderers/slim'
app.register Middleman::Renderers::Slim app.send :include, Middleman::Renderers::Slim
rescue LoadError rescue LoadError
end end
# Less Support # Less Support
begin begin
require 'middleman-core/renderers/less' require 'middleman-core/renderers/less'
app.register Middleman::Renderers::Less app.send :include, Middleman::Renderers::Less
rescue LoadError rescue LoadError
end end
# Stylus Support # Stylus Support
begin begin
require 'middleman-core/renderers/stylus' require 'middleman-core/renderers/stylus'
app.register Middleman::Renderers::Stylus app.send :include, Middleman::Renderers::Stylus
rescue LoadError rescue LoadError
end end
@ -102,8 +102,6 @@ module Middleman
end end
end end
end end
alias :included :registered
end end
# Custom error class for handling # Custom error class for handling

View file

@ -15,8 +15,7 @@ module Middleman
# Extension registered # Extension registered
class << self class << self
# @private # @private
def registered(app) def included(app)
# CSSPIE HTC File # CSSPIE HTC File
::Rack::Mime::MIME_TYPES['.htc'] = 'text/x-component' ::Rack::Mime::MIME_TYPES['.htc'] = 'text/x-component'
@ -32,7 +31,6 @@ module Middleman
# Include instance methods # Include instance methods
app.send :include, InstanceMethods app.send :include, InstanceMethods
end end
alias :included :registered
end end
module ClassMethods module ClassMethods

View file

@ -1,26 +1,20 @@
# Require lib
require 'rack/showexceptions'
# Support rack/showexceptions during development # Support rack/showexceptions during development
module Middleman module Middleman
module CoreExtensions module CoreExtensions
module ShowExceptions module ShowExceptions
def self.included(app)
# Require lib
require 'rack/showexceptions'
# Setup extension # Whether to catch and display exceptions
class << self # @return [Boolean]
app.config.define_setting :show_exceptions, true, 'Whether to catch and display exceptions'
# Once registered # When in dev
def registered(app) app.configure :development do
# Whether to catch and display exceptions # Include middlemare
# @return [Boolean] if config[:show_exceptions]
app.config.define_setting :show_exceptions, true, 'Whether to catch and display exceptions' use ::Rack::ShowExceptions
# When in dev
app.configure :development do
# Include middlemare
if config[:show_exceptions]
use ::Rack::ShowExceptions
end
end end
end end
end end

View file

@ -0,0 +1,149 @@
module Middleman
class Extension
class_attribute :supports_multiple_instances, :instance_reader => false, :instance_writer => false
class_attribute :defined_helpers, :instance_reader => false, :instance_writer => false
class_attribute :ext_name, :instance_reader => false, :instance_writer => false
class << self
def config
@_config ||= ::Middleman::Configuration::ConfigurationManager.new
end
def option(key, default=nil, description=nil)
config.define_setting(key, default, description)
end
# Add helpers to 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
# be used as helpers in a new module.
def helpers(*m, &block)
self.defined_helpers ||= []
if block
mod = Module.new
mod.module_eval(&block)
m = [mod]
end
self.defined_helpers += m
end
def extension_name
self.ext_name || self.name.underscore.split('/').last.to_sym
end
def register(n=self.extension_name)
::Middleman::Extensions.register(n, self)
end
def activate
new(::Middleman::Application)
end
def clear_after_extension_callbacks
@_extension_activation_callbacks = {}
end
def after_extension_activated(name, &block)
@_extension_activation_callbacks ||= {}
@_extension_activation_callbacks[name] ||= []
@_extension_activation_callbacks[name] << block if block_given?
end
def activated_extension(instance)
name = instance.class.extension_name
return unless @_extension_activation_callbacks && @_extension_activation_callbacks[name]
@_extension_activation_callbacks[name].each do |block|
block.arity == 1 ? block.call(instance) : block.call()
end
end
end
attr_accessor :options
attr_reader :app
delegate :after_extension_activated, :to => :"::Middleman::Extension"
def initialize(klass, options_hash={}, &block)
@_helpers = []
@klass = klass
setup_options(options_hash, &block)
setup_app_reference_when_available
# Bind app hooks to local methods
bind_before_configuration
bind_after_configuration
bind_after_build
end
def app=(app)
@app = app
(self.class.defined_helpers || []).each do |m|
app.class.send(:include, m)
end
end
protected
def setup_options(options_hash, &block)
@options = self.class.config.dup
@options.finalize!
options_hash.each do |k, v|
@options[k] = v
end
yield @options if block_given?
end
def setup_app_reference_when_available
ext = self
@klass.initialized do
ext.app = self
end
@klass.instance_available do
ext.app ||= self
end
end
def bind_before_configuration
ext = self
if ext.respond_to?(:before_configuration)
@klass.before_configuration do
ext.before_configuration
end
end
end
def bind_after_configuration
ext = self
@klass.after_configuration do
if ext.respond_to?(:after_configuration)
ext.after_configuration
end
if ext.respond_to?(:manipulate_resource_list)
ext.app.sitemap.register_resource_list_manipulator(ext.class.extension_name, ext)
end
end
end
def bind_after_build
ext = self
if ext.respond_to?(:after_build)
@klass.after_build do |builder|
if ext.method(:after_build).arity === 1
ext.after_build(builder)
else
ext.after_build
end
end
end
end
end
end

View file

@ -20,35 +20,11 @@ module Middleman
# #
# @param [Symbol] name The name of the extension # @param [Symbol] name The name of the extension
# @param [Module] namespace The extension module # @param [Module] namespace The extension module
# @yield Instead of passing a module in namespace, you can provide def register(name, namespace)
# a block which returns your extension module. This gives if !registered.has_key?(name.to_sym)
# you the ability to require other files only when the registered[name.to_sym] = namespace
# extension is activated.
def register(name, namespace=nil, &block)
# If we've already got a matching extension that passed the
# version check, bail out.
return if registered.has_key?(name.to_sym) &&
!registered[name.to_sym].is_a?(String)
registered[name.to_sym] = if block_given?
block
elsif namespace
namespace
end end
end end
def load(name)
name = name.to_sym
return nil unless registered.has_key?(name)
extension = registered[name]
if extension.is_a?(Proc)
extension = extension.call() || nil
registered[name] = extension
end
extension
end
end end
end end
@ -98,152 +74,6 @@ module Middleman
File.exists?(full_path) File.exists?(full_path)
end end
end end
class Extension
class_attribute :supports_multiple_instances, :instance_reader => false, :instance_writer => false
class_attribute :defined_helpers, :instance_reader => false, :instance_writer => false
class_attribute :ext_name, :instance_reader => false, :instance_writer => false
class << self
def config
@_config ||= ::Middleman::Configuration::ConfigurationManager.new
end
def option(key, default=nil, description=nil)
config.define_setting(key, default, description)
end
# Add helpers to 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
# be used as helpers in a new module.
def helpers(*m, &block)
self.defined_helpers ||= []
if block
mod = Module.new
mod.module_eval(&block)
m = [mod]
end
self.defined_helpers += m
end
def extension_name
self.ext_name || self.name.underscore.split('/').last.to_sym
end
def register(n=self.extension_name)
::Middleman::Extensions.register(n, self)
end
def activate
new(::Middleman::Application)
end
def clear_after_extension_callbacks
@_extension_activation_callbacks = {}
end
def after_extension_activated(name, &block)
@_extension_activation_callbacks ||= {}
@_extension_activation_callbacks[name] ||= []
@_extension_activation_callbacks[name] << block if block_given?
end
def activated_extension(instance)
name = instance.class.extension_name
return unless @_extension_activation_callbacks && @_extension_activation_callbacks[name]
@_extension_activation_callbacks[name].each do |block|
block.arity == 1 ? block.call(instance) : block.call()
end
end
end
attr_accessor :options
attr_reader :app
delegate :after_extension_activated, :to => :"::Middleman::Extension"
def initialize(klass, options_hash={}, &block)
@_helpers = []
@klass = klass
setup_options(options_hash, &block)
setup_app_reference_when_available
# Bind app hooks to local methods
bind_before_configuration
bind_after_configuration
bind_after_build
end
def app=(app)
@app = app
(self.class.defined_helpers || []).each do |m|
app.class.send(:include, m)
end
end
protected
def setup_options(options_hash, &block)
@options = self.class.config.dup
@options.finalize!
options_hash.each do |k, v|
@options[k] = v
end
yield @options if block_given?
end
def setup_app_reference_when_available
ext = self
@klass.initialized do
ext.app = self
end
@klass.instance_available do
ext.app ||= self
end
end
def bind_before_configuration
ext = self
if ext.respond_to?(:before_configuration)
@klass.before_configuration do
ext.before_configuration
end
end
end
def bind_after_configuration
ext = self
@klass.after_configuration do
if ext.respond_to?(:after_configuration)
ext.after_configuration
end
if ext.respond_to?(:manipulate_resource_list)
ext.app.sitemap.register_resource_list_manipulator(ext.class.extension_name, ext)
end
end
end
def bind_after_build
ext = self
if ext.respond_to?(:after_build)
@klass.after_build do |builder|
if ext.method(:after_build).arity === 1
ext.after_build(builder)
else
ext.after_build
end
end
end
end
end
end end
require 'middleman-core/extension'

View file

@ -7,7 +7,7 @@ module Middleman
class << self class << self
# Once registered # Once registered
def registered(app) def included(app)
# Set to automatically convert some characters into a directory # Set to automatically convert some characters into a directory
app.config.define_setting :automatic_directory_matcher, nil, 'Set to automatically convert some characters into a directory' app.config.define_setting :automatic_directory_matcher, nil, 'Set to automatically convert some characters into a directory'
@ -33,7 +33,6 @@ module Middleman
# Include instance methods # Include instance methods
app.send :include, InstanceMethods app.send :include, InstanceMethods
end end
alias :included :registered
end end

View file

@ -1,11 +1,12 @@
require 'middleman-core/renderers/sass' require 'middleman-core/renderers/sass'
require 'compass'
class Middleman::CoreExtensions::Compass < ::Middleman::Extension class Middleman::CoreExtensions::Compass < ::Middleman::Extension
def initialize(app, options_hash={}, &block) def initialize(app, options_hash={}, &block)
super super
require 'compass'
# Hooks to manually update the compass config after we're # Hooks to manually update the compass config after we're
# done with it # done with it
app.define_hook :compass_config app.define_hook :compass_config
@ -73,3 +74,5 @@ class Middleman::CoreExtensions::Compass < ::Middleman::Extension
end end
end end
end end
Middleman::CoreExtensions::Compass.register

View file

@ -248,3 +248,5 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension
end end
end end
end end
Middleman::CoreExtensions::DefaultHelpers.register

View file

@ -209,3 +209,5 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
end end
end end
end end
Middleman::CoreExtensions::Internationalization.register(:i18n)

View file

@ -174,3 +174,5 @@ class Middleman::Extensions::Lorem < ::Middleman::Extension
end end
end end
end end
Middleman::Extensions::Lorem.register