perf
Thomas Reynolds 2016-01-13 17:16:36 -08:00
parent c213bd19df
commit bf19bbfed7
22 changed files with 360 additions and 280 deletions

View File

@ -48,31 +48,38 @@ module Middleman::Cli
verbose = options['verbose'] ? 0 : 1
instrument = options['instrument']
@app = ::Middleman::Application.new do
config[:mode] = :build
config[:environment] = env
config[:show_exceptions] = false
::Middleman::Logger.singleton(verbose, instrument)
builder = nil
::Middleman::Logger.singleton(verbose, instrument)
::Middleman::Util.instrument "builder_setup" do
@app = ::Middleman::Application.new do
config[:mode] = :build
config[:environment] = env
config[:show_exceptions] = false
end
builder = Middleman::Builder.new(@app,
glob: options['glob'],
clean: options['clean'],
parallel: options['parallel'])
builder.thor = self
builder.on_build_event(&method(:on_event))
end
builder = Middleman::Builder.new(@app,
glob: options['glob'],
clean: options['clean'],
parallel: options['parallel'])
builder.thor = self
builder.on_build_event(&method(:on_event))
::Middleman::Util.instrument "builder_run" do
if builder.run!
clean_directories! if options['clean']
shell.say 'Project built successfully.'
else
msg = 'There were errors during this build'
unless options['verbose']
msg << ', re-run with `middleman build --verbose` to see the full exception.'
end
shell.say msg, :red
if builder.run!
clean_directories! if options['clean']
shell.say 'Project built successfully.'
else
msg = 'There were errors during this build'
unless options['verbose']
msg << ', re-run with `middleman build --verbose` to see the full exception.'
exit(1)
end
shell.say msg, :red
exit(1)
end
end

View File

@ -110,22 +110,22 @@ Feature: Assets get file hashes appended to them and references to them are upda
Scenario: Enabling an asset host still produces hashed files and references
Given the Server is running at "asset-hash-host-app"
When I go to "/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-e587b659.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-7af0b5ab.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/site-4b64a653.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-a772891f.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"'
When I go to "/subdir/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-e587b659.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/site-4b64a653.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
When I go to "/other/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-e587b659.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/site-4b64a653.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"'
When I go to "/stylesheets/fragment-7af0b5ab.css"
When I go to "/stylesheets/fragment-a772891f.css"
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg")'
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?test")'
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test")'

View File

@ -0,0 +1 @@
activate :asset_host, host: "http://assets1.example.com"

View File

@ -210,46 +210,51 @@ module Middleman
# Search the root of the project for required files
$LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root)
@callbacks = ::Middleman::CallbackManager.new
@callbacks.install_methods!(self, [
:initialized,
:configure,
:before_extensions,
:before_sitemap,
:before_configuration,
:after_configuration,
:after_configuration_eval,
:ready,
:before_build,
:after_build,
:before_shutdown,
:before, # Before Rack requests
:before_render,
:after_render,
:before_server
])
::Middleman::Util.instrument "application.setup" do
@callbacks = ::Middleman::CallbackManager.new
@callbacks.install_methods!(self, [
:initialized,
:configure,
:before_extensions,
:before_instance_block,
:before_sitemap,
:before_configuration,
:after_configuration,
:after_configuration_eval,
:ready,
:before_build,
:after_build,
:before_shutdown,
:before, # Before Rack requests
:before_render,
:after_render,
:before_server
])
@middleware = Set.new
@mappings = Set.new
@middleware = Set.new
@mappings = Set.new
@template_context_class = Class.new(Middleman::TemplateContext)
@generic_template_context = @template_context_class.new(self)
@config_context = ConfigContext.new(self, @template_context_class)
@template_context_class = Class.new(Middleman::TemplateContext)
@generic_template_context = @template_context_class.new(self)
@config_context = ConfigContext.new(self, @template_context_class)
# Setup the default values from calls to set before initialization
@config = ::Middleman::Configuration::ConfigurationManager.new
@config.load_settings(self.class.config.all_settings)
# Setup the default values from calls to set before initialization
@config = ::Middleman::Configuration::ConfigurationManager.new
@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
# TODO, make this less global
::Middleman::FileRenderer.cache.clear
::Middleman::TemplateRenderer.cache.clear
end
execute_callbacks(:before_extensions)
@extensions = ::Middleman::ExtensionManager.new(self)
execute_callbacks(:before_instance_block)
# Evaluate a passed block if given
config_context.instance_exec(&block) if block_given?

