Move configuration into a separate object, that can be reused for extension configuration and makes settings, their defaults, and descriptions inspectable.
This commit is contained in:
parent
42f9e331da
commit
781fa1c65f
|
@ -12,10 +12,14 @@ require "middleman-core/vendor/hooks-0.2.0/lib/hooks"
|
||||||
require "middleman-core/sitemap"
|
require "middleman-core/sitemap"
|
||||||
|
|
||||||
require "middleman-core/core_extensions"
|
require "middleman-core/core_extensions"
|
||||||
|
require "middleman-core/configuration"
|
||||||
|
|
||||||
# Core Middleman Class
|
# Core Middleman Class
|
||||||
module Middleman
|
module Middleman
|
||||||
class Application
|
class Application
|
||||||
|
# Global configuration
|
||||||
|
include Configuration::Global
|
||||||
|
|
||||||
# Uses callbacks
|
# Uses callbacks
|
||||||
include Hooks
|
include Hooks
|
||||||
|
|
||||||
|
@ -34,50 +38,19 @@ module Middleman
|
||||||
class_eval(&block) if block_given?
|
class_eval(&block) if block_given?
|
||||||
include(*extensions) if extensions.any?
|
include(*extensions) if extensions.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Access class-wide defaults
|
|
||||||
#
|
|
||||||
# @private
|
|
||||||
# @return [Hash] Hash of default values
|
|
||||||
def defaults
|
|
||||||
@defaults ||= {}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set class-wide defaults
|
|
||||||
#
|
|
||||||
# @param [Symbol] key Unique key name
|
|
||||||
# @param value Default value
|
|
||||||
# @return [void]
|
|
||||||
def set(key, value=nil, &block)
|
|
||||||
@defaults ||= {}
|
|
||||||
@defaults[key] = value
|
|
||||||
|
|
||||||
@inst.set(key, value, &block) if @inst
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
delegate :helpers, :to => :"self.class"
|
delegate :helpers, :to => :"self.class"
|
||||||
|
|
||||||
# Set attributes (global variables)
|
|
||||||
#
|
|
||||||
# @param [Symbol] key Name of the attribue
|
|
||||||
# @param value Attribute value
|
|
||||||
# @return [void]
|
|
||||||
def set(key, value=nil, &block)
|
|
||||||
setter = "#{key}=".to_sym
|
|
||||||
self.class.send(:attr_accessor, key) if !respond_to?(setter)
|
|
||||||
value = block if block_given?
|
|
||||||
send(setter, value)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Root project directory (overwritten in middleman build/server)
|
# Root project directory (overwritten in middleman build/server)
|
||||||
# @return [String]
|
# @return [String]
|
||||||
set :root, ENV["MM_ROOT"] || Dir.pwd
|
set :root, ENV["MM_ROOT"] || Dir.pwd
|
||||||
|
|
||||||
# Pathname-addressed root
|
# Pathname-addressed root
|
||||||
def root_path
|
def self.root_path
|
||||||
@_root_path ||= Pathname.new(root)
|
Pathname(root)
|
||||||
end
|
end
|
||||||
|
delegate :root_path, :to => :"self.class"
|
||||||
|
|
||||||
# Name of the source directory
|
# Name of the source directory
|
||||||
# @return [String]
|
# @return [String]
|
||||||
|
@ -178,7 +151,7 @@ module Middleman
|
||||||
cache.clear
|
cache.clear
|
||||||
|
|
||||||
# Setup the default values from calls to set before initialization
|
# Setup the default values from calls to set before initialization
|
||||||
self.class.superclass.defaults.each { |k,v| set(k,v) }
|
self.class.superclass.config.to_h.each { |k,v| self.class.set(k,v) }
|
||||||
|
|
||||||
# Evaluate a passed block if given
|
# Evaluate a passed block if given
|
||||||
instance_exec(&block) if block_given?
|
instance_exec(&block) if block_given?
|
||||||
|
@ -205,13 +178,6 @@ module Middleman
|
||||||
# @return [Boolean] If we're in build mode
|
# @return [Boolean] If we're in build mode
|
||||||
def build?; environment == :build; end
|
def build?; environment == :build; end
|
||||||
|
|
||||||
# Backwards compatibilty with old Sinatra template interface
|
|
||||||
#
|
|
||||||
# @return [Middleman::Application]
|
|
||||||
def settings
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
# The full path to the source directory
|
# The full path to the source directory
|
||||||
#
|
#
|
||||||
# @return [String]
|
# @return [String]
|
||||||
|
|
218
middleman-core/lib/middleman-core/configuration.rb
Normal file
218
middleman-core/lib/middleman-core/configuration.rb
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
module Middleman
|
||||||
|
module Configuration
|
||||||
|
# Access to a global configuration manager for the whole Middleman project,
|
||||||
|
# plus backwards compatibility mechanisms for older Middleman projects.
|
||||||
|
module Global
|
||||||
|
def self.included(app)
|
||||||
|
app.send :extend, ClassMethods
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# Global configuration for the whole Middleman project.
|
||||||
|
# @return [ConfigurationManager]
|
||||||
|
def config
|
||||||
|
@_config ||= ConfigurationManager.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set attributes (global variables)
|
||||||
|
#
|
||||||
|
# @deprecated Prefer accessing settings through "config".
|
||||||
|
#
|
||||||
|
# @param [Symbol] key Name of the attribue
|
||||||
|
# @param value Attribute value
|
||||||
|
# @return [void]
|
||||||
|
def set(key, default=nil, &block)
|
||||||
|
config.define_setting(key, default)
|
||||||
|
@inst.set(key, default, &block) if @inst
|
||||||
|
end
|
||||||
|
|
||||||
|
# Access global settings as methods, to preserve compatibility with
|
||||||
|
# old Middleman.
|
||||||
|
#
|
||||||
|
# @deprecated Prefer accessing settings through "config".
|
||||||
|
def method_missing(method)
|
||||||
|
if config.defines_setting? method
|
||||||
|
config[method]
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Needed so that method_missing makes sense
|
||||||
|
def respond_to?(method, include_private = false)
|
||||||
|
super || config.defines_setting?(method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def config
|
||||||
|
self.class.config
|
||||||
|
end
|
||||||
|
|
||||||
|
# Backwards compatibilty with old Sinatra template interface
|
||||||
|
#
|
||||||
|
# @deprecated Prefer accessing settings through "config".
|
||||||
|
#
|
||||||
|
# @return [ConfigurationManager]
|
||||||
|
alias :settings :config
|
||||||
|
|
||||||
|
# Set attributes (global variables)
|
||||||
|
#
|
||||||
|
# @deprecated Prefer accessing settings through "config".
|
||||||
|
#
|
||||||
|
# @param [Symbol] key Name of the attribue
|
||||||
|
# @param value Attribute value
|
||||||
|
# @return [void]
|
||||||
|
def set(key, value=nil, &block)
|
||||||
|
value = block if block_given?
|
||||||
|
config[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
# Access global settings as methods, to preserve compatibility with
|
||||||
|
# old Middleman.
|
||||||
|
#
|
||||||
|
# @deprecated Prefer accessing settings through "config".
|
||||||
|
def method_missing(method)
|
||||||
|
if config.defines_setting? method
|
||||||
|
config[method]
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Needed so that method_missing makes sense
|
||||||
|
def respond_to?(method, include_private = false)
|
||||||
|
super || config.defines_setting?(method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# A class that manages a collection of documented settings.
|
||||||
|
# Can be used by extensions as well as the main Middleman
|
||||||
|
# application. Extensions should probably finalize their instance
|
||||||
|
# after defining all the settings they want to expose.
|
||||||
|
class ConfigurationManager
|
||||||
|
def initialize
|
||||||
|
# A hash from setting key to ConfigSetting instance.
|
||||||
|
@settings = {}
|
||||||
|
@finalized = false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get all settings, sorted by key, as ConfigSetting objects.
|
||||||
|
# @return [Array<ConfigSetting>]
|
||||||
|
def all_settings
|
||||||
|
@settings.values.sort_by(&:key)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get a full ConfigSetting object for the setting with the give key.
|
||||||
|
# @return [ConfigSetting]
|
||||||
|
def setting(key)
|
||||||
|
@settings[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the value of a setting by key. Returns nil if there is no such setting.
|
||||||
|
# @return [Object]
|
||||||
|
def [](key)
|
||||||
|
setting = @settings[key]
|
||||||
|
setting ? setting.value : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set the value of a setting by key. Creates the setting if it doesn't exist.
|
||||||
|
# @param [Symbol] key
|
||||||
|
# @param [Object] val
|
||||||
|
def []=(key, val)
|
||||||
|
setting = @settings[key] || define_setting(key)
|
||||||
|
setting.value = val
|
||||||
|
end
|
||||||
|
|
||||||
|
# Allow configuration settings to be read and written via methods
|
||||||
|
def method_missing(method, *args)
|
||||||
|
if defines_setting?(method) && args.size == 0
|
||||||
|
self[method]
|
||||||
|
elsif method =~ /^(\w+)=$/ && args.size == 1
|
||||||
|
self[$1] = args[0]
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Needed so that method_missing makes sense
|
||||||
|
def respond_to?(method, include_private = false)
|
||||||
|
super || defines_setting?(method) || (method =~ /^(\w+)=$/ && defines_setting?($1))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Does this configuration manager know about the setting identified by key?
|
||||||
|
# @param [Symbol] key
|
||||||
|
# @return [Boolean]
|
||||||
|
def defines_setting?(key)
|
||||||
|
@settings.has_key?(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Define a new setting, with optional default and user-friendly description.
|
||||||
|
# Once the configuration manager is finalized, no new settings may be defined.
|
||||||
|
#
|
||||||
|
# @param [Symbol] key
|
||||||
|
# @param [Object] default
|
||||||
|
# @param [String] description
|
||||||
|
# @return [ConfigSetting]
|
||||||
|
def define_setting(key, default=nil, description=nil)
|
||||||
|
raise "Setting #{key} doesn't exist" if @finalized
|
||||||
|
raise "Setting #{key} already defined" if @settings.has_key?(key)
|
||||||
|
raise "Setting key must be a Symbol" unless key.is_a? Symbol
|
||||||
|
|
||||||
|
@settings[key] = ConfigSetting.new(key, default, description)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Switch the configuration manager is finalized, it switches to read-only
|
||||||
|
# mode and no new settings may be defined.
|
||||||
|
def finalize!
|
||||||
|
@finalized = true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Deep duplicate of the configuration manager
|
||||||
|
def dup
|
||||||
|
copy = ConfigurationManager.new
|
||||||
|
@settings.each do |key, setting|
|
||||||
|
copy_setting = copy.define_setting setting.key, setting.default, setting.description
|
||||||
|
copy_setting.value = setting.value if setting.value_set?
|
||||||
|
end
|
||||||
|
copy
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_h
|
||||||
|
hash = {}
|
||||||
|
@settings.each do |key, setting|
|
||||||
|
hash[key] = setting.value
|
||||||
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
to_h.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ConfigSetting
|
||||||
|
attr_accessor :key, :default, :description
|
||||||
|
attr_writer :value
|
||||||
|
|
||||||
|
def initialize(key, default, description)
|
||||||
|
@value_set = false
|
||||||
|
self.key = key
|
||||||
|
self.default = default
|
||||||
|
self.description = description
|
||||||
|
end
|
||||||
|
|
||||||
|
def value=(value)
|
||||||
|
@value = value
|
||||||
|
@value_set = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def value
|
||||||
|
value_set? ? @value : default
|
||||||
|
end
|
||||||
|
|
||||||
|
def value_set?
|
||||||
|
@value_set
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -37,9 +37,6 @@ module Middleman
|
||||||
class << self
|
class << self
|
||||||
# @private
|
# @private
|
||||||
def registered(app)
|
def registered(app)
|
||||||
# Using for version parsing
|
|
||||||
require "rubygems"
|
|
||||||
|
|
||||||
app.define_hook :after_configuration
|
app.define_hook :after_configuration
|
||||||
app.define_hook :before_configuration
|
app.define_hook :before_configuration
|
||||||
app.define_hook :build_config
|
app.define_hook :build_config
|
||||||
|
|
Loading…
Reference in a new issue