Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Provide a core extension class, like Rails::Engine #460

Closed
wants to merge 4 commits into from

2 participants

@tdreyno
Owner

Thinking of sneaking this in the back door... starting to get real annoyed with every extension being jammed into Application by default.

...core/lib/middleman-core/core_extensions/extensions.rb
((6 lines not shown))
ext
else
::Middleman::Extensions.load(ext.to_sym)
end
- if ext_module.nil?
+ $stderr.puts extension_container.to_s
@bhollis Owner
bhollis added a note

Straggler debugging statement?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@bhollis
Owner

I like the idea. The only concern would be that you don't get to lazy-require quite as much, but it seems worth it to drop a ton of boilerplate.

@tdreyno
Owner

I think we're losing a ton of laziness in Bundle.require, maybe we add a lazy require here, like Tilt.

@tdreyno
Owner

I like this idea a lot. Will wait until 3.1, but I've been thinking about it all weekend and this could be great.

@tdreyno
Owner

Moving to 3.1

@tdreyno
Owner

Still trying to figure out the best way to do this, it's liable to become spaghetti. @bhollis, I'd love some input.

Blocks, hooks or methods:

class MyPlugin < Middleman::Extension
  after_configuration do
    # my thing
  end
end
class MyPlugin < Middleman::Extension
  after :configuration, :do_it

  def do_it
    # my thing
  end
end
class MyPlugin < Middleman::Extension
  def after_configuration
    # my thing
  end
end

I think the hooks one provides the most flexibility and lets other pieces of code expose events to be hooked. Like so:

# File Watcher
def file_did_change(path)
  trigger :file_did_change, path
end

# Extension
class MyWatcher < Middleman::Extension
  after :file_did_change, :update_cache

  def update_cache(path)
    # do something
  end
end

Is this kind of binding and eventing sane in Ruby? I feel like my JS brain is creating things that aren't normal in Ruby-land.

@bhollis
Owner

I think I like the hooks thing (it's sorta like ActiveModel::Callbacks). I'm not sure after is the right name for the method though - will there be a corresponding before?

In general it'd actually be nicer to have methods on Middleman::Extension that you override (allows for inheritance, makes it easier to figure out what's available to override) but maybe that gets complicated and makes things harder to extend? I guess you could always mix in more methods to Middleman::Extension to make new callbacks...

@tdreyno
Owner

I'm using the ActiveSupport Callback stuff already, so sweet.

@tdreyno tdreyno referenced this pull request in middleman/middleman-blog
Closed

Allow Multiple Blogs #37

@tdreyno
Owner

This happened, simply, elsewhere

@tdreyno tdreyno closed this
@tdreyno tdreyno deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 446 additions and 515 deletions.
  1. +9 −0 middleman-core/lib/middleman-core/core_extensions/builder.rb
  2. +32 −9 middleman-core/lib/middleman-core/core_extensions/extensions.rb
  3. +4 −0 middleman-core/lib/middleman-core/core_extensions/request.rb
  4. +64 −0 middleman-core/lib/middleman-core/extensions.rb
  5. +16 −0 middleman-core/lib/middleman-core/sitemap/store.rb
  6. +1 −1  middleman-core/lib/middleman-core/step_definitions/builder_steps.rb
  7. +2 −29 middleman-more/features/minify_css.feature
  8. +3 −58 middleman-more/features/minify_javascript.feature
  9. +13 −35 middleman-more/lib/middleman-more.rb
  10. +49 −10 middleman-more/lib/middleman-more/core_extensions/assets.rb
  11. +9 −0 middleman-more/lib/middleman-more/core_extensions/compass.rb
  12. +34 −48 middleman-more/lib/middleman-more/extensions/asset_hash.rb
  13. +20 −36 middleman-more/lib/middleman-more/extensions/asset_host.rb
  14. +26 −33 middleman-more/lib/middleman-more/extensions/automatic_image_sizes.rb
  15. +38 −55 middleman-more/lib/middleman-more/extensions/cache_buster.rb
  16. +25 −45 middleman-more/lib/middleman-more/extensions/directory_indexes.rb
  17. +49 −54 middleman-more/lib/middleman-more/extensions/gzip.rb
  18. +3 −17 middleman-more/lib/middleman-more/extensions/lorem.rb
  19. +18 −26 middleman-more/lib/middleman-more/extensions/minify_css.rb
  20. +16 −25 middleman-more/lib/middleman-more/extensions/minify_javascript.rb
  21. +15 −34 middleman-more/lib/middleman-more/extensions/relative_assets.rb