View File

@ -72,13 +72,17 @@ module Middleman
Contract ResourceList
def prerender_css
logger.debug '== Prerendering CSS'
css_files = @app.sitemap.resources.select do |resource|
resource.ext == '.css'
end.each(&method(:output_resource))
logger.debug '== Checking for Compass sprites'
css_files = @app.sitemap.resources
.select { |resource| resource.ext == '.css' }
.each(&method(:output_resource))
# Double-check for compass sprites
@app.files.find_new_files!
@app.sitemap.ensure_resource_list_updated!
if @app.files.find_new_files!.length > 0
logger.debug '== Checking for Compass sprites'
@app.sitemap.ensure_resource_list_updated!
end
css_files
end
@ -131,24 +135,26 @@ module Middleman
# @return [void]
Contract Pathname, Or[String, Pathname] => Any
def export_file!(output_file, source)
source = write_tempfile(output_file, source.to_s) if source.is_a? String
# ::Middleman::Util.instrument "write_file", output_file: output_file do
source = write_tempfile(output_file, source.to_s) if source.is_a? String
method, source_path = if source.is_a? Tempfile
[FileUtils.method(:mv), source.path]
else
[FileUtils.method(:cp), source.to_s]
end
method, source_path = if source.is_a? Tempfile
[::FileUtils.method(:mv), source.path]
else
[::FileUtils.method(:cp), source.to_s]
end
mode = which_mode(output_file, source_path)
mode = which_mode(output_file, source_path)
if mode == :created || mode == :updated
FileUtils.mkdir_p(output_file.dirname)
method.call(source_path, output_file.to_s)
end
if mode == :created || mode == :updated
::FileUtils.mkdir_p(output_file.dirname)
method.call(source_path, output_file.to_s)
end
source.unlink if source.is_a? Tempfile
source.unlink if source.is_a? Tempfile
trigger(mode, output_file)
trigger(mode, output_file)
# end
end
# Try to output a resource and capture errors.
@ -162,7 +168,7 @@ module Middleman
if resource.binary?
export_file!(output_file, resource.file_descriptor[:full_path])
else
response = @rack.get(URI.escape(resource.request_path))
response = @rack.get(::URI.escape(resource.request_path))
# If we get a response, save it to a tempfile.
if response.status == 200

View File

@ -48,8 +48,15 @@ module Middleman
Contract Or[Symbol, ArrayOf[Symbol]], Maybe[ArrayOf[Any]], Maybe[RespondTo[:instance_exec]] => Any
def execute(keys, args=[], scope=self)
callbacks_for(keys).each { |b| scope.instance_exec(*args, &b) }
@subscribers.each { |b| scope.instance_exec(keys, args, &b) }
callbacks = callbacks_for(keys)
callbacks_count = callbacks.length + @subscribers.length
return if callbacks_count < 1
# ::Middleman::Util.instrument "callbacks.execute", keys: keys, length: callbacks_count do
callbacks.each { |b| scope.instance_exec(*args, &b) }
@subscribers.each { |b| scope.instance_exec(keys, args, &b) }
# end
end
Contract Or[Symbol, ArrayOf[Symbol]] => ::Hamster::Vector

View File

@ -19,6 +19,12 @@ Middleman::Extensions.register :data, auto_activate: :before_sitemap do
Middleman::CoreExtensions::Data
end
# Rewrite embedded URLs via Rack
Middleman::Extensions.register :inline_url_rewriter, auto_activate: :before_sitemap do
require 'middleman-core/core_extensions/inline_url_rewriter'
Middleman::CoreExtensions::InlineURLRewriter
end
# Catch and show exceptions at the Rack level
Middleman::Extensions.register :show_exceptions, auto_activate: :before_configuration, modes: [:server] do
require 'middleman-core/core_extensions/show_exceptions'

