Finish porting to new callbacks manager
This commit is contained in:
parent
f8e4f6f059
commit
e64954fbff
15 changed files with 330 additions and 193 deletions
|
@ -1,29 +1,14 @@
|
||||||
# i18n Built-in
|
|
||||||
require 'i18n'
|
|
||||||
|
|
||||||
# Don't fail on invalid locale, that's not what our current
|
|
||||||
# users expect.
|
|
||||||
::I18n.enforce_available_locales = false
|
|
||||||
|
|
||||||
# Use ActiveSupport JSON
|
# Use ActiveSupport JSON
|
||||||
require 'active_support/json'
|
require 'active_support/json'
|
||||||
require 'active_support/core_ext/integer/inflections'
|
require 'active_support/core_ext/integer/inflections'
|
||||||
|
|
||||||
# Simple callback library
|
|
||||||
require 'hooks'
|
|
||||||
|
|
||||||
# Our custom logger
|
|
||||||
require 'middleman-core/logger'
|
|
||||||
|
|
||||||
require 'middleman-core/contracts'
|
require 'middleman-core/contracts'
|
||||||
|
require 'middleman-core/callback_manager'
|
||||||
|
require 'middleman-core/logger'
|
||||||
require 'middleman-core/sitemap/store'
|
require 'middleman-core/sitemap/store'
|
||||||
|
|
||||||
require 'middleman-core/configuration'
|
require 'middleman-core/configuration'
|
||||||
|
|
||||||
require 'middleman-core/extension_manager'
|
require 'middleman-core/extension_manager'
|
||||||
require 'middleman-core/core_extensions'
|
require 'middleman-core/core_extensions'
|
||||||
|
|
||||||
require 'middleman-core/config_context'
|
require 'middleman-core/config_context'
|
||||||
require 'middleman-core/file_renderer'
|
require 'middleman-core/file_renderer'
|
||||||
require 'middleman-core/template_renderer'
|
require 'middleman-core/template_renderer'
|
||||||
|
@ -38,6 +23,9 @@ module Middleman
|
||||||
include Contracts
|
include Contracts
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
extend Forwardable
|
||||||
|
def_delegator :config, :define_setting
|
||||||
|
|
||||||
# Global configuration for the whole Middleman project.
|
# Global configuration for the whole Middleman project.
|
||||||
# @return [ConfigurationManager]
|
# @return [ConfigurationManager]
|
||||||
def config
|
def config
|
||||||
|
@ -56,38 +44,37 @@ module Middleman
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Uses callbacks
|
Contract ::Middleman::ConfigContext
|
||||||
include Hooks
|
attr_reader :config_context
|
||||||
include Hooks::InstanceHooks
|
|
||||||
|
|
||||||
define_hook :initialized
|
Contract ::Middleman::Sitemap::Store
|
||||||
define_hook :after_configuration
|
attr_reader :sitemap
|
||||||
define_hook :before_configuration
|
|
||||||
|
|
||||||
# Before request hook
|
# An anonymous subclass of ::Middleman::TemplateContext
|
||||||
define_hook :before
|
attr_reader :template_context_class
|
||||||
|
|
||||||
# Ready (all loading and parsing of extensions complete) hook
|
# An instance of the above anonymouse class.
|
||||||
define_hook :ready
|
attr_reader :generic_template_context
|
||||||
|
|
||||||
# Runs before the build is started
|
Contract ::Middleman::Configuration::ConfigurationManager
|
||||||
define_hook :before_build
|
attr_reader :config
|
||||||
|
|
||||||
# Runs after the build is finished
|
Contract ::Middleman::ExtensionManager
|
||||||
define_hook :after_build
|
attr_reader :extensions
|
||||||
|
|
||||||
define_hook :before_shutdown
|
Contract SetOf[MiddlewareDescriptor]
|
||||||
|
attr_reader :middleware
|
||||||
|
|
||||||
define_hook :before_render
|
Contract SetOf[MapDescriptor]
|
||||||
define_hook :after_render
|
attr_reader :mappings
|
||||||
|
|
||||||
# Which host preview should start on.
|
# Which host preview should start on.
|
||||||
# @return [Fixnum]
|
# @return [Fixnum]
|
||||||
config.define_setting :host, '0.0.0.0', 'The preview server host'
|
define_setting :host, '0.0.0.0', 'The preview server host'
|
||||||
|
|
||||||
# Which port preview should start on.
|
# Which port preview should start on.
|
||||||
# @return [Fixnum]
|
# @return [Fixnum]
|
||||||
config.define_setting :port, 4567, 'The preview server port'
|
define_setting :port, 4567, 'The preview server port'
|
||||||
|
|
||||||
# Whether to serve the preview server over HTTPS.
|
# Whether to serve the preview server over HTTPS.
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
|
@ -103,73 +90,73 @@ module Middleman
|
||||||
|
|
||||||
# Name of the source directory
|
# Name of the source directory
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :source, 'source', 'Name of the source directory'
|
define_setting :source, 'source', 'Name of the source directory'
|
||||||
|
|
||||||
# Middleman mode. Defaults to :server, set to :build by the build process
|
# Middleman mode. Defaults to :server, set to :build by the build process
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :mode, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :server), 'Middleman mode. Defaults to :server'
|
define_setting :mode, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :server), 'Middleman mode. Defaults to :server'
|
||||||
|
|
||||||
# Middleman environment. Defaults to :development
|
# Middleman environment. Defaults to :development
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :environment, :development, 'Middleman environment. Defaults to :development'
|
define_setting :environment, :development, 'Middleman environment. Defaults to :development'
|
||||||
|
|
||||||
# Which file should be used for directory indexes
|
# Which file should be used for directory indexes
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :index_file, 'index.html', 'Which file should be used for directory indexes'
|
define_setting :index_file, 'index.html', 'Which file should be used for directory indexes'
|
||||||
|
|
||||||
# Whether to strip the index file name off links to directory indexes
|
# Whether to strip the index file name off links to directory indexes
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
config.define_setting :strip_index_file, true, 'Whether to strip the index file name off links to directory indexes'
|
define_setting :strip_index_file, true, 'Whether to strip the index file name off links to directory indexes'
|
||||||
|
|
||||||
# Whether to include a trailing slash when stripping the index file
|
# Whether to include a trailing slash when stripping the index file
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
config.define_setting :trailing_slash, true, 'Whether to include a trailing slash when stripping the index file'
|
define_setting :trailing_slash, true, 'Whether to include a trailing slash when stripping the index file'
|
||||||
|
|
||||||
# Location of javascripts within source.
|
# Location of javascripts within source.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :js_dir, 'javascripts', 'Location of javascripts within source'
|
define_setting :js_dir, 'javascripts', 'Location of javascripts within source'
|
||||||
|
|
||||||
# Location of stylesheets within source. Used by Compass.
|
# Location of stylesheets within source. Used by Compass.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :css_dir, 'stylesheets', 'Location of stylesheets within source'
|
define_setting :css_dir, 'stylesheets', 'Location of stylesheets within source'
|
||||||
|
|
||||||
# Location of images within source. Used by HTML helpers and Compass.
|
# Location of images within source. Used by HTML helpers and Compass.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :images_dir, 'images', 'Location of images within source'
|
define_setting :images_dir, 'images', 'Location of images within source'
|
||||||
|
|
||||||
# Location of fonts within source. Used by Compass.
|
# Location of fonts within source. Used by Compass.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :fonts_dir, 'fonts', 'Location of fonts within source'
|
define_setting :fonts_dir, 'fonts', 'Location of fonts within source'
|
||||||
|
|
||||||
# Location of layouts within source. Used by renderers.
|
# Location of layouts within source. Used by renderers.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :layouts_dir, 'layouts', 'Location of layouts within source'
|
define_setting :layouts_dir, 'layouts', 'Location of layouts within source'
|
||||||
|
|
||||||
# Where to build output files
|
# Where to build output files
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :build_dir, 'build', 'Where to build output files'
|
define_setting :build_dir, 'build', 'Where to build output files'
|
||||||
|
|
||||||
# Default prefix for building paths. Used by HTML helpers and Compass.
|
# Default prefix for building paths. Used by HTML helpers and Compass.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :http_prefix, '/', 'Default prefix for building paths'
|
define_setting :http_prefix, '/', 'Default prefix for building paths'
|
||||||
|
|
||||||
# Default layout name
|
# Default layout name
|
||||||
# @return [String, Symbold]
|
# @return [String, Symbold]
|
||||||
config.define_setting :layout, :_auto_layout, 'Default layout name'
|
define_setting :layout, :_auto_layout, 'Default layout name'
|
||||||
|
|
||||||
# Default string encoding for templates and output.
|
# Default string encoding for templates and output.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
config.define_setting :encoding, 'utf-8', 'Default string encoding for templates and output'
|
define_setting :encoding, 'utf-8', 'Default string encoding for templates and output'
|
||||||
|
|
||||||
# Should Padrino include CRSF tag
|
# Should Padrino include CRSF tag
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
config.define_setting :protect_from_csrf, false, 'Should Padrino include CRSF tag'
|
define_setting :protect_from_csrf, false, 'Should Padrino include CRSF tag'
|
||||||
|
|
||||||
# Set to automatically convert some characters into a directory
|
# Set to automatically convert some characters into a directory
|
||||||
config.define_setting :automatic_directory_matcher, nil, 'Set to automatically convert some characters into a directory'
|
define_setting :automatic_directory_matcher, nil, 'Set to automatically convert some characters into a directory'
|
||||||
|
|
||||||
# Setup callbacks which can exclude paths from the sitemap
|
# Setup callbacks which can exclude paths from the sitemap
|
||||||
config.define_setting :ignored_sitemap_matchers, {
|
define_setting :ignored_sitemap_matchers, {
|
||||||
# Files starting with an underscore, but not a double-underscore
|
# Files starting with an underscore, but not a double-underscore
|
||||||
partials: proc { |file|
|
partials: proc { |file|
|
||||||
ignored = false
|
ignored = false
|
||||||
|
@ -190,37 +177,40 @@ module Middleman
|
||||||
}
|
}
|
||||||
}, 'Callbacks that can exclude paths from the sitemap'
|
}, 'Callbacks that can exclude paths from the sitemap'
|
||||||
|
|
||||||
config.define_setting :watcher_disable, false, 'If the Listen watcher should not run'
|
define_setting :watcher_disable, false, 'If the Listen watcher should not run'
|
||||||
config.define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode'
|
define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode'
|
||||||
config.define_setting :watcher_latency, nil, 'The Listen watcher latency'
|
define_setting :watcher_latency, nil, 'The Listen watcher latency'
|
||||||
|
|
||||||
attr_reader :config_context
|
# Delegate convenience methods off to their implementations
|
||||||
attr_reader :sitemap
|
|
||||||
attr_reader :cache
|
|
||||||
attr_reader :template_context_class
|
|
||||||
attr_reader :config
|
|
||||||
attr_reader :generic_template_context
|
|
||||||
attr_reader :extensions
|
|
||||||
attr_reader :sources
|
|
||||||
|
|
||||||
Contract SetOf[MiddlewareDescriptor]
|
|
||||||
attr_reader :middleware
|
|
||||||
|
|
||||||
Contract SetOf[MapDescriptor]
|
|
||||||
attr_reader :mappings
|
|
||||||
|
|
||||||
# Reference to Logger singleton
|
|
||||||
def_delegator :"::Middleman::Logger", :singleton, :logger
|
def_delegator :"::Middleman::Logger", :singleton, :logger
|
||||||
def_delegator :"::Middleman::Util", :instrument
|
def_delegator :"::Middleman::Util", :instrument
|
||||||
def_delegators :"self.class", :root, :root_path
|
def_delegators :"self.class", :root, :root_path
|
||||||
def_delegators :@generic_template_context, :link_to, :image_tag, :asset_path
|
def_delegators :@generic_template_context, :link_to, :image_tag, :asset_path
|
||||||
def_delegators :@extensions, :activate
|
def_delegators :@extensions, :activate
|
||||||
|
def_delegators :config, :define_setting
|
||||||
|
|
||||||
# Initialize the Middleman project
|
# Initialize the Middleman project
|
||||||
def initialize(&block)
|
def initialize(&block)
|
||||||
# Search the root of the project for required files
|
# Search the root of the project for required files
|
||||||
$LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root)
|
$LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root)
|
||||||
|
|
||||||
|
@callbacks = ::Middleman::CallbackManager.new
|
||||||
|
@callbacks.install_methods!(self, [
|
||||||
|
:initialized,
|
||||||
|
:configure,
|
||||||
|
:before_sitemap,
|
||||||
|
:before_configuration,
|
||||||
|
:after_configuration,
|
||||||
|
:after_configuration_eval,
|
||||||
|
:ready,
|
||||||
|
:before_build,
|
||||||
|
:after_build,
|
||||||
|
:before_shutdown,
|
||||||
|
:before, # Before Rack requests
|
||||||
|
:before_render,
|
||||||
|
:after_render
|
||||||
|
])
|
||||||
|
|
||||||
@middleware = Set.new
|
@middleware = Set.new
|
||||||
@mappings = Set.new
|
@mappings = Set.new
|
||||||
|
|
||||||
|
@ -228,21 +218,22 @@ module Middleman
|
||||||
@generic_template_context = @template_context_class.new(self)
|
@generic_template_context = @template_context_class.new(self)
|
||||||
@config_context = ConfigContext.new(self, @template_context_class)
|
@config_context = ConfigContext.new(self, @template_context_class)
|
||||||
|
|
||||||
::Middleman::FileRenderer.cache.clear
|
|
||||||
::Middleman::TemplateRenderer.cache.clear
|
|
||||||
|
|
||||||
# Setup the default values from calls to set before initialization
|
# Setup the default values from calls to set before initialization
|
||||||
@config = ::Middleman::Configuration::ConfigurationManager.new
|
@config = ::Middleman::Configuration::ConfigurationManager.new
|
||||||
@config.load_settings(self.class.config.all_settings)
|
@config.load_settings(self.class.config.all_settings)
|
||||||
|
|
||||||
config[:source] = ENV['MM_SOURCE'] if ENV['MM_SOURCE']
|
config[:source] = ENV['MM_SOURCE'] if ENV['MM_SOURCE']
|
||||||
|
|
||||||
|
# TODO, make this less global
|
||||||
|
::Middleman::FileRenderer.cache.clear
|
||||||
|
::Middleman::TemplateRenderer.cache.clear
|
||||||
|
|
||||||
@extensions = ::Middleman::ExtensionManager.new(self)
|
@extensions = ::Middleman::ExtensionManager.new(self)
|
||||||
|
|
||||||
# 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?
|
||||||
|
|
||||||
@extensions.auto_activate(:before_sitemap)
|
execute_callbacks(:before_sitemap)
|
||||||
|
|
||||||
# Initialize the Sitemap
|
# Initialize the Sitemap
|
||||||
@sitemap = ::Middleman::Sitemap::Store.new(self)
|
@sitemap = ::Middleman::Sitemap::Store.new(self)
|
||||||
|
@ -254,42 +245,34 @@ module Middleman
|
||||||
|
|
||||||
::Middleman::Extension.clear_after_extension_callbacks
|
::Middleman::Extension.clear_after_extension_callbacks
|
||||||
|
|
||||||
@extensions.auto_activate(:before_configuration)
|
after_configuration_eval(&method(:prune_tilt_templates))
|
||||||
|
|
||||||
run_hook :initialized
|
start_lifecycle
|
||||||
|
|
||||||
run_hook :before_configuration
|
|
||||||
|
|
||||||
evaluate_configuration
|
|
||||||
|
|
||||||
# This is for making the tests work - since the tests
|
|
||||||
# don't completely reload middleman, I18n.load_path can get
|
|
||||||
# polluted with paths from other test app directories that don't
|
|
||||||
# exist anymore.
|
|
||||||
if ENV['TEST']
|
|
||||||
::I18n.load_path.delete_if { |path| path =~ %r{tmp/aruba} }
|
|
||||||
::I18n.reload!
|
|
||||||
end
|
|
||||||
|
|
||||||
# Clean up missing Tilt exts
|
|
||||||
Tilt.mappings.each do |key, _|
|
|
||||||
begin
|
|
||||||
Tilt[".#{key}"]
|
|
||||||
rescue LoadError, NameError
|
|
||||||
Tilt.mappings.delete(key)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@extensions.activate_all
|
|
||||||
|
|
||||||
run_hook :after_configuration
|
|
||||||
config_context.execute_callbacks(:after_configuration)
|
|
||||||
|
|
||||||
run_hook :ready
|
|
||||||
@config_context.execute_callbacks(:ready)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_configuration
|
# Boot the app.
|
||||||
|
def start_lifecycle
|
||||||
|
# Before config is parsed, before extensions get to it.
|
||||||
|
execute_callbacks(:initialized)
|
||||||
|
|
||||||
|
# Before config is parsed. Mostly used for extensions.
|
||||||
|
execute_callbacks(:before_configuration)
|
||||||
|
|
||||||
|
# Eval config.
|
||||||
|
evaluate_configuration!
|
||||||
|
|
||||||
|
# Post parsing, pre-extension callback
|
||||||
|
execute_callbacks(:after_configuration_eval)
|
||||||
|
|
||||||
|
# After extensions have worked after_config
|
||||||
|
execute_callbacks(:after_configuration)
|
||||||
|
|
||||||
|
# Everything is stable
|
||||||
|
execute_callbacks(:ready)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Eval config
|
||||||
|
def evaluate_configuration!
|
||||||
# Check for and evaluate local configuration in `config.rb`
|
# Check for and evaluate local configuration in `config.rb`
|
||||||
config_rb = File.join(root, 'config.rb')
|
config_rb = File.join(root, 'config.rb')
|
||||||
if File.exist? config_rb
|
if File.exist? config_rb
|
||||||
|
@ -311,49 +294,67 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run any `configure` blocks for the current environment.
|
# Run any `configure` blocks for the current environment.
|
||||||
config_context.execute_callbacks([:configure, config[:environment]])
|
execute_callbacks([:configure, config[:environment]])
|
||||||
|
|
||||||
# Run any `configure` blocks for the current mode.
|
# Run any `configure` blocks for the current mode.
|
||||||
config_context.execute_callbacks([:configure, config[:mode]])
|
execute_callbacks([:configure, config[:mode]])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Clean up missing Tilt exts
|
||||||
|
def prune_tilt_templates
|
||||||
|
::Tilt.mappings.each do |key, _|
|
||||||
|
begin
|
||||||
|
::Tilt[".#{key}"]
|
||||||
|
rescue LoadError, NameError
|
||||||
|
::Tilt.mappings.delete(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether we're in server mode
|
# Whether we're in server mode
|
||||||
# @return [Boolean] If we're in dev mode
|
# @return [Boolean] If we're in dev mode
|
||||||
|
Contract Bool
|
||||||
def server?
|
def server?
|
||||||
config[:mode] == :server
|
config[:mode] == :server
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether we're in build mode
|
# Whether we're in build mode
|
||||||
# @return [Boolean] If we're in dev mode
|
# @return [Boolean] If we're in dev mode
|
||||||
|
Contract Bool
|
||||||
def build?
|
def build?
|
||||||
config[:mode] == :build
|
config[:mode] == :build
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether we're in a specific environment
|
# Whether we're in a specific environment
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
|
Contract Bool
|
||||||
def environment?(key)
|
def environment?(key)
|
||||||
config[:environment] == key
|
config[:environment] == key
|
||||||
end
|
end
|
||||||
|
|
||||||
# Backwards compatible helper. What the current environment is.
|
# Backwards compatible helper. What the current environment is.
|
||||||
# @return [Symbol]
|
# @return [Symbol]
|
||||||
|
Contract Symbol
|
||||||
def environment
|
def environment
|
||||||
config[:environment]
|
config[:environment]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Backwards compatible helper. Whether we're in dev mode.
|
# Backwards compatible helper. Whether we're in dev mode.
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
|
Contract Bool
|
||||||
def development?
|
def development?
|
||||||
environment?(:development)
|
environment?(:development)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Backwards compatible helper. Whether we're in production mode.
|
# Backwards compatible helper. Whether we're in production mode.
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
|
Contract Bool
|
||||||
def production?
|
def production?
|
||||||
environment?(:production)
|
environment?(:production)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Backwards compatible helper. The full path to the default source dir.
|
# Backwards compatible helper. The full path to the default source dir.
|
||||||
|
Contract Pathname
|
||||||
def source_dir
|
def source_dir
|
||||||
Pathname(File.join(root, config[:source]))
|
Pathname(File.join(root, config[:source]))
|
||||||
end
|
end
|
||||||
|
@ -376,8 +377,9 @@ module Middleman
|
||||||
@mappings << MapDescriptor.new(map, block)
|
@mappings << MapDescriptor.new(map, block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Let everyone know we're shutting down.
|
||||||
def shutdown!
|
def shutdown!
|
||||||
run_hook :before_shutdown
|
execute_callbacks(:before_shutdown)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Work around this bug: http://bugs.ruby-lang.org/issues/4521
|
# Work around this bug: http://bugs.ruby-lang.org/issues/4521
|
||||||
|
|
|
@ -2,6 +2,7 @@ require 'pathname'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
require 'middleman-core/rack'
|
require 'middleman-core/rack'
|
||||||
|
require 'middleman-core/callback_manager'
|
||||||
require 'middleman-core/contracts'
|
require 'middleman-core/contracts'
|
||||||
|
|
||||||
module Middleman
|
module Middleman
|
||||||
|
@ -36,10 +37,11 @@ module Middleman
|
||||||
@glob = opts.fetch(:glob)
|
@glob = opts.fetch(:glob)
|
||||||
@cleaning = opts.fetch(:clean)
|
@cleaning = opts.fetch(:clean)
|
||||||
|
|
||||||
@_event_callbacks = []
|
|
||||||
|
|
||||||
rack_app = ::Middleman::Rack.new(@app).to_app
|
rack_app = ::Middleman::Rack.new(@app).to_app
|
||||||
@rack = ::Rack::MockRequest.new(rack_app)
|
@rack = ::Rack::MockRequest.new(rack_app)
|
||||||
|
|
||||||
|
@callbacks = ::Middleman::CallbackManager.new
|
||||||
|
@callbacks.install_methods!(self, [:on_build_event])
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run the build phase.
|
# Run the build phase.
|
||||||
|
@ -49,7 +51,7 @@ module Middleman
|
||||||
@has_error = false
|
@has_error = false
|
||||||
@events = {}
|
@events = {}
|
||||||
|
|
||||||
@app.run_hook :before_build, self
|
@app.execute_callbacks(:before_build, [self])
|
||||||
|
|
||||||
queue_current_paths if @cleaning
|
queue_current_paths if @cleaning
|
||||||
prerender_css
|
prerender_css
|
||||||
|
@ -60,21 +62,11 @@ module Middleman
|
||||||
|
|
||||||
::Middleman::Profiling.report('build')
|
::Middleman::Profiling.report('build')
|
||||||
|
|
||||||
# Run hooks
|
@app.execute_callbacks(:after_build, [self])
|
||||||
@app.run_hook :after_build, self
|
|
||||||
@app.config_context.execute_callbacks(:after_build, [self])
|
|
||||||
|
|
||||||
!@has_error
|
!@has_error
|
||||||
end
|
end
|
||||||
|
|
||||||
# Attach callbacks for build events.
|
|
||||||
# @return [Array<Proc>] All the attached events.
|
|
||||||
Contract Proc => ArrayOf[Proc]
|
|
||||||
def on_build_event(&block)
|
|
||||||
@_event_callbacks << block if block_given?
|
|
||||||
@_event_callbacks
|
|
||||||
end
|
|
||||||
|
|
||||||
# Pre-request CSS to give Compass a chance to build sprites
|
# Pre-request CSS to give Compass a chance to build sprites
|
||||||
# @return [Array<Resource>] List of css resources that were output.
|
# @return [Array<Resource>] List of css resources that were output.
|
||||||
Contract ResourceList
|
Contract ResourceList
|
||||||
|
@ -253,9 +245,7 @@ module Middleman
|
||||||
@events[event_type] ||= []
|
@events[event_type] ||= []
|
||||||
@events[event_type] << target
|
@events[event_type] << target
|
||||||
|
|
||||||
@_event_callbacks.each do |callback|
|
execute_callbacks(:on_build_event, [event_type, target, extra])
|
||||||
callback.call(event_type, target, extra)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,22 +11,23 @@ module Middleman
|
||||||
@callbacks = ::Hamster.hash
|
@callbacks = ::Hamster.hash
|
||||||
end
|
end
|
||||||
|
|
||||||
Contract RespondTo[:define_singleton_method], ArrayOf[Symbol], Maybe[Proc] => Any
|
Contract RespondTo[:define_singleton_method], ArrayOf[Symbol] => Any
|
||||||
def install_methods!(install_target, names, &block)
|
def install_methods!(install_target, names)
|
||||||
manager = self
|
manager = self
|
||||||
|
|
||||||
names.each do |name|
|
names.each do |method_name|
|
||||||
method_name = block_given? ? block.call(name) : name
|
|
||||||
|
|
||||||
install_target.define_singleton_method(method_name) do |*keys, &b|
|
install_target.define_singleton_method(method_name) do |*keys, &b|
|
||||||
key_set = keys.unshift(name)
|
key_set = keys.unshift(method_name)
|
||||||
manager.add(key_set.length > 1 ? key_set : key_set.first, &b)
|
manager.add(key_set.length > 1 ? key_set : key_set[0], &b)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
install_target.define_singleton_method(:execute_callbacks) do |keys, *args|
|
install_target.define_singleton_method(:execute_callbacks) do |*args|
|
||||||
manager.execute(keys, args, self)
|
keys = args.shift
|
||||||
|
manager.execute(keys, args[0], self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
install_target.define_singleton_method(:callbacks_for, &method(:callbacks_for))
|
||||||
end
|
end
|
||||||
|
|
||||||
Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
|
Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
|
||||||
|
@ -34,16 +35,19 @@ module Middleman
|
||||||
immutable_keys = keys.is_a?(Symbol) ? keys : ::Hamster::Vector.new(keys)
|
immutable_keys = keys.is_a?(Symbol) ? keys : ::Hamster::Vector.new(keys)
|
||||||
|
|
||||||
@callbacks = @callbacks.put(immutable_keys) do |v|
|
@callbacks = @callbacks.put(immutable_keys) do |v|
|
||||||
v.nil? ? ::Hamster.set(block) : v.add(block)
|
v.nil? ? ::Hamster::Vector.new([block]) : v.push(block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Contract Or[Symbol, ArrayOf[Symbol]], Maybe[ArrayOf[Any]], Maybe[RespondTo[:instance_exec]] => Any
|
Contract Or[Symbol, ArrayOf[Symbol]], Maybe[ArrayOf[Any]], Maybe[RespondTo[:instance_exec]] => Any
|
||||||
def execute(keys, args=[], scope=self)
|
def execute(keys, args=[], scope=self)
|
||||||
immutable_keys = keys.is_a?(Symbol) ? keys : ::Hamster::Vector.new(keys)
|
callbacks_for(keys).each { |b| scope.instance_exec(*args, &b) }
|
||||||
|
end
|
||||||
|
|
||||||
callbacks = @callbacks.get(immutable_keys)
|
Contract Or[Symbol, ArrayOf[Symbol]] => ::Hamster::Vector
|
||||||
callbacks && callbacks.each { |b| scope.instance_exec(*args, &b) }
|
def callbacks_for(keys)
|
||||||
|
immutable_keys = keys.is_a?(Symbol) ? keys : ::Hamster::Vector.new(keys)
|
||||||
|
@callbacks.get(immutable_keys) || ::Hamster.vector
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,8 +15,19 @@ module Middleman
|
||||||
@app = app
|
@app = app
|
||||||
@template_context_class = template_context_class
|
@template_context_class = template_context_class
|
||||||
|
|
||||||
|
sub_callbacks = [:before_build, :after_build, :configure, :after_configuration, :ready]
|
||||||
|
|
||||||
@callbacks = ::Middleman::CallbackManager.new
|
@callbacks = ::Middleman::CallbackManager.new
|
||||||
@callbacks.install_methods!(self, [:ready, :after_build, :after_configuration, :configure])
|
@callbacks.install_methods!(self, sub_callbacks)
|
||||||
|
|
||||||
|
# Trigger internal callbacks when app level are executed.
|
||||||
|
self_context = self
|
||||||
|
|
||||||
|
sub_callbacks.each do |key|
|
||||||
|
app.send(key) do |*args|
|
||||||
|
self_context.execute_callbacks(key, args)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def helpers(*helper_modules, &block)
|
def helpers(*helper_modules, &block)
|
||||||
|
|
|
@ -10,6 +10,25 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
|
||||||
# Exposes `langs` to templates
|
# Exposes `langs` to templates
|
||||||
expose_to_template :langs
|
expose_to_template :langs
|
||||||
|
|
||||||
|
def initialize(*)
|
||||||
|
super
|
||||||
|
|
||||||
|
require 'i18n'
|
||||||
|
|
||||||
|
# Don't fail on invalid locale, that's not what our current
|
||||||
|
# users expect.
|
||||||
|
::I18n.enforce_available_locales = false
|
||||||
|
|
||||||
|
# This is for making the tests work - since the tests
|
||||||
|
# don't completely reload middleman, I18n.load_path can get
|
||||||
|
# polluted with paths from other test app directories that don't
|
||||||
|
# exist anymore.
|
||||||
|
app.after_configuration_eval do
|
||||||
|
::I18n.load_path.delete_if { |path| path =~ %r{tmp/aruba} }
|
||||||
|
::I18n.reload!
|
||||||
|
end if ENV['TEST']
|
||||||
|
end
|
||||||
|
|
||||||
def after_configuration
|
def after_configuration
|
||||||
# See https://github.com/svenfuchs/i18n/wiki/Fallbacks
|
# See https://github.com/svenfuchs/i18n/wiki/Fallbacks
|
||||||
unless options[:no_fallbacks]
|
unless options[:no_fallbacks]
|
||||||
|
|
|
@ -380,6 +380,7 @@ module Middleman
|
||||||
|
|
||||||
def bind_after_configuration
|
def bind_after_configuration
|
||||||
ext = self
|
ext = self
|
||||||
|
|
||||||
@app.after_configuration do
|
@app.after_configuration do
|
||||||
ext.after_configuration if ext.respond_to?(:after_configuration)
|
ext.after_configuration if ext.respond_to?(:after_configuration)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,17 @@ module Middleman
|
||||||
def initialize(app)
|
def initialize(app)
|
||||||
@app = app
|
@app = app
|
||||||
@activated = {}
|
@activated = {}
|
||||||
|
|
||||||
|
manager = self
|
||||||
|
{
|
||||||
|
before_sitemap: :before_sitemap,
|
||||||
|
initialized: :before_configuration
|
||||||
|
}.each do |key, value|
|
||||||
|
cb = proc { manager.auto_activate(value) }
|
||||||
|
@app.send(key, &cb)
|
||||||
|
end
|
||||||
|
|
||||||
|
@app.after_configuration_eval(&method(:activate_all))
|
||||||
end
|
end
|
||||||
|
|
||||||
def auto_activate(key)
|
def auto_activate(key)
|
||||||
|
|
|
@ -59,14 +59,10 @@ module Middleman
|
||||||
options = options.deep_merge(options[:renderer_options]) if options[:renderer_options]
|
options = options.deep_merge(options[:renderer_options]) if options[:renderer_options]
|
||||||
|
|
||||||
template_class = ::Tilt[path]
|
template_class = ::Tilt[path]
|
||||||
|
|
||||||
# Allow hooks to manipulate the template before render
|
# Allow hooks to manipulate the template before render
|
||||||
@app.class.callbacks_for_hook(:before_render).each do |callback|
|
body = @app.callbacks_for(:before_render).reduce(body) do |sum, callback|
|
||||||
newbody = if callback.respond_to?(:call)
|
callback.call(sum, path, locs, template_class) || sum
|
||||||
callback.call(body, path, locs, template_class)
|
|
||||||
elsif callback.respond_to?(:evaluate)
|
|
||||||
callback.evaluate(self, body, path, locs, template_class)
|
|
||||||
end
|
|
||||||
body = newbody if newbody # Allow the callback to return nil to skip it
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read compiled template from disk or cache
|
# Read compiled template from disk or cache
|
||||||
|
@ -80,14 +76,8 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
# Allow hooks to manipulate the result after render
|
# Allow hooks to manipulate the result after render
|
||||||
@app.class.callbacks_for_hook(:after_render).each do |callback|
|
content = @app.callbacks_for(:before_render).reduce(content) do |sum, callback|
|
||||||
# Uber::Options::Value doesn't respond to call
|
callback.call(sum, path, locs, template_class) || sum
|
||||||
newcontent = if callback.respond_to?(:call)
|
|
||||||
callback.call(content, path, locs, template_class)
|
|
||||||
elsif callback.respond_to?(:evaluate)
|
|
||||||
callback.evaluate(self, content, path, locs, template_class)
|
|
||||||
end
|
|
||||||
content = newcontent if newcontent # Allow the callback to return nil to skip it
|
|
||||||
end
|
end
|
||||||
|
|
||||||
output = ::ActiveSupport::SafeBuffer.new ''
|
output = ::ActiveSupport::SafeBuffer.new ''
|
||||||
|
|
|
@ -85,7 +85,7 @@ module Middleman
|
||||||
full_request_path = File.join(env['SCRIPT_NAME'], request_path) # Path including rack mount
|
full_request_path = File.join(env['SCRIPT_NAME'], request_path) # Path including rack mount
|
||||||
|
|
||||||
# Run before callbacks
|
# Run before callbacks
|
||||||
@middleman.run_hook :before
|
@middleman.execute_callbacks(:before)
|
||||||
|
|
||||||
# Get the resource object for this path
|
# Get the resource object for this path
|
||||||
resource = @middleman.sitemap.find_resource_by_destination_path(request_path.gsub(' ', '%20'))
|
resource = @middleman.sitemap.find_resource_by_destination_path(request_path.gsub(' ', '%20'))
|
||||||
|
|
|
@ -13,9 +13,7 @@ module Middleman
|
||||||
::Tilt.register 'coffee', DebuggingCoffeeScriptTemplate
|
::Tilt.register 'coffee', DebuggingCoffeeScriptTemplate
|
||||||
::Tilt.prefer(DebuggingCoffeeScriptTemplate)
|
::Tilt.prefer(DebuggingCoffeeScriptTemplate)
|
||||||
|
|
||||||
app.before_configuration do
|
DebuggingCoffeeScriptTemplate.middleman_app = app
|
||||||
DebuggingCoffeeScriptTemplate.middleman_app = self
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# A Template for Tilt which outputs debug messages
|
# A Template for Tilt which outputs debug messages
|
||||||
|
|
|
@ -12,7 +12,7 @@ module Middleman
|
||||||
def initialize(app, config={}, &block)
|
def initialize(app, config={}, &block)
|
||||||
super
|
super
|
||||||
|
|
||||||
# Array of callbacks which can ass ignored
|
# Array of callbacks which can assign ignored
|
||||||
@ignored_callbacks = Set.new
|
@ignored_callbacks = Set.new
|
||||||
|
|
||||||
@app.sitemap.define_singleton_method(:ignored?, &method(:ignored?))
|
@app.sitemap.define_singleton_method(:ignored?, &method(:ignored?))
|
||||||
|
|
|
@ -345,4 +345,4 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
# And, require the actual default implementation for a watcher.
|
# And, require the actual default implementation for a watcher.
|
||||||
require 'middleman-core/sources/source_watcher.rb'
|
require 'middleman-core/sources/source_watcher'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Watcher Library
|
# Watcher Library
|
||||||
require 'listen'
|
require 'listen'
|
||||||
require 'middleman-core/contracts'
|
require 'middleman-core/contracts'
|
||||||
|
require 'middleman-core/contracts'
|
||||||
require 'backports/2.0.0/enumerable/lazy'
|
require 'backports/2.0.0/enumerable/lazy'
|
||||||
|
|
||||||
module Middleman
|
module Middleman
|
||||||
|
@ -55,7 +56,8 @@ module Middleman
|
||||||
|
|
||||||
@listener = nil
|
@listener = nil
|
||||||
|
|
||||||
@on_change_callbacks = Set.new
|
@callbacks = ::Middleman::CallbackManager.new
|
||||||
|
@callbacks.install_methods!(self, [:on_change])
|
||||||
|
|
||||||
@waiting_for_existence = !@directory.exist?
|
@waiting_for_existence = !@directory.exist?
|
||||||
end
|
end
|
||||||
|
@ -174,16 +176,6 @@ module Middleman
|
||||||
listen!
|
listen!
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add callback to be run on file change
|
|
||||||
#
|
|
||||||
# @param [Proc] matcher A Regexp to match the change path against
|
|
||||||
# @return [Set<Proc>]
|
|
||||||
Contract Proc => SetOf[Proc]
|
|
||||||
def on_change(&block)
|
|
||||||
@on_change_callbacks << block
|
|
||||||
@on_change_callbacks
|
|
||||||
end
|
|
||||||
|
|
||||||
# Work around this bug: http://bugs.ruby-lang.org/issues/4521
|
# Work around this bug: http://bugs.ruby-lang.org/issues/4521
|
||||||
# where Ruby will call to_s/inspect while printing exception
|
# where Ruby will call to_s/inspect while printing exception
|
||||||
# messages, which can take a long time (minutes at full CPU)
|
# messages, which can take a long time (minutes at full CPU)
|
||||||
|
@ -237,11 +229,11 @@ module Middleman
|
||||||
logger.debug "== Deletion (#{f[:types].inspect}): #{f[:relative_path]}"
|
logger.debug "== Deletion (#{f[:types].inspect}): #{f[:relative_path]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
run_callbacks(
|
execute_callbacks(:on_change, [
|
||||||
@on_change_callbacks,
|
|
||||||
valid_updates,
|
valid_updates,
|
||||||
valid_removes
|
valid_removes,
|
||||||
) unless valid_updates.empty? && valid_removes.empty?
|
self
|
||||||
|
]) unless valid_updates.empty? && valid_removes.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_file_to_cache(f)
|
def add_file_to_cache(f)
|
||||||
|
@ -289,17 +281,5 @@ module Middleman
|
||||||
|
|
||||||
::Middleman::SourceFile.new(Pathname(relative_path), path, @directory, types)
|
::Middleman::SourceFile.new(Pathname(relative_path), path, @directory, types)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Notify callbacks for a file given an array of callbacks
|
|
||||||
#
|
|
||||||
# @param [Pathname] path The file that was changed
|
|
||||||
# @param [Symbol] callbacks_name The name of the callbacks method
|
|
||||||
# @return [void]
|
|
||||||
Contract Set, ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any
|
|
||||||
def run_callbacks(callbacks, updated_files, removed_files)
|
|
||||||
callbacks.each do |callback|
|
|
||||||
callback.call(updated_files, removed_files, self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,6 @@ Gem::Specification.new do |s|
|
||||||
s.add_dependency('rack', ['>= 1.4.5', '< 2.0'])
|
s.add_dependency('rack', ['>= 1.4.5', '< 2.0'])
|
||||||
s.add_dependency('tilt', ['~> 1.4.1'])
|
s.add_dependency('tilt', ['~> 1.4.1'])
|
||||||
s.add_dependency('erubis')
|
s.add_dependency('erubis')
|
||||||
s.add_dependency('hooks', ['~> 0.3'])
|
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
s.add_dependency('activesupport', ['~> 4.2.0'])
|
s.add_dependency('activesupport', ['~> 4.2.0'])
|
||||||
|
|
132
middleman-core/spec/middleman-core/callbacks_spec.rb
Normal file
132
middleman-core/spec/middleman-core/callbacks_spec.rb
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
# require 'spec_helper'
|
||||||
|
require 'middleman-core/callback_manager'
|
||||||
|
|
||||||
|
describe ::Middleman::CallbackManager do
|
||||||
|
it "adds a simple key" do
|
||||||
|
counters = {
|
||||||
|
test1: 0,
|
||||||
|
test2: 0,
|
||||||
|
test3: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
m = ::Middleman::CallbackManager.new
|
||||||
|
m.add(:test3) { counters[:test3] += 1 }
|
||||||
|
m.add(:test1) { counters[:test1] += 1 }
|
||||||
|
m.add(:test2) { counters[:test2] += 1 }
|
||||||
|
m.add(:test1) { counters[:test1] += 1 }
|
||||||
|
m.add(:test2) { counters[:test2] += 1 }
|
||||||
|
m.add(:test1) { counters[:test1] += 1 }
|
||||||
|
m.add(:test3) { counters[:test3] += 1 }
|
||||||
|
|
||||||
|
m.execute(:test1)
|
||||||
|
m.execute(:test2)
|
||||||
|
|
||||||
|
expect(counters[:test1]).to eq 3
|
||||||
|
expect(counters[:test2]).to eq 2
|
||||||
|
expect(counters[:test3]).to eq 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it "callbacks run in order" do
|
||||||
|
result = []
|
||||||
|
|
||||||
|
m = ::Middleman::CallbackManager.new
|
||||||
|
m.add(:test) { result.push(1) }
|
||||||
|
m.add(:test) { result.push(2) }
|
||||||
|
m.add(:test) { result.push(3) }
|
||||||
|
|
||||||
|
m.execute(:test)
|
||||||
|
|
||||||
|
expect(result.join('')).to eq '123'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adds a nested key" do
|
||||||
|
counters = {
|
||||||
|
test1: 0,
|
||||||
|
test1a: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
m = ::Middleman::CallbackManager.new
|
||||||
|
m.add([:test1, :a]) { |n| counters[:test1a] += n }
|
||||||
|
m.add(:test1) { counters[:test1] += 1 }
|
||||||
|
|
||||||
|
m.execute([:test1, :a], [2])
|
||||||
|
m.execute([:test1, :b], [5])
|
||||||
|
|
||||||
|
expect(counters[:test1]).to eq 0
|
||||||
|
expect(counters[:test1a]).to eq 2
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works in isolation" do
|
||||||
|
m1 = ::Middleman::CallbackManager.new
|
||||||
|
m2 = ::Middleman::CallbackManager.new
|
||||||
|
|
||||||
|
counters = {
|
||||||
|
test1: 0,
|
||||||
|
test2: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
m1.add(:test1) { |n| counters[:test1] += n }
|
||||||
|
m2.add(:test1) { |n| counters[:test2] += n }
|
||||||
|
|
||||||
|
m1.execute(:test1, [2])
|
||||||
|
m2.execute(:test1, [5])
|
||||||
|
m1.execute(:test2, [20])
|
||||||
|
m2.execute(:test2, [50])
|
||||||
|
|
||||||
|
expect(counters[:test1]).to eq 2
|
||||||
|
expect(counters[:test2]).to eq 5
|
||||||
|
end
|
||||||
|
|
||||||
|
it "installs to arbitrary instances" do
|
||||||
|
instance = Class.new(Object).new
|
||||||
|
|
||||||
|
m = ::Middleman::CallbackManager.new
|
||||||
|
m.install_methods!(instance, [:ready])
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
instance.ready { |n| counter += n }
|
||||||
|
instance.execute_callbacks(:ready, [2])
|
||||||
|
instance.execute_callbacks(:ready2, [10])
|
||||||
|
instance.execute_callbacks([:ready], [20])
|
||||||
|
instance.execute_callbacks([:ready, :two], [20])
|
||||||
|
expect(counter).to eq 2
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes in default scope" do
|
||||||
|
instance = Class.new(Object).new
|
||||||
|
m = ::Middleman::CallbackManager.new
|
||||||
|
m.install_methods!(instance, [:ready])
|
||||||
|
|
||||||
|
internal_self = nil
|
||||||
|
instance.ready do
|
||||||
|
internal_self = self
|
||||||
|
end
|
||||||
|
|
||||||
|
instance.execute_callbacks(:ready)
|
||||||
|
|
||||||
|
expect(internal_self) === instance
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes in custom scope" do
|
||||||
|
instance = Class.new(Object).new
|
||||||
|
m = ::Middleman::CallbackManager.new
|
||||||
|
m.install_methods!(instance, [:ready])
|
||||||
|
|
||||||
|
external_class = Struct.new(:counter, :scope) do
|
||||||
|
def when_ready(n)
|
||||||
|
self[:scope] = self
|
||||||
|
self[:counter] += n
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
external_instance = external_class.new(0, nil)
|
||||||
|
|
||||||
|
instance.ready(&external_instance.method(:when_ready))
|
||||||
|
|
||||||
|
instance.execute_callbacks(:ready, [5])
|
||||||
|
|
||||||
|
expect(external_instance[:scope]).to eq external_instance
|
||||||
|
expect(external_instance[:counter]).to eq 5
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Add table
Reference in a new issue