View
9 middleman-core/lib/middleman-core/core_extensions/builder.rb
@@ -9,6 +9,15 @@ class << self
# @private
def registered(app)
app.define_hook :after_build
+
+ ::Middleman::Extension.add_hooks do
+ set_callback :activate, :after, :autoregister_after_build
+
+ def autoregister_after_build
+ return unless respond_to?(:after_build)
+ app.after_build(&method(:after_build))
+ end
+ end
end
alias :included :registered
end
View
41 middleman-core/lib/middleman-core/core_extensions/extensions.rb
@@ -37,9 +37,6 @@ module Extensions
class << self
# @private
def registered(app)
- # Using for version parsing
- require "rubygems"
-
app.define_hook :after_configuration
app.define_hook :before_configuration
app.define_hook :build_config
@@ -54,6 +51,29 @@ def registered(app)
app.extend ClassMethods
app.send :include, InstanceMethods
app.delegate :configure, :to => :"self.class"
+
+ ::Middleman::Extension.add_hooks do
+ set_callback :activate, :after, :autoregister_config_callbacks
+
+ def autoregister_config_callbacks
+ if respond_to?(:on_build) && app.build?
+ app.build_config(&method(:on_build))
+ end
+
+ if respond_to?(:in_dev) && app.development?
+ app.build_config(&method(:in_dev))
+ end
+
+ if respond_to?(:before_configuration)
+ app.before_configuration(&method(:before_configuration))
+ end
+
+ if respond_to?(:after_configuration)
+ app.after_configuration(&method(:after_configuration))
+ end
+ end
+ end
+
end
alias :included :registered
end
@@ -106,17 +126,20 @@ module InstanceMethods
# @param [Symbol, Module] ext Which extension to activate
# @return [void]
def activate(ext, options={}, &block)
- ext_module = if ext.is_a?(Module)
+ extension_container = if ext.is_a?(Module)
ext
else
::Middleman::Extensions.load(ext.to_sym)
end
-
- if ext_module.nil?
- logger.error "== Unknown Extension: #{ext}"
- else
+
+ if extension_container.nil?
+ logger.warn "== Unknown Extension: #{ext}"
+ elsif extension_container.is_a? Class
+ logger.debug "== Activating: #{ext}"
+ extension_container.new(self, options, &block)
+ elsif extension_container.is_a? Module
logger.debug "== Activating: #{ext}"
- self.class.register(ext_module, options, &block)
+ self.class.register(extension_container, options, &block)
end
end
View
4 middleman-core/lib/middleman-core/core_extensions/request.rb
@@ -27,6 +27,10 @@ def registered(app)
# Include instance methods
app.send :include, InstanceMethods
+
+ ::Middleman::Extension.add_hooks do
+ delegate :use, :map, :to => :app
+ end
end
alias :included :registered
end
View
64 middleman-core/lib/middleman-core/extensions.rb
@@ -100,4 +100,68 @@ def spec_has_file?(spec, path)
File.exists?(full_path)
end
end
+
+ require 'active_support/descendants_tracker'
+ require 'active_support/callbacks'
+ require 'active_support/core_ext/module/delegation'
+
+ # Auto-registration class, in the style of Rails::Engine
+ class Extension
+ include ::ActiveSupport::Callbacks
+ extend ::ActiveSupport::DescendantsTracker
+
+ class_attribute :autoregister
+ class_attribute :extension_name
+
+ class << self
+ def config_options(opts={})
+ @_config_options ||= {}
+ @_config_options.merge!(opts)
+ @_config_options
+ end
+
+ def helpers(&block)
+ @_helpers ||= Set.new
+ @_helpers << block if block_given?
+ @_helpers
+ end
+
+ def add_hooks(&block)
+ class_eval(&block)
+ end
+
+ def inherited(base)
+ super
+
+ if base.autoregister.nil? || base.autoregister === true
+ extension_name = base.extension_name || generate_extension_name(base.name.split("::").last)
+ ::Middleman::Extensions.register(extension_name) { base }
+ end
+ end
+
+ protected
+ def generate_extension_name(class_or_module)
+ ActiveSupport::Inflector.underscore(class_or_module).tr("/", "_").to_sym
+ end
+ end
+
+ attr_reader :app, :options
+
+ delegate :logger, :to => :app
+
+ define_callbacks :activate
+
+ def initialize(app, options={}, &block)
+ @app = app
+ @options = self.class.config_options.dup.merge(options)
+
+ self.class.helpers.each do |h|
+ @app.class.helpers(&h)
+ end
+
+ run_callbacks :activate do
+ # Derp
+ end
+ end
+ end
end
View
16 middleman-core/lib/middleman-core/sitemap/store.rb
@@ -229,3 +229,19 @@ def reset_lookup_cache!
end
end
end
+
+::Middleman::Extension.add_hooks do
+ set_callback :activate, :after, :autoregister_resource_list_manipulator
+
+ def autoregister_resource_list_manipulator
+ return unless respond_to?(:manipulate_resource_list)
+
+ extension = self
+ app.ready do
+ sitemap.register_resource_list_manipulator(
+ extension.class.extension_name,
+ extension
+ )
+ end
+ end
+end
View
2  middleman-core/lib/middleman-core/step_definitions/builder_steps.rb
@@ -27,7 +27,7 @@
Given /^a built app at "([^\"]*)"$/ do |path|
step %Q{a fixture app "#{path}"}
- step %Q{I run `middleman build`}
+ step %Q{I run `middleman build --verbose`}
end
Given /^was successfully built$/ do
View
31 middleman-more/features/minify_css.feature
@@ -36,9 +36,7 @@ Feature: Minify CSS
end
end
- activate :minify_css
-
- set :css_compressor, ::PassThrough
+ activate :minify_css, :compressor => ::PassThrough
"""
And the Server is running at "passthrough-app"
When I go to "/stylesheets/site.css"
@@ -73,9 +71,7 @@ Feature: Minify CSS
end
end
- activate :minify_css, :inline => true
-
- set :css_compressor, ::PassThrough
+ activate :minify_css, :inline => true, :compressor => ::PassThrough
page "/inline-css.html", :layout => false
"""
@@ -89,29 +85,6 @@ Feature: Minify CSS
good: deal; }
</style>
"""
-
- Scenario: Rendering inline css with a passthrough minifier using activate-style compressor
- Given a fixture app "passthrough-app"
- And a file named "config.rb" with:
- """
- module ::HelloCompressor
- def self.compress(data)
- "Hello"
- end
- end
-
- activate :minify_css, :inline => true, :compressor => ::HelloCompressor
-
- page "/inline-css.html", :layout => false
- """
- And the Server is running at "passthrough-app"
- When I go to "/inline-css.html"
- Then I should see:
- """
- <style type='text/css'>
- Hello
- </style>
- """
Scenario: Rendering inline css with the feature enabled
Given a fixture app "minify-css-app"
View
61 middleman-more/features/minify_javascript.feature
@@ -40,59 +40,8 @@ Feature: Minify Javascript
I'm a jQuery {{template}}.
</script>
"""
-
- Scenario: Rendering inline js with a passthrough minifier
- Given a fixture app "passthrough-app"
- And a file named "config.rb" with:
- """
- module ::PassThrough
- def self.compress(data)
- data
- end
- end
-
- activate :minify_javascript, :inline => true
- set :js_compressor, ::PassThrough
-
- page "/inline-js.html", :layout => false
- """
- And the Server is running at "passthrough-app"
- When I go to "/inline-js.html"
- Then I should see:
- """
- <script type='text/javascript'>
- //<![CDATA[
- ;(function() {
- this;
- should();
- all.be();
- on = { one: line };
- })();
- //]]>
- </script>
- <script>
- ;(function() {
- this;
- should();
- too();
- })();
- </script>
- <script type='text/javascript'>
- //<!--
- ;(function() {
- one;
- line();
- here();
- })();
- //-->
- </script>
- <script type='text/html'>
- I'm a jQuery {{template}}.
- </script>
- """
-
- Scenario: Rendering inline css with a passthrough minifier using activate-style compressor
+ Scenario: Rendering inline css with a passthrough minifier
Given a fixture app "passthrough-app"
And a file named "config.rb" with:
"""
@@ -206,9 +155,7 @@ Feature: Minify Javascript
end
end
- activate :minify_javascript, :inline => true
-
- set :js_compressor, ::PassThrough
+ activate :minify_javascript, :inline => true, :compressor => ::PassThrough
page "/inline-coffeescript.html", :layout => false
"""
@@ -226,9 +173,7 @@ Feature: Minify Javascript
end
end
- activate :minify_javascript
-
- set :js_compressor, ::PassThrough
+ activate :minify_javascript, :compressor => ::PassThrough
"""
And the Server is running at "passthrough-app"
When I go to "/javascripts/coffee_test.js"
View
48 middleman-more/lib/middleman-more.rb
@@ -51,37 +51,22 @@ def registered(app, options={})
# Setup Optional Extensions
###
- # CacheBuster adds a query string to assets in dynamic templates to
- # avoid browser caches failing to update to your new content.
- Middleman::Extensions.register(:cache_buster) do
- require "middleman-more/extensions/cache_buster"
- Middleman::Extensions::CacheBuster
- end
+ # CacheBuster adds a query string to assets in dynamic templates to avoid
+ # browser caches failing to update to your new content.
+ require "middleman-more/extensions/cache_buster"
# MinifyCss compresses CSS
- Middleman::Extensions.register(:minify_css) do
- require "middleman-more/extensions/minify_css"
- Middleman::Extensions::MinifyCss
- end
+ require "middleman-more/extensions/minify_css"
# MinifyJavascript compresses JS
- Middleman::Extensions.register(:minify_javascript) do
- require "middleman-more/extensions/minify_javascript"
- Middleman::Extensions::MinifyJavascript
- end
+ require "middleman-more/extensions/minify_javascript"
# RelativeAssets allow any asset path in dynamic templates to be either
# relative to the root of the project or use an absolute URL.
- Middleman::Extensions.register(:relative_assets) do
- require "middleman-more/extensions/relative_assets"
- Middleman::Extensions::RelativeAssets
- end
+ require "middleman-more/extensions/relative_assets"
# GZIP assets and pages during build
- Middleman::Extensions.register(:gzip) do
- require "middleman-more/extensions/gzip"
- Middleman::Extensions::Gzip
- end
+ require "middleman-more/extensions/gzip"
# AssetHash appends a hash of the file contents to the assets filename
# to avoid browser caches failing to update to your new content.
@@ -93,29 +78,22 @@ def registered(app, options={})
# AssetHost allows you to setup multiple domains to host your static
# assets. Calls to asset paths in dynamic templates will then rotate
# through each of the asset servers to better spread the load.
- Middleman::Extensions.register(:asset_host) do
- require "middleman-more/extensions/asset_host"
- Middleman::Extensions::AssetHost
- end
+ require "middleman-more/extensions/asset_host"
# Provide Apache-style index.html files for directories
- Middleman::Extensions.register(:directory_indexes) do
- require "middleman-more/extensions/directory_indexes"
- Middleman::Extensions::DirectoryIndexes
- end
+ require "middleman-more/extensions/directory_indexes"
# Lorem provides a handful of helpful prototyping methods to generate
# words, paragraphs, fake images, names and email addresses.
require "middleman-more/extensions/lorem"
- Middleman::Application.register Middleman::Extensions::Lorem
+ app.before_configuration do
+ activate :lorem
+ end
# AutomaticImageSizes inspects the images used in your dynamic templates
# and automatically adds width and height attributes to their HTML
# elements.
- Middleman::Extensions.register(:automatic_image_sizes) do
- require "middleman-more/extensions/automatic_image_sizes"
- Middleman::Extensions::AutomaticImageSizes
- end
+ require "middleman-more/extensions/automatic_image_sizes"
end
end
end
View
59 middleman-more/lib/middleman-more/core_extensions/assets.rb
@@ -18,26 +18,65 @@ def registered(app)
# Methods to be mixed-in to Middleman::Application
module InstanceMethod
+
+ def assets_paths
+ @_assets_paths ||= AssetPaths.new(self)
+ end
+
+ # Get the URL of an asset given a type/prefix
+ #
+ # @param [String] path The path (such as "photo.jpg")
+ # @param [String] prefix The type prefix (such as "images")
+ # @return [String] The fully qualified asset url
+ def asset_url(*args)
+ assets_paths.asset_url(*args)
+ end
+ end
+ class AssetPaths
+ def initialize(app)
+ @app = app
+ @handlers = Set.new
+
+ register_handler do |path, prefix, result|
+ # Don't touch assets which already have a full path
+ if path.include?("//")
+ path
+ else # rewrite paths to use their destination path
+ path = File.join(prefix, path)
+ if resource = @app.sitemap.find_resource_by_path(path)
+ resource.url
+ else
+ File.join(@app.http_prefix, path)
+ end
+ end
+ end
+ end
+
+ def register_handler(&block)
+ @handlers << block if block_given?
+ end
+
# Get the URL of an asset given a type/prefix
#
# @param [String] path The path (such as "photo.jpg")
# @param [String] prefix The type prefix (such as "images")
# @return [String] The fully qualified asset url
def asset_url(path, prefix="")
- # Don't touch assets which already have a full path
- if path.include?("//")
- path
- else # rewrite paths to use their destination path
- path = File.join(prefix, path)
- if resource = sitemap.find_resource_by_path(path)
- resource.url
- else
- File.join(http_prefix, path)
- end
+ @handlers.inject("") do |result, handler|
+ handler.call(path, prefix, result)
end
end
end
+
+ ::Middleman::Extension.add_hooks do
+ set_callback :activate, :after, :autoregister_asset_url
+
+ def autoregister_asset_url
+ return unless respond_to?(:asset_url)
+ app.assets_paths.register_handler(&method(:asset_url))
+ end
+ end
end
end
end
View
9 middleman-more/lib/middleman-more/core_extensions/compass.rb
@@ -65,6 +65,15 @@ def registered(app)
::Tilt.register 'scss', CompassScssTemplate
::Tilt.prefer(CompassScssTemplate)
end
+
+ ::Middleman::Extension.add_hooks do
+ set_callback :activate, :after, :autoregister_compass_config
+
+ def autoregister_compass_config
+ return unless respond_to?(:compass_config)
+ app.compass_config(&method(:compass_config))
+ end
+ end
end
alias :included :registered
end
View
82 middleman-more/lib/middleman-more/extensions/asset_hash.rb
@@ -1,57 +1,43 @@
module Middleman
module Extensions
- module AssetHash
- class << self
- def registered(app, options={})
- require 'digest/sha1'
- require 'rack/test'
- require 'uri'
-
- exts = options[:exts] || %w(.jpg .jpeg .png .gif .js .css)
-
- # Allow specifying regexes to ignore, plus always ignore apple touch icons
- ignore = Array(options[:ignore]) << /^apple-touch-icon/
-
- app.ready do
- sitemap.register_resource_list_manipulator(
- :asset_hash,
- AssetHashManager.new(self, exts, ignore)
- )
-
- use Middleware, :exts => exts, :middleman_app => self, :ignore => ignore
- end
- end
- alias :included :registered
+ class AssetHash < ::Middleman::Extension
+ config_options :exts => %w(.jpg .jpeg .png .gif .js .css),
+ :ignore => []
+
+ def initialize(*args)
+ require 'digest/sha1'
+ require 'rack/test'
+ require 'uri'
+
+ super
end
- # Central class for managing asset_hash extension
- class AssetHashManager
- def initialize(app, exts, ignore)
- @app = app
- @exts = exts
- @ignore = ignore
- end
-
- # Update the main sitemap resource list
- # @return [void]
- def manipulate_resource_list(resources)
- resources.each do |resource|
- next unless @exts.include? resource.ext
- next if @ignore.any? { |ignore| Middleman::Util.path_match(ignore, resource.destination_path) }
-
- if resource.template? # if it's a template, render it out
- # Render through the Rack interface so middleware and mounted apps get a shot
- rack_client = ::Rack::Test::Session.new(@app.class)
- response = rack_client.get(URI.escape(resource.destination_path), {}, { "bypass_asset_hash" => true })
- raise "#{resource.path} should be in the sitemap!" unless response.status == 200
-
- digest = Digest::SHA1.hexdigest(response.body)[0..7]
- else # if it's a static file, just hash it
- digest = Digest::SHA1.file(resource.source_file).hexdigest[0..7]
- end
+ def after_configuration
+ ignore = Array(options[:ignore]) << /^apple-touch-icon/
+ app.use Middleware, :middleman_app => app,
+ :exts => options[:exts],
+ :ignore => ignore
+ end
- resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
+ # Update the main sitemap resource list
+ # @return [void]
+ def manipulate_resource_list(resources)
+ resources.each do |resource|
+ next unless options[:exts].include? resource.ext
+ next if options[:ignore].any? { |ignore| Middleman::Util.path_match(ignore, resource.destination_path) }
+
+ if resource.template? # if it's a template, render it out
+ # Render through the Rack interface so middleware and mounted apps get a shot
+ rack_client = ::Rack::Test::Session.new(app.class)
+ response = rack_client.get(URI.escape(resource.destination_path), {}, { "bypass_asset_hash" => true })
+ raise "#{resource.path} should be in the sitemap!" unless response.status == 200
+
+ digest = Digest::SHA1.hexdigest(response.body)[0..7]
+ else # if it's a static file, just hash it
+ digest = Digest::SHA1.file(resource.source_file).hexdigest[0..7]
end
+
+ resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
end
end
View
56 middleman-more/lib/middleman-more/extensions/asset_host.rb
@@ -3,43 +3,27 @@ module Middleman
module Extensions
# Asset Host module
- module AssetHost
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app)
- # Default to no host
- app.set :asset_host, false
-
- # Include methods
- app.send :include, InstanceMethods
- end
-
- alias :included :registered
- end
-
- # Asset Host Instance Methods
- module InstanceMethods
-
- # Override default asset url helper to include asset hosts
- #
- # @param [String] path
- # @param [String] prefix
- # @return [String]
- def asset_url(path, prefix="")
- original_output = super
- return original_output unless asset_host
-
- asset_prefix = if asset_host.is_a?(Proc)
- asset_host.call(original_output)
- elsif asset_host.is_a?(String)
- asset_host
- end
-
- File.join(asset_prefix, original_output)
+ class AssetHost < ::Middleman::Extension
+ config_options :host => false
+
+ # Override default asset url helper to include asset hosts
+ #
+ # @param [String] path
+ # @param [String] prefix
+ # @return [String]
+ def asset_url(path, prefix, result)
+ host = options[:host]
+
+ # TODO: Deprecation warning for set :asset_host
+ return result unless host
+
+ asset_prefix = if host.is_a?(Proc)
+ host.call(result)
+ elsif host.is_a?(String)
+ host
end
+
+ File.join(asset_prefix, result)
end
end
end
View
59 middleman-more/lib/middleman-more/extensions/automatic_image_sizes.rb
@@ -3,26 +3,17 @@ module Middleman
module Extensions
# Automatic Image Sizes extension
- module AutomaticImageSizes
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app)
- # Include 3rd-party fastimage library
- require "middleman-more/extensions/automatic_image_sizes/fastimage"
-
- # Include methods
- app.send :include, InstanceMethods
- end
-
- alias :included :registered
+ class AutomaticImageSizes < ::Middleman::Extension
+
+ def initialize(*args)
+ # Include 3rd-party fastimage library
+ require "middleman-more/extensions/automatic_image_sizes/fastimage"
+
+ super
end
-
+
# Automatic Image Sizes Instance Methods
- module InstanceMethods
-
+ helpers do
# Override default image_tag helper to automatically calculate and include
# image dimensions.
#
@@ -30,21 +21,23 @@ module InstanceMethods
# @param [Hash] params
# @return [String]
def image_tag(path, params={})
- if !params.has_key?(:width) && !params.has_key?(:height) && !path.include?("://")
- params[:alt] ||= ""
-
- real_path = path
- real_path = File.join(images_dir, real_path) unless real_path =~ %r{^/}
- full_path = File.join(source_dir, real_path)
-
- if File.exists? full_path
- begin
- width, height = ::FastImage.size(full_path, :raise_on_failure => true)
- params[:width] = width
- params[:height] = height
- rescue
- warn "Couldn't determine dimensions for image #{path}: #{$!.message}"
- end
+ if params.has_key?(:width) || params.has_key?(:height) || path.include?("://")
+ return super
+ end
+
+ params[:alt] ||= ""
+
+ real_path = path.dup
+ real_path = File.join(images_dir, real_path) unless real_path =~ %r{^/}
+ full_path = File.join(source_dir, real_path)
+
+ if File.exists? full_path
+ begin
+ width, height = ::FastImage.size(full_path, :raise_on_failure => true)
+ params[:width] = width
+ params[:height] = height
+ rescue
+ warn "Couldn't determine dimensions for image #{path}: #{$!.message}"
end
end
View
93 middleman-more/lib/middleman-more/extensions/cache_buster.rb
@@ -3,67 +3,50 @@ module Middleman
module Extensions
# The Cache Buster extension
- module CacheBuster
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app)
- # Add instance methods to context
- app.send :include, InstanceMethods
-
- # After compass is setup, make it use the registered cache buster
- app.compass_config do |config|
- config.asset_cache_buster do |path, real_path|
- real_path = real_path.path if real_path.is_a? File
- real_path = real_path.gsub(File.join(root, build_dir), source)
- if File.readable?(real_path)
- File.mtime(real_path).strftime("%s")
- else
- logger.warn "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
- end
- end
+ class CacheBuster < ::Middleman::Extension
+
+ # After compass is setup, make it use the registered cache buster
+ def compass_config(config)
+ config.asset_cache_buster do |path, real_path|
+ real_path = real_path.path if real_path.is_a? File
+ real_path = real_path.gsub(File.join(app.root, app.build_dir), app.source)
+ if File.readable?(real_path)
+ File.mtime(real_path).strftime("%s")
+ else
+ logger.warn "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
end
end
- alias :included :registered
end
+
+ # asset_url override if we're using cache busting
+ # @param [String] path
+ # @param [String] prefix
+ def asset_url(path, prefix, result)
+ if result.include?("://") || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(result))
+ result
+ else
+ if app.respond_to?(:http_images_path) && prefix == app.http_images_path
+ prefix = app.images_dir
+ end
- # Cache buster instance methods
- module InstanceMethods
-
- # asset_url override if we're using cache busting
- # @param [String] path
- # @param [String] prefix
- def asset_url(path, prefix="")
- http_path = super
-
- if http_path.include?("://") || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(http_path))
- http_path
- else
- if respond_to?(:http_images_path) && prefix == http_images_path
- prefix = images_dir
- end
-
- real_path_static = File.join(prefix, path)
-
- if build?
- real_path_dynamic = File.join(build_dir, prefix, path)
- real_path_dynamic = File.expand_path(real_path_dynamic, root)
- http_path << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
- elsif resource = sitemap.find_resource_by_path(real_path_static)
- if !resource.template?
- http_path << "?" + File.mtime(resource.source_file).strftime("%s")
- else
- # It's a template, possible with partials. We can't really
- # know when it's updated, so generate fresh cache buster every
- # time during developement
- http_path << "?" + Time.now.strftime("%s")
- end
+ real_path_static = File.join(prefix, path)
+
+ if app.build?
+ real_path_dynamic = File.join(app.build_dir, prefix, path)
+ real_path_dynamic = File.expand_path(real_path_dynamic, app.root)
+ result << "?" + File.mtime(real_path_dynamic).strftime("%s") if File.readable?(real_path_dynamic)
+ elsif resource = app.sitemap.find_resource_by_path(real_path_static)
+ if !resource.template?
+ result << "?" + File.mtime(resource.source_file).strftime("%s")
+ else
+ # It's a template, possible with partials. We can't really
+ # know when it's updated, so generate fresh cache buster every
+ # time during developement
+ result << "?" + Time.now.strftime("%s")
end
-
- http_path
end
+
+ result
end
end
end
View
70 middleman-more/lib/middleman-more/extensions/directory_indexes.rb
@@ -3,53 +3,33 @@ module Middleman
module Extensions
# Directory Indexes extension
- module DirectoryIndexes
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app)
- app.after_configuration do
- sitemap.register_resource_list_manipulator(
- :directory_indexes,
- DirectoryIndexManager.new(self)
- )
+ class DirectoryIndexes < ::Middleman::Extension
+
+ # Update the main sitemap resource list
+ # @return [void]
+ def manipulate_resource_list(resources)
+ index_file = app.index_file
+ ext = File.extname(index_file)
+ new_index_path = "/#{index_file}"
+
+ resources.each do |resource|
+ # Check if it would be pointless to reroute
+ next if resource.path == index_file ||
+ resource.path.end_with?(new_index_path) ||
+ File.extname(index_file) != resource.ext
+
+ # Check if frontmatter turns directory_index off
+ d = resource.data
+ next if d && d["directory_index"] == false
+
+ # Check if file metadata (options set by "page" in config.rb) turns directory_index off
+ if resource.metadata[:options] && resource.metadata[:options][:directory_index] == false
+ next
end
- end
-
- alias :included :registered
- end
-
- # Central class for managing the directory indexes extension
- class DirectoryIndexManager
- def initialize(app)
- @app = app
- end
-
- # Update the main sitemap resource list
- # @return [void]
- def manipulate_resource_list(resources)
- index_file = @app.index_file
- new_index_path = "/#{index_file}"
-
- resources.each do |resource|
- # Check if it would be pointless to reroute
- next if resource.destination_path == index_file ||
- resource.destination_path.end_with?(new_index_path) ||
- File.extname(index_file) != resource.ext
- # Check if frontmatter turns directory_index off
- d = resource.data
- next if d && d["directory_index"] == false
-
- # Check if file metadata (options set by "page" in config.rb) turns directory_index off
- if resource.metadata[:options] && resource.metadata[:options][:directory_index] == false
- next
- end
-
- resource.destination_path = resource.destination_path.chomp(File.extname(index_file)) + new_index_path
- end
+
+ directory_path = resource.destination_path.chomp(ext)
+ resource.destination_path = directory_path + new_index_path
end
end
end
View
103 middleman-more/lib/middleman-more/extensions/gzip.rb
@@ -2,70 +2,65 @@
require 'stringio'
require 'find'
-module Middleman::Extensions
+module Middleman
+ module Extensions
+
+ # This extension Gzips assets and pages when building.
+ # Gzipped assets and pages can be served directly by Apache or
+ # Nginx with the proper configuration, and pre-zipping means that we
+ # can use a more agressive compression level at no CPU cost per request.
+ #
+ # Use Nginx's gzip_static directive, or AddEncoding and mod_rewrite in Apache
+ # to serve your Gzipped files whenever the normal (non-.gz) filename is requested.
+ #
+ # Pass the :exts options to customize which file extensions get zipped (defaults
+ # to .html, .htm, .js and .css.
+ #
+ class Gzip < ::Middleman::Extension
+ config_options :exts => %w(.js .css .html .htm)
- # This extension Gzips assets and pages when building.
- # Gzipped assets and pages can be served directly by Apache or
- # Nginx with the proper configuration, and pre-zipping means that we
- # can use a more agressive compression level at no CPU cost per request.
- #
- # Use Nginx's gzip_static directive, or AddEncoding and mod_rewrite in Apache
- # to serve your Gzipped files whenever the normal (non-.gz) filename is requested.
- #
- # Pass the :exts options to customize which file extensions get zipped (defaults
- # to .html, .htm, .js and .css.
- #
- module Gzip
- class << self
- def registered(app, options={})
- exts = options[:exts] || %w(.js .css .html .htm)
+ def after_build(builder)
+ paths = ::Middleman::Util.all_files_under(app.build_dir)
+ paths.each do |path|
+ next unless options[:exts].include? path.extname
+
+ output_filename, old_size, new_size = gzip_file(path.to_s)
- app.after_build do |builder|
-
- paths = ::Middleman::Util.all_files_under(self.class.inst.build_dir)
- paths.each do |path|
- next unless exts.include? path.extname
-
- output_filename, old_size, new_size = Middleman::Extensions::Gzip.gzip_file(path.to_s)
-
- if output_filename
- size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger'
- builder.say_status :gzip, "#{output_filename} (#{number_to_human_size((old_size - new_size).abs)} #{size_change_word})"
- end
+ if output_filename
+ size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger'
+ builder.say_status :gzip, "#{output_filename} (#{app.number_to_human_size((old_size - new_size).abs)} #{size_change_word})"
end
end
end
+
+ def gzip_file(path)
+ input_file = File.open(path, 'rb').read
+ output_filename = path + '.gz'
+ input_file_time = File.mtime(path)
- alias :included :registered
- end
+ # Check if the right file's already there
+ if File.exist?(output_filename) && File.mtime(output_filename) == input_file_time
+ return
+ end
- def self.gzip_file(path)
- input_file = File.open(path, 'rb').read
- output_filename = path + '.gz'
- input_file_time = File.mtime(path)
+ File.open(output_filename, 'wb') do |f|
+ gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
+ gz.mtime = input_file_time.to_i
+ gz.write input_file
+ gz.close
+ end
- # Check if the right file's already there
- if File.exist?(output_filename) && File.mtime(output_filename) == input_file_time
- return
- end
+ # Make the file times match, both for Nginx's gzip_static extension
+ # and so we can ID existing files. Also, so even if the GZ files are
+ # wiped out by build --clean and recreated, we won't rsync them over
+ # again because they'll end up with the same mtime.
+ File.utime(File.atime(output_filename), input_file_time, output_filename)
- File.open(output_filename, 'wb') do |f|
- gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
- gz.mtime = input_file_time.to_i
- gz.write input_file
- gz.close
+ old_size = File.size(path)
+ new_size = File.size(output_filename)
+
+ [output_filename, old_size, new_size]
end
-
- # Make the file times match, both for Nginx's gzip_static extension
- # and so we can ID existing files. Also, so even if the GZ files are
- # wiped out by build --clean and recreated, we won't rsync them over
- # again because they'll end up with the same mtime.
- File.utime(File.atime(output_filename), input_file_time, output_filename)
-
- old_size = File.size(path)
- new_size = File.size(output_filename)
-
- [output_filename, old_size, new_size]
end
end
end
View
20 middleman-more/lib/middleman-more/extensions/lorem.rb
@@ -3,22 +3,8 @@ module Middleman
module Extensions
# Lorem helper
- module Lorem
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app)
- # Include methods
- app.send :include, InstanceMethods
- end
-
- alias :included :registered
- end
-
- # Lorem extension instance methods
- module InstanceMethods
+ class Lorem < ::Middleman::Extension
+ helpers do
# Access to the Lorem object
# @return [Middleman::Extensions::Lorem::LoremObject]
def lorem
@@ -35,7 +21,7 @@ def placekitten(size, options={})
lorem.image(size, options)
end
end
-
+
# Adapted from Frank:
# https://github.com/blahed/frank/
# Copyright (c) 2010 Travis Dunn
View
44 middleman-more/lib/middleman-more/extensions/minify_css.rb
@@ -1,33 +1,25 @@
# Extensions namespace
module Middleman
module Extensions
-
- # Minify CSS Extension
- module MinifyCss
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app, options={})
- app.set :css_compressor, false
-
- ignore = Array(options[:ignore]) << /\.min\./
- inline = options[:inline] || false
-
- app.after_configuration do
- chosen_compressor = css_compressor || options[:compressor] || begin
- require "middleman-more/extensions/minify_css/rainpress"
- ::Rainpress
- end
-
- # Setup Rack middleware to minify CSS
- use Rack, :compressor => chosen_compressor,
- :ignore => ignore,
- :inline => inline
- end
+
+ # Minify CSS Extension
+ class MinifyCss < ::Middleman::Extension
+ config_options :compressor => false,
+ :ignore => [],
+ :inline => false
+
+ def after_configuration
+ # TODO: Deprecation warning for set :css_compressor
+ chosen_compressor = options[:compressor] || begin
+ require "middleman-more/extensions/minify_css/rainpress"
+ ::Rainpress
end
- alias :included :registered
+
+ # Setup Rack middleware to minify CSS
+ ignore = Array(options[:ignore]) << /\.min\./
+ use Rack, :compressor => chosen_compressor,
+ :ignore => ignore,
+ :inline => options[:inline]
end
# Rack middleware to look for CSS and compress it
View
41 middleman-more/lib/middleman-more/extensions/minify_javascript.rb
@@ -3,32 +3,23 @@ module Middleman
module Extensions
# Minify Javascript Extension
- module MinifyJavascript
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app, options={})
- app.set :js_compressor, false
-
- ignore = Array(options[:ignore]) << /\.min\./
- inline = options[:inline] || false
-
- # Once config is parsed
- app.after_configuration do
- chosen_compressor = js_compressor || options[:compressor] || begin
- require 'uglifier'
- ::Uglifier.new
- end
-
- # Setup Rack middlware to minify JS
- use Rack, :compressor => chosen_compressor,
- :ignore => ignore,
- :inline => inline
- end
+ class MinifyJavascript < ::Middleman::Extension
+ config_options :compressor => false,
+ :ignore => [],
+ :inline => false
+
+ def after_configuration
+ # TODO: Deprecation warning for set :js_compressor
+ chosen_compressor = options[:compressor] || begin
+ require 'uglifier'
+ ::Uglifier.new
end
- alias :included :registered
+
+ # Setup Rack middlware to minify JS
+ ignore = Array(options[:ignore]) << /\.min\./
+ use Rack, :compressor => chosen_compressor,
+ :ignore => ignore,
+ :inline => options[:inline]
end
# Rack middleware to look for JS and compress it
View
49 middleman-more/lib/middleman-more/extensions/relative_assets.rb
@@ -3,43 +3,24 @@ module Middleman
module Extensions
# Relative Assets extension
- module RelativeAssets
-
- # Setup extension
- class << self
-
- # Once registered
- def registered(app)
- # Tell compass to use relative assets
- app.compass_config do |config|
- config.relative_assets = true
- end
-
- # Include instance methods
- app.send :include, InstanceMethods
- end
-
- alias :included :registered
+ class RelativeAssets < ::Middleman::Extension
+ def compass_config(config)
+ config.relative_assets = true
end
-
- # Relative Assets instance method
- module InstanceMethods
-
- # asset_url override for relative assets
- # @param [String] path
- # @param [String] prefix
- # @return [String]
- def asset_url(path, prefix="")
- path = super(path, prefix)
-
- if path.include?("//")
- path
- else
- current_dir = Pathname('/' + current_resource.destination_path)
- Pathname(path).relative_path_from(current_dir.dirname)
- end
+
+ # asset_url override for relative assets
+ # @param [String] path
+ # @param [String] prefix
+ # @return [String]
+ def asset_url(path, prefix, result)
+ if result.include?("//")
+ result
+ else
+ current_dir = Pathname('/' + app.current_resource.destination_path).dirname
+ Pathname(result).relative_path_from(current_dir)
end
end
end
+
end
end
Something went wrong with that request. Please try again.