View File

@ -30,6 +30,7 @@ module Middleman::CoreExtensions
resources.each do |resource|
next if resource.ignored?
next if resource.file_descriptor.nil?
next unless resource.template?
fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup

View File

@ -0,0 +1,148 @@
require 'rack'
require 'rack/response'
require 'addressable/uri'
require 'middleman-core/util'
require 'middleman-core/contracts'
module Middleman
module CoreExtensions
class InlineURLRewriter < ::Middleman::Extension
include Contracts
expose_to_application rewrite_inline_urls: :add
IGNORE_DESCRIPTOR = Or[Regexp, RespondTo[:call], String]
REWRITER_DESCRIPTOR = {
id: Symbol,
proc: Or[Proc, Method],
url_extensions: ArrayOf[String],
source_extensions: ArrayOf[String],
ignore: ArrayOf[IGNORE_DESCRIPTOR]
}
def initialize(app, options_hash={}, &block)
super
@rewriters = {}
end
Contract REWRITER_DESCRIPTOR => Any
def add(options)
@rewriters[options] = options
end
def after_configuration
app.use Rack, {
rewriters: @rewriters.values,
middleman_app: @app
}
end
class Rack
include Contracts
Contract RespondTo[:call], ({
middleman_app: IsA['Middleman::Application'],
rewriters: ArrayOf[REWRITER_DESCRIPTOR]
}) => Any
def initialize(app, options={})
@rack_app = app
@middleman_app = options.fetch(:middleman_app)
@rewriters = options.fetch(:rewriters)
end
def call(env)
status, headers, response = @rack_app.call(env)
# Allow configuration or upstream request to skip all rewriting
return [status, headers, response] if env['bypass_inline_url_rewriter'] == 'true'
all_source_exts = @rewriters
.reduce([]) { |sum, rewriter| sum + rewriter[:source_extensions] }
.flatten
.uniq
source_exts_regex_text = Regexp.union(all_source_exts).to_s
all_asset_exts = @rewriters
.reduce([]) { |sum, rewriter| sum + rewriter[:url_extensions] }
.flatten
.uniq
path = ::Middleman::Util.full_path(env['PATH_INFO'], @middleman_app)
return [status, headers, response] unless path =~ /(^\/$)|(#{source_exts_regex_text}$)/
return [status, headers, response] unless body = ::Middleman::Util.extract_response_text(response)
dirpath = ::Pathname.new(File.dirname(path))
rewritten = nil
# ::Middleman::Util.instrument "inline_url_rewriter", path: path do
rewritten = ::Middleman::Util.rewrite_paths(body, path, all_asset_exts) do |asset_path|
uri = ::Addressable::URI.parse(asset_path)
relative_path = uri.host.nil?
full_asset_path = if relative_path
dirpath.join(asset_path).to_s
else
asset_path
end
@rewriters.each do |rewriter|
uid = rewriter.fetch(:id)
# Allow upstream request to skip this specific rewriting
next if env["bypass_inline_url_rewriter_#{uid}"] == 'true'
exts = rewriter.fetch(:url_extensions)
next unless exts.include?(::File.extname(asset_path))
source_exts = rewriter.fetch(:source_extensions)
next unless source_exts.include?(::File.extname(path))
ignore = rewriter.fetch(:ignore)
next if ignore.any? { |r| should_ignore?(r, full_asset_path) }
rewrite_ignore = Array(rewriter.fetch(:rewrite_ignore, []))
next if rewrite_ignore.any? { |ignore| ::Middleman::Util.path_match(ignore, path) }
proc = rewriter.fetch(:proc)
result = proc.call(asset_path, dirpath, path)
asset_path = result if result
end
asset_path
# end
end
::Rack::Response.new(
rewritten,
status,
headers
).finish
end
Contract IGNORE_DESCRIPTOR, String => Bool
def should_ignore?(validator, value)
if validator.is_a? Regexp
# Treat as Regexp
!value.match(validator).nil?
elsif validator.respond_to? :call
# Treat as proc
validator.call(value)
elsif validator.is_a? String
# Treat as glob
File.fnmatch(value, validator)
else
# If some unknown thing, don't ignore
false
end
end
end
end
end
end

View File

@ -1,8 +1,8 @@
require 'addressable/uri'
require 'middleman-core/util'
require 'middleman-core/rack'
class Middleman::Extensions::AssetHash < ::Middleman::Extension
option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for hashable assets.'
option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .woff2 .eot .ttf .svg .svgz), 'List of extensions that get asset hashes appended to them.'
option :ignore, [], 'Regexes of filenames to skip adding asset hashes to'
option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
@ -10,23 +10,19 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
def initialize(app, options_hash={}, &block)
super
require 'addressable/uri'
require 'digest/sha1'
require 'rack/mock'
require 'middleman-core/middleware/inline_url_rewriter'
end
def after_configuration
# Allow specifying regexes to ignore, plus always ignore apple touch icons
@ignore = Array(options.ignore) + [/^apple-touch-icon/]
app.use ::Middleman::Middleware::InlineURLRewriter,
id: :asset_hash,
url_extensions: options.exts.sort.reverse,
source_extensions: %w(.htm .html .php .css .js),
ignore: @ignore,
rewrite_ignore: options.rewrite_ignore,
middleman_app: app,
proc: method(:rewrite_url)
app.rewrite_inline_urls id: :asset_hash,
url_extensions: options.exts.sort.reverse,
source_extensions: options.sources,
ignore: @ignore,
rewrite_ignore: options.rewrite_ignore,
proc: method(:rewrite_url)
end
Contract String, Or[String, Pathname], Any => Maybe[String]
@ -77,15 +73,19 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
return if ignored_resource?(resource)
return if resource.ignored?
# Render through the Rack interface so middleware and mounted apps get a shot
response = @rack_client.get(
URI.escape(resource.destination_path),
'bypass_inline_url_rewriter_asset_hash' => 'true'
)
digest = if resource.template?
# Render through the Rack interface so middleware and mounted apps get a shot
response = @rack_client.get(
::URI.escape(resource.destination_path),
'bypass_inline_url_rewriter_asset_hash' => 'true'
)
raise "#{resource.path} should be in the sitemap!" unless response.status == 200
raise "#{resource.path} should be in the sitemap!" unless response.status == 200
digest = Digest::SHA1.hexdigest(response.body)[0..7]
::Digest::SHA1.hexdigest(response.body)[0..7]
else
::Digest::SHA1.file(resource.source_file).hexdigest[0..7]
end
resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
resource

View File

@ -1,5 +1,4 @@
require 'addressable/uri'
require 'middleman-core/middleware/inline_url_rewriter'
class Middleman::Extensions::AssetHost < ::Middleman::Extension
option :host, nil, 'The asset host to use or a Proc to determine asset host', required: true
@ -8,15 +7,15 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
option :ignore, [], 'Regexes of filenames to skip adding query strings to'
option :rewrite_ignore, [], 'Regexes of filenames to skip processing for host rewrites'
def ready
app.use ::Middleman::Middleware::InlineURLRewriter,
id: :asset_host,
url_extensions: options.exts,
source_extensions: options.sources,
ignore: options.ignore,
rewrite_ignore: options.rewrite_ignore,
middleman_app: app,
proc: method(:rewrite_url)
def initialize(app, options_hash={}, &block)
super
app.rewrite_inline_urls id: :asset_host,
url_extensions: options.exts,
source_extensions: options.sources,
ignore: options.ignore,
rewrite_ignore: options.rewrite_ignore,
proc: method(:rewrite_url)
end
Contract String, Or[String, Pathname], Any => String

View File

@ -8,18 +8,12 @@ class Middleman::Extensions::CacheBuster < ::Middleman::Extension
def initialize(app, options_hash={}, &block)
super
require 'middleman-core/middleware/inline_url_rewriter'
end
def after_configuration
app.use ::Middleman::Middleware::InlineURLRewriter,
id: :cache_buster,
url_extensions: options.exts,
source_extensions: options.sources,
ignore: options.ignore,
rewrite_ignore: options.rewrite_ignore,
middleman_app: app,
proc: method(:rewrite_url)
app.rewrite_inline_urls id: :cache_buster,
url_extensions: options.exts,
source_extensions: options.sources,
ignore: options.ignore,
rewrite_ignore: options.rewrite_ignore,
proc: method(:rewrite_url)
end
Contract String, Or[String, Pathname], Any => String

View File

@ -10,18 +10,12 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
def initialize(app, options_hash={}, &block)
super
require 'middleman-core/middleware/inline_url_rewriter'
end
def ready
app.use ::Middleman::Middleware::InlineURLRewriter,
id: :asset_hash,
url_extensions: options.exts,
source_extensions: options.sources,
ignore: options.ignore,
rewrite_ignore: options.rewrite_ignore,
middleman_app: app,
proc: method(:rewrite_url)
app.rewrite_inline_urls id: :asset_hash,
url_extensions: options.exts,
source_extensions: options.sources,
ignore: options.ignore,
rewrite_ignore: options.rewrite_ignore,
proc: method(:rewrite_url)
end
helpers do

View File

@ -73,9 +73,11 @@ module Middleman
# end
# Render using Tilt
content = ::Middleman::Util.instrument 'render.tilt', path: path do
template.render(context, locs, &block)
end
content = nil
# ::Middleman::Util.instrument 'render.tilt', path: path do
content = template.render(context, locs, &block)
# end
# Allow hooks to manipulate the result after render
content = @app.callbacks_for(:after_render).reduce(content) do |sum, callback|

View File

@ -1,109 +0,0 @@
require 'rack'
require 'rack/response'
require 'addressable/uri'
require 'middleman-core/util'
require 'middleman-core/contracts'
module Middleman
module Middleware
class InlineURLRewriter
include Contracts
IGNORE_DESCRIPTOR = Or[Regexp, RespondTo[:call], String]
Contract RespondTo[:call], ({
middleman_app: IsA['Middleman::Application'],
id: Maybe[Symbol],
proc: Or[Proc, Method],
url_extensions: ArrayOf[String],
source_extensions: ArrayOf[String],
ignore: ArrayOf[IGNORE_DESCRIPTOR]
}) => Any
def initialize(app, options={})
@rack_app = app
@middleman_app = options.fetch(:middleman_app)
@uid = options.fetch(:id, nil)
@proc = options.fetch(:proc)
raise 'InlineURLRewriter requires a :proc to call with inline URL results' unless @proc
@exts = options.fetch(:url_extensions)
@source_exts = options.fetch(:source_extensions)
@source_exts_regex_text = Regexp.union(@source_exts).to_s
@ignore = options.fetch(:ignore)
@rewrite_ignore = Array(options.fetch(:rewrite_ignore, []))
end
def call(env)
status, headers, response = @rack_app.call(env)
# Allow configuration or upstream request to skip all rewriting
if rewrite_ignore?(env['PATH_INFO']) || env['bypass_inline_url_rewriter'] == 'true'
return [status, headers, response]
end
# Allow upstream request to skip this specific rewriting
if @uid
uid_key = "bypass_inline_url_rewriter_#{@uid}"
return [status, headers, response] if env[uid_key] == 'true'
end
path = ::Middleman::Util.full_path(env['PATH_INFO'], @middleman_app)
if path =~ /(^\/$)|(#{@source_exts_regex_text}$)/
if body = ::Middleman::Util.extract_response_text(response)
dirpath = Pathname.new(File.dirname(path))
rewritten = ::Middleman::Util.rewrite_paths(body, path, @exts) do |asset_path|
uri = ::Addressable::URI.parse(asset_path)
relative_path = uri.host.nil?
full_asset_path = if relative_path
dirpath.join(asset_path).to_s
else
asset_path
end
@ignore.none? { |r| should_ignore?(r, full_asset_path) } && @proc.call(asset_path, dirpath, path)
end
status, headers, response = ::Rack::Response.new(
rewritten,
status,
headers
).finish
end
end
[status, headers, response]
end
Contract IGNORE_DESCRIPTOR, String => Bool
def should_ignore?(validator, value)
if validator.is_a? Regexp
# Treat as Regexp
!value.match(validator).nil?
elsif validator.respond_to? :call
# Treat as proc
validator.call(value)
elsif validator.is_a? String
# Treat as glob
File.fnmatch(value, validator)
else
# If some unknown thing, don't ignore
false
end
end
Contract String => Bool
def rewrite_ignore?(path)
@rewrite_ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) }
end
end
end
end

View File

@ -127,9 +127,9 @@ module Middleman
# @return [String]
Contract Hash, Hash => String
def render(opts={}, locs={})
return ::Middleman::FileRenderer.new(@app, file_descriptor[:full_path].to_s).template_data_for_file unless template?
return File.read(file_descriptor[:full_path].to_s) unless template?
::Middleman::Util.instrument 'render.resource', path: file_descriptor[:full_path].to_s, destination_path: destination_path do
# ::Middleman::Util.instrument 'render.resource', path: file_descriptor[:full_path].to_s, destination_path: destination_path do
md = metadata
opts = md[:options].deep_merge(opts)
locs = md[:locals].deep_merge(locs)
@ -140,7 +140,7 @@ module Middleman
renderer = ::Middleman::TemplateRenderer.new(@app, file_descriptor[:full_path].to_s)
renderer.render(locs, opts)
end
# end
end
# A path without the directory index - so foo/index.html becomes

View File

@ -75,6 +75,7 @@ module Middleman
def initialize(app)
@app = app
@resources = []
@rebuild_reasons = [:first_run]
@update_count = 0
@resource_list_manipulators = ::Hamster::Vector.empty
@ -115,9 +116,10 @@ module Middleman
# Rebuild the list of resources from scratch, using registed manipulators
# @return [void]
Contract Maybe[Symbol] => Any
def rebuild_resource_list!(name=nil)
Contract Symbol => Any
def rebuild_resource_list!(name)
@lock.synchronize do
@rebuild_reasons << name
@app.logger.debug "== Requesting resource list rebuilding: #{name}"
@needs_sitemap_rebuild = true
end
@ -198,29 +200,36 @@ module Middleman
def ensure_resource_list_updated!
@lock.synchronize do
return unless @needs_sitemap_rebuild
@needs_sitemap_rebuild = false
@app.logger.debug '== Rebuilding resource list'
::Middleman::Util.instrument "sitemap.update", reasons: @rebuild_reasons.uniq do
@needs_sitemap_rebuild = false
@resources = []
@app.logger.debug '== Rebuilding resource list'
@resource_list_manipulators.each do |m|
@app.logger.debug "== Running manipulator: #{m[:name]}"
@resources = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, @resources)
@resources = []
# Reset lookup cache
reset_lookup_cache!
@resource_list_manipulators.each do |m|
::Middleman::Util.instrument "sitemap.manipulator", name: m[:name] do
@app.logger.debug "== Running manipulator: #{m[:name]}"
@resources = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, @resources)
# Rebuild cache
@resources.each do |resource|
@_lookup_by_path[resource.path] = resource
@_lookup_by_destination_path[resource.destination_path] = resource
# Reset lookup cache
reset_lookup_cache!
# Rebuild cache
@resources.each do |resource|
@_lookup_by_path[resource.path] = resource
@_lookup_by_destination_path[resource.destination_path] = resource
end
invalidate_resources_not_ignored_cache!
end
end
invalidate_resources_not_ignored_cache!
end
@update_count += 1
@update_count += 1
@rebuild_reasons = []
end
end
end

View File

@ -213,12 +213,12 @@ module Middleman
# Manually poll all watchers for new content.
#
# @return [void]
Contract Any
Contract ArrayOf[Pathname]
def find_new_files!
return unless @update_count != @last_update_count
return [] unless @update_count != @last_update_count
@last_update_count = @update_count
watchers.each(&:poll_once!)
watchers.reduce([]) { |sum, w| sum + w.poll_once! }
end
# Start up all listeners.

View File

@ -180,17 +180,19 @@ module Middleman
# Manually trigger update events.
#
# @return [void]
Contract Any
Contract ArrayOf[Pathname]
def poll_once!
updated = ::Middleman::Util.all_files_under(@directory.to_s)
removed = @files.keys.reject { |p| updated.include?(p) }
update(updated, removed)
return unless @waiting_for_existence && @directory.exist?
if @waiting_for_existence && @directory.exist?
@waiting_for_existence = false
listen!
end
@waiting_for_existence = false
listen!
updated + removed
end
# Work around this bug: http://bugs.ruby-lang.org/issues/4521

View File

@ -4,22 +4,23 @@ require 'capybara/cucumber'
Given /^a clean server$/ do
@initialize_commands = []
@activation_commands = []
end
Given /^"([^\"]*)" feature is "([^\"]*)"$/ do |feature, state|
@initialize_commands ||= []
@activation_commands ||= []
if state == 'enabled'
@initialize_commands << lambda { activate(feature.to_sym) }
@activation_commands << lambda { activate(feature.to_sym) }
end
end
Given /^"([^\"]*)" feature is "enabled" with "([^\"]*)"$/ do |feature, options_str|
@initialize_commands ||= []
@activation_commands ||= []
options = eval("{#{options_str}}")
@initialize_commands << lambda { activate(feature.to_sym, options) }
@activation_commands << lambda { activate(feature.to_sym, options) }
end
Given /^"([^\"]*)" is set to "([^\"]*)"$/ do |variable, value|
@ -41,6 +42,7 @@ Given /^the Server is running$/ do
ENV['MM_ROOT'] = root_dir
initialize_commands = @initialize_commands || []
activation_commands = @activation_commands || []
@server_inst = ::Middleman::Application.new do
config[:watcher_disable] = true
@ -49,6 +51,12 @@ Given /^the Server is running$/ do
initialize_commands.each do |p|
instance_exec(&p)
end
app.after_configuration_eval do
activation_commands.each do |p|
config_context.instance_exec(&p)
end
end
end
Capybara.app = ::Middleman::Rack.new(@server_inst).to_app

View File

@ -332,7 +332,7 @@ module Middleman
end
Contract String, String, ArrayOf[String], Proc => String
def rewrite_paths(body, _path, exts, &_block)
def rewrite_paths(body, _path, exts, &block)
matcher = /([=\'\"\(,]\s*)([^\s\'\"\)>]+(#{Regexp.union(exts)}))/
url_fn_prefix = 'url('
@ -349,7 +349,7 @@ module Middleman
begin
uri = ::Addressable::URI.parse(asset_path)
if uri.relative? && uri.host.nil? && (result = yield(asset_path))
if uri.relative? && uri.host.nil? && (result = block.call(asset_path))
"#{opening_character}#{result}"
else
match

View File

@ -17,7 +17,7 @@ module Middleman
# @return [Array<Hash, String>]
Contract Pathname, Maybe[Symbol] => [Hash, Maybe[String]]
def parse(full_path, frontmatter_delims, known_type=nil)
return [{}, nil] if Middleman::Util.binary?(full_path)
return [{}, nil] if ::Middleman::Util.binary?(full_path)
# Avoid weird race condition when a file is renamed
begin
@ -74,8 +74,8 @@ module Middleman
# @return [Hash]
Contract String, Pathname, Bool => Hash
def parse_yaml(content, full_path)
symbolize_recursive(YAML.load(content) || {})
rescue StandardError, Psych::SyntaxError => error
symbolize_recursive(::YAML.load(content) || {})
rescue StandardError, ::Psych::SyntaxError => error
warn "YAML Exception parsing #{full_path}: #{error.message}"
{}
end
@ -85,7 +85,7 @@ module Middleman
# @return [Hash]
Contract String, Pathname => Hash
def parse_json(content, full_path)
symbolize_recursive(JSON.parse(content) || {})
symbolize_recursive(::JSON.parse(content) || {})
rescue StandardError => error
warn "JSON Exception parsing #{full_path}: #{error.message}"
{}