From 5f8beba4b37c4fa8b9be4a6dc92927df3be3857c Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 13 Jan 2016 17:16:36 -0800 Subject: [PATCH 001/140] Perf --- .rubocop.yml | 1 - middleman-cli/lib/middleman-cli/build.rb | 49 +++--- middleman-core/features/asset_hash.feature | 10 +- .../fixtures/asset-host-app/config.rb | 1 + .../lib/middleman-core/application.rb | 65 ++++---- middleman-core/lib/middleman-core/builder.rb | 46 +++--- .../lib/middleman-core/callback_manager.rb | 11 +- .../lib/middleman-core/core_extensions.rb | 6 + .../core_extensions/front_matter.rb | 1 + .../core_extensions/inline_url_rewriter.rb | 148 ++++++++++++++++++ .../middleman-core/extensions/asset_hash.rb | 40 ++--- .../middleman-core/extensions/asset_host.rb | 19 ++- .../middleman-core/extensions/cache_buster.rb | 18 +-- .../extensions/relative_assets.rb | 18 +-- .../lib/middleman-core/file_renderer.rb | 8 +- .../middleware/inline_url_rewriter.rb | 109 ------------- .../lib/middleman-core/sitemap/resource.rb | 4 +- .../lib/middleman-core/sitemap/store.rb | 43 +++-- middleman-core/lib/middleman-core/sources.rb | 6 +- .../middleman-core/sources/source_watcher.rb | 10 +- .../step_definitions/server_steps.rb | 16 +- middleman-core/lib/middleman-core/util.rb | 4 +- .../lib/middleman-core/util/data.rb | 8 +- middleman-core/middleman-core.gemspec | 1 + 24 files changed, 361 insertions(+), 281 deletions(-) create mode 100644 middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb delete mode 100644 middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb diff --git a/.rubocop.yml b/.rubocop.yml index c1b86127..8d078f21 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,7 +10,6 @@ AllCops: - '**/tmp/**/*' - '**/bin/**/*' - 'middleman-core/lib/middleman-core/step_definitions/**/*' - - 'middleman-core/lib/vendored-middleman-deps/**/*' - 'middleman-cli/lib/middleman-cli/templates/**/*' - 'middleman-core/fixtures/**/*' - 'middleman-core/features/**/*' diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index 1ef884b2..3ff1d638 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -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 diff --git a/middleman-core/features/asset_hash.feature b/middleman-core/features/asset_hash.feature index 0a05c1a6..751b9e30 100644 --- a/middleman-core/features/asset_hash.feature +++ b/middleman-core/features/asset_hash.feature @@ -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")' diff --git a/middleman-core/fixtures/asset-host-app/config.rb b/middleman-core/fixtures/asset-host-app/config.rb index e69de29b..e470be25 100644 --- a/middleman-core/fixtures/asset-host-app/config.rb +++ b/middleman-core/fixtures/asset-host-app/config.rb @@ -0,0 +1 @@ + activate :asset_host, host: "http://assets1.example.com" diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index be603df4..659bd1ba 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -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? diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index 02feb15b..add35fe9 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/callback_manager.rb b/middleman-core/lib/middleman-core/callback_manager.rb index 4315256a..5db86302 100644 --- a/middleman-core/lib/middleman-core/callback_manager.rb +++ b/middleman-core/lib/middleman-core/callback_manager.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/core_extensions.rb b/middleman-core/lib/middleman-core/core_extensions.rb index ea31f89a..e38be937 100644 --- a/middleman-core/lib/middleman-core/core_extensions.rb +++ b/middleman-core/lib/middleman-core/core_extensions.rb @@ -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' diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index 739b49fd..ffde6b19 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -28,6 +28,7 @@ module Middleman::CoreExtensions Contract ResourceList => ResourceList def manipulate_resource_list(resources) resources.each do |resource| + next if resource.binary? next if resource.ignored? next if resource.file_descriptor.nil? diff --git a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb new file mode 100644 index 00000000..2d04902d --- /dev/null +++ b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index da84a23d..7122eb10 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -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,29 +10,25 @@ 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] def rewrite_url(asset_path, dirpath, _request_path) uri = ::Addressable::URI.parse(asset_path) - relative_path = uri.path[0..0] != '/' + relative_path = !uri.path.start_with?('/') full_asset_path = if relative_path dirpath.join(asset_path).to_s @@ -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.binary? + ::Digest::SHA1.file(resource.source_file).hexdigest[0..7] + else + # 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] + end resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" } resource diff --git a/middleman-core/lib/middleman-core/extensions/asset_host.rb b/middleman-core/lib/middleman-core/extensions/asset_host.rb index 05b4509f..00d463fa 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_host.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_host.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/extensions/cache_buster.rb b/middleman-core/lib/middleman-core/extensions/cache_buster.rb index 8f1ceb64..44eda9bc 100644 --- a/middleman-core/lib/middleman-core/extensions/cache_buster.rb +++ b/middleman-core/lib/middleman-core/extensions/cache_buster.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/extensions/relative_assets.rb b/middleman-core/lib/middleman-core/extensions/relative_assets.rb index f232f6a4..a6d1f074 100644 --- a/middleman-core/lib/middleman-core/extensions/relative_assets.rb +++ b/middleman-core/lib/middleman-core/extensions/relative_assets.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index 09c6b5d2..1eb551d9 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -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| diff --git a/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb deleted file mode 100644 index b76c3285..00000000 --- a/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb +++ /dev/null @@ -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 diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 7a13e9f9..ceb7bb7f 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -129,7 +129,7 @@ module Middleman def render(opts={}, locs={}) return ::Middleman::FileRenderer.new(@app, file_descriptor[:full_path].to_s).template_data_for_file 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 diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index 985b3ae4..4d938cac 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 6b888a87..44c3e316 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -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. diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 00e500fb..6d667db0 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 7defbbc0..5f32e691 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index c4210a0e..ec6b1854 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -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 diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb index c1dc1cd3..6670f989 100644 --- a/middleman-core/lib/middleman-core/util/data.rb +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -17,7 +17,7 @@ module Middleman # @return [Array] 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}" {} diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 3769e4e2..894bf470 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -23,6 +23,7 @@ Gem::Specification.new do |s| s.add_dependency('rack', ['>= 1.4.5', '< 2.0']) s.add_dependency('tilt', ['~> 1.4.1']) s.add_dependency('erubis') + s.add_dependency('fast_blank') # Helpers s.add_dependency('activesupport', ['~> 4.2']) From d82ac590db5fbb4f7482aed679acef9646d1c45c Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 14 Jan 2016 11:21:42 -0800 Subject: [PATCH 002/140] Cop --- .rubocop.yml | 2 + CHANGELOG.md | 2 + Rakefile | 8 +- middleman-cli/Rakefile | 4 +- middleman-cli/lib/middleman-cli/build.rb | 4 +- middleman-core/Rakefile | 2 +- .../lib/middleman-core/application.rb | 43 +++-- middleman-core/lib/middleman-core/builder.rb | 46 +++--- .../lib/middleman-core/callback_manager.rb | 4 +- .../core_extensions/collections/lazy_step.rb | 2 +- .../middleman-core/core_extensions/data.rb | 2 +- .../core_extensions/default_helpers.rb | 6 +- .../core_extensions/file_watcher.rb | 2 +- .../middleman-core/core_extensions/i18n.rb | 6 +- .../core_extensions/inline_url_rewriter.rb | 36 ++--- .../middleman-core/core_extensions/routing.rb | 4 +- .../lib/middleman-core/extension.rb | 4 +- .../lib/middleman-core/extensions/lorem.rb | 2 +- .../middleman-core/extensions/minify_css.rb | 4 +- .../extensions/minify_javascript.rb | 4 +- .../lib/middleman-core/file_renderer.rb | 8 +- .../lib/middleman-core/preview_server.rb | 6 +- .../preview_server/server_hostname.rb | 4 +- middleman-core/lib/middleman-core/rack.rb | 2 +- .../lib/middleman-core/renderers/kramdown.rb | 2 +- .../lib/middleman-core/renderers/less.rb | 2 +- .../lib/middleman-core/renderers/redcarpet.rb | 2 +- .../lib/middleman-core/renderers/sass.rb | 2 - .../sitemap/extensions/ignores.rb | 4 +- .../sitemap/extensions/import.rb | 14 +- .../sitemap/extensions/proxies.rb | 2 +- .../sitemap/extensions/redirects.rb | 2 +- .../sitemap/extensions/traversal.rb | 10 +- .../lib/middleman-core/sitemap/resource.rb | 28 ++-- .../lib/middleman-core/sitemap/store.rb | 4 +- middleman-core/lib/middleman-core/sources.rb | 12 +- .../middleman-core/sources/source_watcher.rb | 10 +- .../lib/middleman-core/template_context.rb | 2 +- .../lib/middleman-core/template_renderer.rb | 149 +++++++++--------- middleman-core/lib/middleman-core/util.rb | 8 +- middleman-core/lib/middleman-core/version.rb | 2 +- middleman/Rakefile | 4 +- 42 files changed, 229 insertions(+), 237 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8d078f21..bf44c2f8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -52,6 +52,8 @@ CaseIndentation: IndentWhenRelativeTo: end TrivialAccessors: ExactNameMatch: true +SingleLineBlockParams: + Enabled: false Metrics/AbcSize: Enabled: false Metrics/PerceivedComplexity: diff --git a/CHANGELOG.md b/CHANGELOG.md index 370a5e81..49440d94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ master * Don't parse frontmatter on ignored files. * Fix displaying frontmatter on `/__middleman/sitemap` * Add `skip_build_clean` config which when set to a block, will avoid removing non-generated paths from build, like .git #1716 +* Minor performance improvements +* DRY-up config.rb-specific commands like `ignore` or `path`. # 4.0.0 diff --git a/Rakefile b/Rakefile index 236a2d83..508c3a1d 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,7 @@ require 'rake' require File.expand_path('../middleman-core/lib/middleman-core/version.rb', __FILE__) ROOT = File.expand_path(File.dirname(__FILE__)) -GEM_NAME = 'middleman' +GEM_NAME = 'middleman'.freeze middleman_gems = %w(middleman-core middleman-cli middleman) GEM_PATHS = middleman_gems.freeze @@ -36,7 +36,7 @@ end desc 'Generate documentation for all middleman gems' task :doc do GEM_PATHS.each do |g| - Dir.chdir("#{File.join(ROOT, g)}") { sh "#{Gem.ruby} -S rake yard" } + Dir.chdir(File.join(ROOT, g).to_s) { sh "#{Gem.ruby} -S rake yard" } end end @@ -45,14 +45,14 @@ task :test do Rake::Task['rubocop'].invoke GEM_PATHS.each do |g| - Dir.chdir("#{File.join(ROOT, g)}") { sh "#{Gem.ruby} -S rake test" } + Dir.chdir(File.join(ROOT, g).to_s) { sh "#{Gem.ruby} -S rake test" } end end desc 'Run specs for all middleman gems' task :spec do GEM_PATHS.each do |g| - Dir.chdir("#{File.join(ROOT, g)}") { sh "#{Gem.ruby} -S rake spec" } + Dir.chdir(File.join(ROOT, g).to_s) { sh "#{Gem.ruby} -S rake spec" } end end diff --git a/middleman-cli/Rakefile b/middleman-cli/Rakefile index a7cd6621..db0d1cb8 100644 --- a/middleman-cli/Rakefile +++ b/middleman-cli/Rakefile @@ -1,4 +1,4 @@ # coding:utf-8 -RAKE_ROOT = __FILE__ -GEM_NAME = 'middleman-cli' +RAKE_ROOT = __FILE__.freeze +GEM_NAME = 'middleman-cli'.freeze require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper') diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index 3ff1d638..e3d098e7 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -52,7 +52,7 @@ module Middleman::Cli ::Middleman::Logger.singleton(verbose, instrument) - ::Middleman::Util.instrument "builder_setup" do + ::Middleman::Util.instrument 'builder_setup' do @app = ::Middleman::Application.new do config[:mode] = :build config[:environment] = env @@ -67,7 +67,7 @@ module Middleman::Cli builder.on_build_event(&method(:on_event)) end - ::Middleman::Util.instrument "builder_run" do + ::Middleman::Util.instrument 'builder_run' do if builder.run! clean_directories! if options['clean'] shell.say 'Project built successfully.' diff --git a/middleman-core/Rakefile b/middleman-core/Rakefile index 3efd63ea..198f09ee 100644 --- a/middleman-core/Rakefile +++ b/middleman-core/Rakefile @@ -1,4 +1,4 @@ # coding:utf-8 -RAKE_ROOT = __FILE__ +RAKE_ROOT = __FILE__.freeze GEM_NAME = ENV['NAME'] || 'middleman-core' require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper') diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 659bd1ba..6915d51e 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -170,7 +170,7 @@ module Middleman ignored = false file[:relative_path].ascend do |f| - if f.basename.to_s.match %r{^_[^_]} + if f.basename.to_s =~ %r{^_[^_]} ignored = true break end @@ -180,8 +180,7 @@ module Middleman end, layout: proc do |file, _sitemap_app| - file[:relative_path].to_s.start_with?('layout.') || - file[:relative_path].to_s.start_with?('layouts/') + file[:relative_path].to_s.start_with?('layout.', 'layouts/') end }, 'Callbacks that can exclude paths from the sitemap' @@ -210,26 +209,26 @@ module Middleman # Search the root of the project for required files $LOAD_PATH.unshift(root) unless $LOAD_PATH.include?(root) - ::Middleman::Util.instrument "application.setup" do + ::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 - ]) + :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 @@ -431,6 +430,6 @@ module Middleman def to_s "#" end - alias_method :inspect, :to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s + alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s end end diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index add35fe9..ef289d42 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -20,7 +20,7 @@ module Middleman def_delegator :@app, :logger # Sort order, images, fonts, js/css and finally everything else. - SORT_ORDER = %w(.png .jpeg .jpg .gif .bmp .svg .svgz .webp .ico .woff .woff2 .otf .ttf .eot .js .css) + SORT_ORDER = %w(.png .jpeg .jpg .gif .bmp .svg .svgz .webp .ico .woff .woff2 .otf .ttf .eot .js .css).freeze # Create a new Builder instance. # @param [Middleman::Application] app The app to build. @@ -74,8 +74,8 @@ module Middleman logger.debug '== Prerendering CSS' css_files = @app.sitemap.resources - .select { |resource| resource.ext == '.css' } - .each(&method(:output_resource)) + .select { |resource| resource.ext == '.css' } + .each(&method(:output_resource)) # Double-check for compass sprites if @app.files.find_new_files!.length > 0 @@ -93,10 +93,10 @@ module Middleman logger.debug '== Building files' @app.sitemap.resources - .sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 } - .reject { |resource| resource.ext == '.css' } - .select { |resource| !@glob || File.fnmatch(@glob, resource.destination_path) } - .each(&method(:output_resource)) + .sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 } + .reject { |resource| resource.ext == '.css' } + .select { |resource| !@glob || File.fnmatch(@glob, resource.destination_path) } + .each(&method(:output_resource)) end # Figure out the correct event mode. @@ -119,9 +119,9 @@ module Middleman Contract Pathname, String => Tempfile def write_tempfile(output_file, contents) file = Tempfile.new([ - File.basename(output_file), - File.extname(output_file) - ]) + File.basename(output_file), + File.extname(output_file) + ]) file.binmode file.write(contents) file.close @@ -136,24 +136,24 @@ module Middleman Contract Pathname, Or[String, Pathname] => Any def export_file!(output_file, source) # ::Middleman::Util.instrument "write_file", output_file: output_file do - source = write_tempfile(output_file, source.to_s) if source.is_a? String + 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 diff --git a/middleman-core/lib/middleman-core/callback_manager.rb b/middleman-core/lib/middleman-core/callback_manager.rb index 5db86302..0edaf4cd 100644 --- a/middleman-core/lib/middleman-core/callback_manager.rb +++ b/middleman-core/lib/middleman-core/callback_manager.rb @@ -54,8 +54,8 @@ module Middleman 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) } + callbacks.each { |b| scope.instance_exec(*args, &b) } + @subscribers.each { |b| scope.instance_exec(keys, args, &b) } # end end diff --git a/middleman-core/lib/middleman-core/core_extensions/collections/lazy_step.rb b/middleman-core/lib/middleman-core/core_extensions/collections/lazy_step.rb index 1286af2c..b316b3e3 100644 --- a/middleman-core/lib/middleman-core/core_extensions/collections/lazy_step.rb +++ b/middleman-core/lib/middleman-core/core_extensions/collections/lazy_step.rb @@ -2,7 +2,7 @@ module Middleman module CoreExtensions module Collections class LazyCollectorStep < BasicObject - DELEGATE = [:hash, :eql?] + DELEGATE = [:hash, :eql?].freeze def initialize(name, args, block, parent=nil) @name = name diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index 22d571be..dca657ac 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -189,7 +189,7 @@ module Middleman (@local_data.keys + @local_sources.keys + @callback_sources.keys).include?(key.to_s) end - alias_method :has_key?, :key? + alias has_key? key? # Convert all the data into a static hash # diff --git a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb index be6371c1..745ca71c 100644 --- a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb @@ -9,7 +9,7 @@ class Padrino::Helpers::OutputHelpers::ErbHandler def capture_from_template(*args, &block) self.output_buffer = '' buf_was = output_buffer - raw = block.call(*args) + raw = yield(*args) captured = template.instance_variable_get(:@_out_buf) self.output_buffer = buf_was engine_matches?(block) && !captured.empty? ? captured : raw @@ -55,7 +55,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension output.safe_concat ::Padrino::Helpers::TagHelpers::NEWLINE end else - output.safe_concat "#{content}" + output.safe_concat content.to_s end output.safe_concat "" @@ -66,7 +66,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension result = if handler = auto_find_proper_handler(&block) handler.capture_from_template(*args, &block) else - block.call(*args) + yield(*args) end ::ActiveSupport::SafeBuffer.new.safe_concat(result) diff --git a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb index 617e0ac7..b5769b86 100644 --- a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb +++ b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb @@ -21,7 +21,7 @@ module Middleman tilde_files: /~$/, ds_store: /\.DS_Store$/, git: /(^|\/)\.git(ignore|modules|\/)/ - } + }.freeze # Setup the extension. def initialize(app, config={}, &block) diff --git a/middleman-core/lib/middleman-core/core_extensions/i18n.rb b/middleman-core/lib/middleman-core/core_extensions/i18n.rb index ce16ab48..b2476796 100644 --- a/middleman-core/lib/middleman-core/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-core/core_extensions/i18n.rb @@ -127,7 +127,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension end # Backwards API compat - alias_method :langs, :locales + alias langs locales Contract Symbol def locale @@ -135,7 +135,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension end # Backwards API compat - alias_method :lang, :locale + alias lang locale # Update the main sitemap resource list # @return Array @@ -274,7 +274,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension File.dirname(path).split('/').each do |path_sub| next if path_sub == '' - partially_localized_path = "#{partially_localized_path}/#{(::I18n.t("paths.#{path_sub}", default: path_sub).to_s)}" + partially_localized_path = "#{partially_localized_path}/#{::I18n.t("paths.#{path_sub}", default: path_sub)}" end path = "#{partially_localized_path}/#{File.basename(path)}" diff --git a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb index 2d04902d..a7f7e778 100644 --- a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb @@ -6,7 +6,6 @@ require 'middleman-core/contracts' module Middleman module CoreExtensions - class InlineURLRewriter < ::Middleman::Extension include Contracts @@ -19,7 +18,7 @@ module Middleman url_extensions: ArrayOf[String], source_extensions: ArrayOf[String], ignore: ArrayOf[IGNORE_DESCRIPTOR] - } + }.freeze def initialize(app, options_hash={}, &block) super @@ -33,19 +32,17 @@ module Middleman end def after_configuration - app.use Rack, { - rewriters: @rewriters.values, - middleman_app: @app - } + app.use Rack, rewriters: @rewriters.values, + middleman_app: @app end class Rack include Contracts - Contract RespondTo[:call], ({ + Contract RespondTo[:call], { middleman_app: IsA['Middleman::Application'], rewriters: ArrayOf[REWRITER_DESCRIPTOR] - }) => Any + } => Any def initialize(app, options={}) @rack_app = app @middleman_app = options.fetch(:middleman_app) @@ -59,15 +56,15 @@ module Middleman return [status, headers, response] if env['bypass_inline_url_rewriter'] == 'true' all_source_exts = @rewriters - .reduce([]) { |sum, rewriter| sum + rewriter[:source_extensions] } - .flatten - .uniq + .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 + .reduce([]) { |sum, rewriter| sum + rewriter[:url_extensions] } + .flatten + .uniq path = ::Middleman::Util.full_path(env['PATH_INFO'], @middleman_app) @@ -76,10 +73,8 @@ module Middleman 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| + rewritten = ::Middleman::Util.instrument 'inline_url_rewriter', path: path do + ::Middleman::Util.rewrite_paths(body, path, all_asset_exts) do |asset_path| uri = ::Addressable::URI.parse(asset_path) relative_path = uri.host.nil? @@ -106,7 +101,7 @@ module Middleman 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) } + next if rewrite_ignore.any? { |i| ::Middleman::Util.path_match(i, path) } proc = rewriter.fetch(:proc) @@ -115,7 +110,7 @@ module Middleman end asset_path - # end + end end ::Rack::Response.new( @@ -143,6 +138,5 @@ module Middleman end end end - end end diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb index c5655dfe..089b0486 100644 --- a/middleman-core/lib/middleman-core/core_extensions/routing.rb +++ b/middleman-core/lib/middleman-core/core_extensions/routing.rb @@ -24,8 +24,8 @@ module Middleman normalized_path = '/' + ::Middleman::Util.strip_leading_slash(normalized_path) if normalized_path.is_a?(String) resources - .select { |r| ::Middleman::Util.path_match(normalized_path, "/#{r.path}") } - .each { |r| r.add_metadata(metadata) } + .select { |r| ::Middleman::Util.path_match(normalized_path, "/#{r.path}") } + .each { |r| r.add_metadata(metadata) } resources end diff --git a/middleman-core/lib/middleman-core/extension.rb b/middleman-core/lib/middleman-core/extension.rb index a94a9e12..1a8b8fa4 100644 --- a/middleman-core/lib/middleman-core/extension.rb +++ b/middleman-core/lib/middleman-core/extension.rb @@ -496,8 +496,8 @@ module Middleman @descriptors[k] = [] define_singleton_method(:"__original_#{v}", &method(v)) - define_singleton_method(v) do |*args, &block| - @descriptors[k] << method(:"__original_#{v}").call(*args, &block) + define_singleton_method(v) do |*args, &b| + @descriptors[k] << method(:"__original_#{v}").call(*args, &b) @app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}") end end diff --git a/middleman-core/lib/middleman-core/extensions/lorem.rb b/middleman-core/lib/middleman-core/extensions/lorem.rb index 91a0612d..6cad9abf 100644 --- a/middleman-core/lib/middleman-core/extensions/lorem.rb +++ b/middleman-core/lib/middleman-core/extensions/lorem.rb @@ -44,7 +44,7 @@ class Middleman::Extensions::Lorem < ::Middleman::Extension module LoremObject class << self # Words for use in lorem text - WORDS = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat) + WORDS = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat).freeze # Get one placeholder word # @return [String] diff --git a/middleman-core/lib/middleman-core/extensions/minify_css.rb b/middleman-core/lib/middleman-core/extensions/minify_css.rb index e58b7852..caf54262 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_css.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_css.rb @@ -36,11 +36,11 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension # Init # @param [Class] app # @param [Hash] options - Contract RespondTo[:call], ({ + Contract RespondTo[:call], { ignore: ArrayOf[PATH_MATCHER], inline: Bool, compressor: Or[Proc, RespondTo[:to_proc], RespondTo[:compress]] - }) => Any + } => Any def initialize(app, options={}) @app = app @ignore = options.fetch(:ignore) diff --git a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb index 73a75cd0..7472e561 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb @@ -28,11 +28,11 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension # Init # @param [Class] app # @param [Hash] options - Contract RespondTo[:call], ({ + Contract RespondTo[:call], { ignore: ArrayOf[PATH_MATCHER], inline: Bool, compressor: Or[Proc, RespondTo[:to_proc], RespondTo[:compress]] - }) => Any + } => Any def initialize(app, options={}) @app = app @ignore = options.fetch(:ignore) diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index 1eb551d9..09c6b5d2 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -73,11 +73,9 @@ module Middleman # end # Render using Tilt - content = nil - - # ::Middleman::Util.instrument 'render.tilt', path: path do - content = template.render(context, locs, &block) - # end + content = ::Middleman::Util.instrument 'render.tilt', path: path do + 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| diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 8080868a..93934478 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -247,10 +247,10 @@ module Middleman end end - if is_logging - http_opts[:Logger] = FilteredWebrickLog.new + http_opts[:Logger] = if is_logging + FilteredWebrickLog.new else - http_opts[:Logger] = ::WEBrick::Log.new(nil, 0) + ::WEBrick::Log.new(nil, 0) end begin diff --git a/middleman-core/lib/middleman-core/preview_server/server_hostname.rb b/middleman-core/lib/middleman-core/preview_server/server_hostname.rb index 833daa4d..29fded66 100644 --- a/middleman-core/lib/middleman-core/preview_server/server_hostname.rb +++ b/middleman-core/lib/middleman-core/preview_server/server_hostname.rb @@ -10,7 +10,7 @@ module Middleman true end - alias_method :to_browser, :to_s + alias to_browser to_s end class ServerPlainHostname < SimpleDelegator @@ -24,7 +24,7 @@ module Middleman # rubocop:enable Style/CaseEquality end - alias_method :to_browser, :to_s + alias to_browser to_s end def self.new(string) diff --git a/middleman-core/lib/middleman-core/rack.rb b/middleman-core/lib/middleman-core/rack.rb index 4578005b..390728b4 100644 --- a/middleman-core/lib/middleman-core/rack.rb +++ b/middleman-core/lib/middleman-core/rack.rb @@ -138,7 +138,7 @@ module Middleman response[1]['Content-Encoding'] = 'gzip' if %w(.svgz .gz).include?(resource.ext) # Do not set Content-Type if status is 1xx, 204, 205 or 304, otherwise # Rack will throw an error (500) - if !(100..199).include?(status) && ![204, 205, 304].include?(status) + if !(100..199).cover?(status) && ![204, 205, 304].include?(status) response[1]['Content-Type'] = resource.content_type || 'application/octet-stream' end halt response diff --git a/middleman-core/lib/middleman-core/renderers/kramdown.rb b/middleman-core/lib/middleman-core/renderers/kramdown.rb index 86317560..adf623d1 100644 --- a/middleman-core/lib/middleman-core/renderers/kramdown.rb +++ b/middleman-core/lib/middleman-core/renderers/kramdown.rb @@ -35,7 +35,7 @@ module Middleman def convert_a(el, indent) content = inner(el, indent) - if el.attr['href'] =~ /\Amailto:/ + if el.attr['href'].start_with?('mailto:') mail_addr = el.attr['href'].sub(/\Amailto:/, '') href = obfuscate('mailto') << ':' << obfuscate(mail_addr) content = obfuscate(content) if content == mail_addr diff --git a/middleman-core/lib/middleman-core/renderers/less.rb b/middleman-core/lib/middleman-core/renderers/less.rb index 715033e7..7830b137 100644 --- a/middleman-core/lib/middleman-core/renderers/less.rb +++ b/middleman-core/lib/middleman-core/renderers/less.rb @@ -26,7 +26,7 @@ module Middleman if ::Less.const_defined? :Engine @engine = ::Less::Engine.new(data) else - parser = ::Less::Parser.new(options.merge filename: eval_file, line: line, paths: ['.', File.dirname(eval_file)]) + parser = ::Less::Parser.new(options.merge(filename: eval_file, line: line, paths: ['.', File.dirname(eval_file)])) @engine = parser.parse(data) end end diff --git a/middleman-core/lib/middleman-core/renderers/redcarpet.rb b/middleman-core/lib/middleman-core/renderers/redcarpet.rb index 545a3c87..122de759 100644 --- a/middleman-core/lib/middleman-core/renderers/redcarpet.rb +++ b/middleman-core/lib/middleman-core/renderers/redcarpet.rb @@ -8,7 +8,7 @@ module Middleman # in the wrong direction ALIASES = { escape_html: :filter_html - } + }.freeze def initialize(*args, &block) super diff --git a/middleman-core/lib/middleman-core/renderers/sass.rb b/middleman-core/lib/middleman-core/renderers/sass.rb index f71f8a9d..b17acaf8 100644 --- a/middleman-core/lib/middleman-core/renderers/sass.rb +++ b/middleman-core/lib/middleman-core/renderers/sass.rb @@ -1,11 +1,9 @@ require 'sass' - module Middleman module Renderers # Sass renderer class Sass < ::Middleman::Extension - opts = { output_style: :nested } opts[:line_comments] = false if ENV['TEST'] define_setting :sass, opts, 'Sass engine options' diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index dfd513c2..beba7d7a 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -23,9 +23,9 @@ module Middleman # Ignore based on the source path (without template extensions) if ignored?(r.path) r.ignore! - else + elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor[:relative_path].to_s) # This allows files to be ignored by their source file name (with template extensions) - r.ignore! if !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor[:relative_path].to_s) + r.ignore! end r diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb index 63b06e13..eba04a44 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb @@ -23,14 +23,14 @@ module Middleman resources + ::Middleman::Util.glob_directory(File.join(from, '**/*')) .reject { |path| File.directory?(path) } .map do |path| - target_path = Pathname(path).relative_path_from(Pathname(from).parent).to_s + target_path = Pathname(path).relative_path_from(Pathname(from).parent).to_s - ::Middleman::Sitemap::Resource.new( - app.sitemap, - renameProc.call(target_path, path), - path - ) - end + ::Middleman::Sitemap::Resource.new( + app.sitemap, + renameProc.call(target_path, path), + path + ) + end end end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb index ca0b7895..33c0f9a5 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -113,7 +113,7 @@ module Middleman def to_s "#<#{self.class} path=#{@path} target=#{@target}>" end - alias_method :inspect, :to_s + alias inspect to_s end end end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb b/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb index 47ffd726..48ede6a0 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb @@ -28,7 +28,7 @@ module Middleman # Setup a redirect from a path to a target # @param [String] path # @param [Hash] opts The :to value gives a target path - Contract String, ({ to: Or[String, ::Middleman::Sitemap::Resource] }), Maybe[Proc] => RedirectDescriptor + Contract String, { to: Or[String, ::Middleman::Sitemap::Resource] }, Maybe[Proc] => RedirectDescriptor def redirect(path, opts={}, &block) RedirectDescriptor.new(path, opts[:to], block_given? ? block : nil) end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb b/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb index 2b456df8..e2bdfc7e 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb @@ -44,14 +44,14 @@ module Middleman def children return [] unless directory_index? - if eponymous_directory? - base_path = eponymous_directory_path - prefix = %r{^#{base_path.sub("/", "\\/")}} + base_path = if eponymous_directory? + eponymous_directory_path else - base_path = path.sub("#{@app.config[:index_file]}", '') - prefix = %r{^#{base_path.sub("/", "\\/")}} + path.sub(@app.config[:index_file].to_s, '') end + prefix = %r{^#{base_path.sub("/", "\\/")}} + @store.resources.select do |sub_resource| if sub_resource.path == path || sub_resource.path !~ prefix false diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index ceb7bb7f..380b7faf 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -29,9 +29,9 @@ module Middleman # The path to use when requesting this resource. Normally it's # the same as {#destination_path} but it can be overridden in subclasses. # @return [String] - alias_method :request_path, :destination_path + alias request_path destination_path - METADATA_HASH = ({ options: Maybe[Hash], locals: Maybe[Hash], page: Maybe[Hash] }) + METADATA_HASH = { options: Maybe[Hash], locals: Maybe[Hash], page: Maybe[Hash] }.freeze # The metadata for this resource # @return [Hash] @@ -53,10 +53,10 @@ module Middleman source = Pathname(source) if source && source.is_a?(String) - if source && source.is_a?(Pathname) - @file_descriptor = ::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir), source, @app.source_dir, Set.new([:source])) + @file_descriptor = if source && source.is_a?(Pathname) + ::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir), source, @app.source_dir, Set.new([:source])) else - @file_descriptor = source + source end @destination_path = @path @@ -130,16 +130,16 @@ module Middleman return ::Middleman::FileRenderer.new(@app, file_descriptor[:full_path].to_s).template_data_for_file unless template? # ::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) - locs[:current_path] ||= destination_path + md = metadata + opts = md[:options].deep_merge(opts) + locs = md[:locals].deep_merge(locs) + locs[:current_path] ||= destination_path - # Certain output file types don't use layouts - opts[:layout] = false if !opts.key?(:layout) && ext != '.html' + # Certain output file types don't use layouts + opts[:layout] = false if !opts.key?(:layout) && ext != '.html' - renderer = ::Middleman::TemplateRenderer.new(@app, file_descriptor[:full_path].to_s) - renderer.render(locs, opts) + renderer = ::Middleman::TemplateRenderer.new(@app, file_descriptor[:full_path].to_s) + renderer.render(locs, opts) # end end @@ -189,7 +189,7 @@ module Middleman def to_s "#<#{self.class} path=#{@path}>" end - alias_method :inspect, :to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s + alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s end class StringResource < Resource diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index 4d938cac..41037309 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -201,7 +201,7 @@ module Middleman @lock.synchronize do return unless @needs_sitemap_rebuild - ::Middleman::Util.instrument "sitemap.update", reasons: @rebuild_reasons.uniq do + ::Middleman::Util.instrument 'sitemap.update', reasons: @rebuild_reasons.uniq do @needs_sitemap_rebuild = false @app.logger.debug '== Rebuilding resource list' @@ -209,7 +209,7 @@ module Middleman @resources = [] @resource_list_manipulators.each do |m| - ::Middleman::Util.instrument "sitemap.manipulator", name: m[:name] do + ::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) diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 44c3e316..4b01d578 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -15,10 +15,10 @@ module Middleman include Contracts # Types which could cause output to change. - OUTPUT_TYPES = [:source, :locales, :data] + OUTPUT_TYPES = [:source, :locales, :data].freeze # Types which require a reload to eval ruby - CODE_TYPES = [:reload] + CODE_TYPES = [:reload].freeze Matcher = Or[Regexp, RespondTo[:call]] @@ -257,11 +257,11 @@ module Middleman # # @param [nil,Regexp] matcher A Regexp to match the change path against Contract Maybe[Matcher] => Any - def changed(matcher=nil, &block) + def changed(matcher=nil, &_block) on_change OUTPUT_TYPES do |updated, _removed| updated .select { |f| matcher.nil? ? true : matches?(matcher, f) } - .each { |f| block.call(f[:relative_path]) } + .each { |f| yield f[:relative_path] } end end @@ -269,11 +269,11 @@ module Middleman # # @param [nil,Regexp] matcher A Regexp to match the change path against Contract Maybe[Matcher] => Any - def deleted(matcher=nil, &block) + def deleted(matcher=nil, &_block) on_change OUTPUT_TYPES do |_updated, removed| removed .select { |f| matcher.nil? ? true : matches?(matcher, f) } - .each { |f| block.call(f[:relative_path]) } + .each { |f| yield f[:relative_path] } end end diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 6d667db0..43efdb21 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -202,7 +202,7 @@ module Middleman def to_s "#" end - alias_method :inspect, :to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s + alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s protected @@ -256,10 +256,10 @@ module Middleman end execute_callbacks(:on_change, [ - valid_updates, - valid_removes, - self - ]) unless valid_updates.empty? && valid_removes.empty? + valid_updates, + valid_removes, + self + ]) unless valid_updates.empty? && valid_removes.empty? end def add_file_to_cache(f) diff --git a/middleman-core/lib/middleman-core/template_context.rb b/middleman-core/lib/middleman-core/template_context.rb index f424c2b1..8bc8d9bc 100644 --- a/middleman-core/lib/middleman-core/template_context.rb +++ b/middleman-core/lib/middleman-core/template_context.rb @@ -162,7 +162,7 @@ module Middleman return nil unless current_path sitemap.find_resource_by_destination_path(current_path) end - alias_method :current_page, :current_resource + alias current_page current_resource protected diff --git a/middleman-core/lib/middleman-core/template_renderer.rb b/middleman-core/lib/middleman-core/template_renderer.rb index 3f6d729b..4af4ce14 100644 --- a/middleman-core/lib/middleman-core/template_renderer.rb +++ b/middleman-core/lib/middleman-core/template_renderer.rb @@ -28,6 +28,75 @@ module Middleman @_cache ||= Cache.new end + # Find a layout on-disk, optionally using a specific engine + # @param [String] name + # @param [Symbol] preferred_engine + # @return [String] + Contract IsA['Middleman::Application'], Or[String, Symbol], Symbol => Maybe[IsA['Middleman::SourceFile']] + def self.locate_layout(app, name, preferred_engine=nil) + resolve_opts = {} + resolve_opts[:preferred_engine] = preferred_engine unless preferred_engine.nil? + + # Check layouts folder + layout_file = resolve_template(app, File.join(app.config[:layouts_dir], name.to_s), resolve_opts) + + # If we didn't find it, check root + layout_file = resolve_template(app, name, resolve_opts) unless layout_file + + # Return the path + layout_file + end + + # Find a template on disk given a output path + # @param [String] request_path + # @option options [Boolean] :preferred_engine If set, try this engine first, then fall back to any engine. + # @return [String, Boolean] Either the path to the template, or false + Contract IsA['Middleman::Application'], Or[Symbol, String], Maybe[Hash] => Maybe[IsA['Middleman::SourceFile']] + def self.resolve_template(app, request_path, options={}) + # Find the path by searching + relative_path = Util.strip_leading_slash(request_path.to_s) + + # By default, any engine will do + preferred_engines = [] + + # If we're specifically looking for a preferred engine + if options.key?(:preferred_engine) + extension_class = ::Tilt[options[:preferred_engine]] + + # Get a list of extensions for a preferred engine + preferred_engines += ::Tilt.mappings.select do |_, engines| + engines.include? extension_class + end.keys + end + + preferred_engines << '*' + preferred_engines << nil if options[:try_static] + + found_template = nil + + preferred_engines.each do |preferred_engine| + path_with_ext = relative_path.dup + path_with_ext << ('.' + preferred_engine) unless preferred_engine.nil? + + globbing = preferred_engine == '*' + + # Cache lookups in build mode only + file = if app.build? + cache.fetch(path_with_ext, preferred_engine) do + app.files.find(:source, path_with_ext, globbing) + end + else + app.files.find(:source, path_with_ext, globbing) + end + + found_template = file if file && (preferred_engine.nil? || ::Tilt[file[:full_path]]) + break if found_template + end + + # If we found one, return it + found_template + end + # Custom error class for handling class TemplateNotFound < RuntimeError; end @@ -132,14 +201,13 @@ module Middleman # Look for :layout of any extension # If found, use it. If not, continue locate_layout(:layout, layout_engine) - else + elsif layout_file = locate_layout(local_layout, layout_engine) # Look for specific layout # If found, use it. If not, error. - if layout_file = locate_layout(local_layout, layout_engine) - layout_file - else - raise ::Middleman::TemplateRenderer::TemplateNotFound, "Could not locate layout: #{local_layout}" - end + + layout_file + else + raise ::Middleman::TemplateRenderer::TemplateNotFound, "Could not locate layout: #{local_layout}" end end @@ -152,25 +220,6 @@ module Middleman self.class.locate_layout(@app, name, preferred_engine) end - # Find a layout on-disk, optionally using a specific engine - # @param [String] name - # @param [Symbol] preferred_engine - # @return [String] - Contract IsA['Middleman::Application'], Or[String, Symbol], Symbol => Maybe[IsA['Middleman::SourceFile']] - def self.locate_layout(app, name, preferred_engine=nil) - resolve_opts = {} - resolve_opts[:preferred_engine] = preferred_engine unless preferred_engine.nil? - - # Check layouts folder - layout_file = resolve_template(app, File.join(app.config[:layouts_dir], name.to_s), resolve_opts) - - # If we didn't find it, check root - layout_file = resolve_template(app, name, resolve_opts) unless layout_file - - # Return the path - layout_file - end - # Find a template on disk given a output path # @param [String] request_path # @param [Hash] options @@ -179,55 +228,5 @@ module Middleman def resolve_template(request_path, options={}) self.class.resolve_template(@app, request_path, options) end - - # Find a template on disk given a output path - # @param [String] request_path - # @option options [Boolean] :preferred_engine If set, try this engine first, then fall back to any engine. - # @return [String, Boolean] Either the path to the template, or false - Contract IsA['Middleman::Application'], Or[Symbol, String], Maybe[Hash] => Maybe[IsA['Middleman::SourceFile']] - def self.resolve_template(app, request_path, options={}) - # Find the path by searching - relative_path = Util.strip_leading_slash(request_path.to_s) - - # By default, any engine will do - preferred_engines = [] - - # If we're specifically looking for a preferred engine - if options.key?(:preferred_engine) - extension_class = ::Tilt[options[:preferred_engine]] - - # Get a list of extensions for a preferred engine - preferred_engines += ::Tilt.mappings.select do |_, engines| - engines.include? extension_class - end.keys - end - - preferred_engines << '*' - preferred_engines << nil if options[:try_static] - - found_template = nil - - preferred_engines.each do |preferred_engine| - path_with_ext = relative_path.dup - path_with_ext << ('.' + preferred_engine) unless preferred_engine.nil? - - globbing = preferred_engine == '*' - - # Cache lookups in build mode only - file = if app.build? - cache.fetch(path_with_ext, preferred_engine) do - app.files.find(:source, path_with_ext, globbing) - end - else - app.files.find(:source, path_with_ext, globbing) - end - - found_template = file if file && (preferred_engine.nil? || ::Tilt[file[:full_path]]) - break if found_template - end - - # If we found one, return it - found_template - end end end diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index ec6b1854..d3683115 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -153,7 +153,7 @@ module Middleman all_files_under(child, &ignore) end.compact elsif path.file? - if block_given? && ignore.call(path) + if block_given? && yield(path) [] else [path] @@ -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 = block.call(asset_path)) + if uri.relative? && uri.host.nil? && (result = yield asset_path) "#{opening_character}#{result}" else match @@ -488,7 +488,7 @@ module Middleman types = Set.new([type]) relative_path = path.relative_path_from(directory) - relative_path = File.join(destination_dir, relative_path) if destination_dir + relative_path = File.join(destination_dir, relative_path) if destination_dir ::Middleman::SourceFile.new(Pathname(relative_path), path, directory, types) end diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index be0be167..0eb4f451 100644 --- a/middleman-core/lib/middleman-core/version.rb +++ b/middleman-core/lib/middleman-core/version.rb @@ -1,5 +1,5 @@ module Middleman # Current Version # @return [String] - VERSION = '4.1.0.rc.1' unless const_defined?(:VERSION) + VERSION = '4.1.0.rc.1'.freeze unless const_defined?(:VERSION) end diff --git a/middleman/Rakefile b/middleman/Rakefile index 034f3633..793455ab 100644 --- a/middleman/Rakefile +++ b/middleman/Rakefile @@ -1,4 +1,4 @@ # coding:utf-8 -RAKE_ROOT = __FILE__ -GEM_NAME = 'middleman' +RAKE_ROOT = __FILE__.freeze +GEM_NAME = 'middleman'.freeze require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper') From ff9c34bca91db881effc79fec5d06781f7f3af90 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 14 Jan 2016 14:02:33 -0800 Subject: [PATCH 003/140] Allow sorting of rewriters. Fixes #1752 --- middleman-core/features/asset_hash.feature | 40 ++++++++++++++++++- .../fixtures/asset-hash-host-app/config.rb | 4 -- .../asset-hash-host-app/source/index.html.erb | 2 +- .../core_extensions/inline_url_rewriter.rb | 14 +++++-- .../middleman-core/extensions/asset_hash.rb | 3 +- 5 files changed, 53 insertions(+), 10 deletions(-) delete mode 100644 middleman-core/fixtures/asset-hash-host-app/config.rb diff --git a/middleman-core/features/asset_hash.feature b/middleman-core/features/asset_hash.feature index 751b9e30..7d23ae6b 100644 --- a/middleman-core/features/asset_hash.feature +++ b/middleman-core/features/asset_hash.feature @@ -107,7 +107,45 @@ Feature: Assets get file hashes appended to them and references to them are upda And I should see 'src="images/100px-5fd6fb90.jpg"' And I should see 'srcset="images/100px-5fd6fb90.jpg 1x, images/200px-c11eb203.jpg 2x, images/300px-59adce76.jpg 3x"' - Scenario: Enabling an asset host still produces hashed files and references + Scenario: Enabling an asset host still produces hashed files and references (hash first) + Given a fixture app "asset-hash-host-app" + And a file named "config.rb" with: + """ + activate :asset_hash + activate :directory_indexes + activate :asset_host, host: 'http://middlemanapp.com' + """ + Given the Server is running at "asset-hash-host-app" + When I go to "/" + 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-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-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-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")' + And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg#test")' + + Scenario: Enabling an asset host still produces hashed files and references (host first) + Given a fixture app "asset-hash-host-app" + And a file named "config.rb" with: + """ + activate :asset_host, host: 'http://middlemanapp.com' + activate :directory_indexes + activate :asset_hash + """ Given the Server is running at "asset-hash-host-app" When I go to "/" Then I should see 'href="http://middlemanapp.com/stylesheets/site-4b64a653.css"' diff --git a/middleman-core/fixtures/asset-hash-host-app/config.rb b/middleman-core/fixtures/asset-hash-host-app/config.rb deleted file mode 100644 index 085caeb7..00000000 --- a/middleman-core/fixtures/asset-hash-host-app/config.rb +++ /dev/null @@ -1,4 +0,0 @@ - -activate :asset_hash -activate :directory_indexes -activate :asset_host, host: 'http://middlemanapp.com' diff --git a/middleman-core/fixtures/asset-hash-host-app/source/index.html.erb b/middleman-core/fixtures/asset-hash-host-app/source/index.html.erb index ea81c790..c9fefc2a 100644 --- a/middleman-core/fixtures/asset-hash-host-app/source/index.html.erb +++ b/middleman-core/fixtures/asset-hash-host-app/source/index.html.erb @@ -3,7 +3,7 @@ <% end %>

Image url:

-<%= image_tag('100px.jpg') %> + <%= image_tag('100px.jpg?test') %> <%= image_tag('100px.jpg?#test') %> <%= image_tag('100px.jpg#test') %> diff --git a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb index a7f7e778..7d42b667 100644 --- a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb @@ -17,7 +17,8 @@ module Middleman proc: Or[Proc, Method], url_extensions: ArrayOf[String], source_extensions: ArrayOf[String], - ignore: ArrayOf[IGNORE_DESCRIPTOR] + ignore: ArrayOf[IGNORE_DESCRIPTOR], + after: Maybe[Symbol] }.freeze def initialize(app, options_hash={}, &block) @@ -32,8 +33,15 @@ module Middleman end def after_configuration - app.use Rack, rewriters: @rewriters.values, - middleman_app: @app + rewriters = @rewriters.values.sort do |a, b| + if b[:after] && b[:after] == a[:id] + 1 + else + 0 + end + end + + app.use Rack, rewriters: rewriters, middleman_app: @app end class Rack diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index 7122eb10..ac464b69 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -22,7 +22,8 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension source_extensions: options.sources, ignore: @ignore, rewrite_ignore: options.rewrite_ignore, - proc: method(:rewrite_url) + proc: method(:rewrite_url), + after: :asset_host end Contract String, Or[String, Pathname], Any => Maybe[String] From be2788b6ca61b246699e1a0bb91c00f055b5e43b Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 14 Jan 2016 14:14:50 -0800 Subject: [PATCH 004/140] Fix automatic images with absolute (or images dir missing) paths in markdown. Fixes #1755 --- .../features/automatic_image_sizes.feature | 23 +++++++++++++++---- .../source/markdown-sizes.html.markdown | 1 + .../extensions/automatic_image_sizes.rb | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 middleman-core/fixtures/automatic-image-size-app/source/markdown-sizes.html.markdown diff --git a/middleman-core/features/automatic_image_sizes.feature b/middleman-core/features/automatic_image_sizes.feature index 89f9d7a5..50a0b02e 100644 --- a/middleman-core/features/automatic_image_sizes.feature +++ b/middleman-core/features/automatic_image_sizes.feature @@ -2,15 +2,28 @@ Feature: Automatically detect and insert image dimensions into tags In order to speed up development and appease YSlow Scenario: Rendering an image with the feature disabled - Given "automatic_image_sizes" feature is "disabled" + Given a fixture app "automatic-image-size-app" + And a file named "config.rb" with: + """ + """ And the Server is running at "automatic-image-size-app" When I go to "/auto-image-sizes.html" Then I should not see "width=" And I should not see "height=" - + When I go to "/markdown-sizes.html" + Then I should not see "width=" + And I should not see "height=" + Scenario: Rendering an image with the feature enabled - Given "automatic_image_sizes" feature is "enabled" + Given a fixture app "automatic-image-size-app" + And a file named "config.rb" with: + """ + activate :automatic_image_sizes + """ And the Server is running at "automatic-image-size-app" When I go to "/auto-image-sizes.html" - Then I should see "width=" - And I should see "height=" \ No newline at end of file + Then I should see 'width="1"' + And I should see 'height="1"' + When I go to "/markdown-sizes.html" + Then I should see 'width="1"' + And I should see 'height="1"' diff --git a/middleman-core/fixtures/automatic-image-size-app/source/markdown-sizes.html.markdown b/middleman-core/fixtures/automatic-image-size-app/source/markdown-sizes.html.markdown new file mode 100644 index 00000000..1f9c8dcd --- /dev/null +++ b/middleman-core/fixtures/automatic-image-size-app/source/markdown-sizes.html.markdown @@ -0,0 +1 @@ +![Alt text](/images/blank.gif) diff --git a/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb b/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb index b88721de..5bd0f14d 100644 --- a/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb +++ b/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb @@ -19,7 +19,7 @@ class Middleman::Extensions::AutomaticImageSizes < ::Middleman::Extension real_path = path.dup real_path = File.join(config[:images_dir], real_path) unless real_path.start_with?('/') - file = app.files.find(:source, real_path) + file = app.files.find(:source, real_path) || app.files.find(:source, real_path.gsub(/^\//, '')) if file && file[:full_path].exist? begin From a47b2138f8c88f5a2a817e50a31f6b4054e73d11 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 14 Jan 2016 14:29:45 -0800 Subject: [PATCH 005/140] Add specific check for TLD-like strings when replacing inline urls. Fixes #1751 --- middleman-core/features/asset_host.feature | 1 + .../fixtures/asset-host-app/source/asset_host.html.erb | 9 +++++++++ middleman-core/lib/middleman-core/util.rb | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/middleman-core/features/asset_host.feature b/middleman-core/features/asset_host.feature index d223b997..4cd733aa 100644 --- a/middleman-core/features/asset_host.feature +++ b/middleman-core/features/asset_host.feature @@ -8,6 +8,7 @@ Feature: Alternate between multiple asset hosts """ And the Server is running When I go to "/asset_host.html" + Then I should see "'.google-analytics.com/ga.js'" Then I should see 'src="https://code.jquery.com/jquery-2.1.3.min.js"' Then I should see content matching %r{http://assets1.example.com/} Then I should not see content matching %r{http://assets1.example.com//} diff --git a/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb b/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb index 30843176..25f4a9d9 100755 --- a/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb +++ b/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb @@ -44,3 +44,12 @@ Angular.js + + diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index d3683115..b5d9af71 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -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? && !asset_path.match(/^[^\/].*[a-z]+\.[a-z]+\/.*/) && (result = yield(asset_path)) "#{opening_character}#{result}" else match From 5529062bc4a2fb3e37976ac423b5cac8976290c5 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 14 Jan 2016 14:31:00 -0800 Subject: [PATCH 006/140] Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49440d94..d497c96a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ master * Add `skip_build_clean` config which when set to a block, will avoid removing non-generated paths from build, like .git #1716 * Minor performance improvements * DRY-up config.rb-specific commands like `ignore` or `path`. +* Fix automatic images with absolute (or images dir missing) paths in markdown. Fixes #1755 +* Fix asset_host in combination with Google Analytics snippet. #1751 # 4.0.0 From 03c95f086320c67a4fd16afd398d5b12de3542fa Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 14 Jan 2016 14:48:40 -0800 Subject: [PATCH 007/140] prep --- middleman-core/lib/middleman-core/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index 0eb4f451..dbe053e0 100644 --- a/middleman-core/lib/middleman-core/version.rb +++ b/middleman-core/lib/middleman-core/version.rb @@ -1,5 +1,5 @@ module Middleman # Current Version # @return [String] - VERSION = '4.1.0.rc.1'.freeze unless const_defined?(:VERSION) + VERSION = '4.1.0.rc.2'.freeze unless const_defined?(:VERSION) end From dc3eac9e96dc76c7fabc6e663494ee0194009d9e Mon Sep 17 00:00:00 2001 From: Jim Dalton Date: Sat, 16 Jan 2016 11:58:00 -0800 Subject: [PATCH 008/140] Use correct type for removed paths passed to update --- middleman-core/lib/middleman-core/sources/source_watcher.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 43efdb21..1af9370c 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -91,7 +91,7 @@ module Middleman stop_listener! if @listener - update([], @files.values) + update([], @files.values.map { |source_file| source_file[:full_path] }) poll_once! @@ -262,11 +262,13 @@ module Middleman ]) unless valid_updates.empty? && valid_removes.empty? end + Contract IsA['Middleman::SourceFile'] => Any def add_file_to_cache(f) @files[f[:full_path]] = f @extensionless_files[strip_extensions(f[:full_path])] = f end + Contract IsA['Middleman::SourceFile'] => Any def remove_file_from_cache(f) @files.delete(f[:full_path]) @extensionless_files.delete(strip_extensions(f[:full_path])) From 22812cb340501a272dcd7041918c47332d55c5e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhamatti=20Niemel=C3=A4?= Date: Mon, 18 Jan 2016 19:55:45 +0200 Subject: [PATCH 009/140] Fix gzip extension status output --- middleman-core/lib/middleman-core/extensions/gzip.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/extensions/gzip.rb b/middleman-core/lib/middleman-core/extensions/gzip.rb index cc1a7fea..12079ab5 100644 --- a/middleman-core/lib/middleman-core/extensions/gzip.rb +++ b/middleman-core/lib/middleman-core/extensions/gzip.rb @@ -64,10 +64,10 @@ class Middleman::Extensions::Gzip < ::Middleman::Extension total_savings += (old_size - new_size) size_change_word = (old_size - new_size) > 0 ? 'smaller' : 'larger' - builder.trigger :gzip, "#{output_filename} (#{NumberHelpers.new.number_to_human_size((old_size - new_size).abs)} #{size_change_word})" + builder.trigger :created, "#{output_filename} (#{NumberHelpers.new.number_to_human_size((old_size - new_size).abs)} #{size_change_word})" end - builder.trigger :gzip, "Total gzip savings: #{NumberHelpers.new.number_to_human_size(total_savings)}" + builder.trigger :gzip, '', "Total gzip savings: #{NumberHelpers.new.number_to_human_size(total_savings)}" I18n.locale = old_locale end From 7bf4e4681f1839701190b65f262a4d1a0d009cdc Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 19 Jan 2016 09:42:49 -0800 Subject: [PATCH 010/140] Show an error message when git CLI is not available. Closes #1765 --- CHANGELOG.md | 1 + middleman-cli/lib/middleman-cli/init.rb | 35 ++++++++++++++++++++++-- middleman-core/features/cli_init.feature | 7 +++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d497c96a..b98569ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ master * DRY-up config.rb-specific commands like `ignore` or `path`. * Fix automatic images with absolute (or images dir missing) paths in markdown. Fixes #1755 * Fix asset_host in combination with Google Analytics snippet. #1751 +* Show an error message when git CLI is not available. #1765 # 4.0.0 diff --git a/middleman-cli/lib/middleman-cli/init.rb b/middleman-cli/lib/middleman-cli/init.rb index 469d9d4c..86e2ef91 100644 --- a/middleman-cli/lib/middleman-cli/init.rb +++ b/middleman-cli/lib/middleman-cli/init.rb @@ -4,6 +4,8 @@ module Middleman::Cli class Init < Thor::Group include Thor::Actions + GIT_CMD = 'git' + check_unknown_options! argument :target, type: :string, default: '.' @@ -25,6 +27,13 @@ module Middleman::Cli require 'fileutils' require 'tmpdir' + if !git_present? + msg = "You need to install the git command line tool to initialize a new project. " + msg << "For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git" + say msg, :red + exit 1 + end + repo_path, repo_branch = if shortname?(options[:template]) require 'open-uri' require 'json' @@ -51,10 +60,11 @@ module Middleman::Cli begin branch_cmd = repo_branch ? "-b #{repo_branch} " : '' - run("git clone --depth 1 #{branch_cmd}#{repo_path} #{dir}") + git_path = "#{branch_cmd}#{repo_path}" + run("#{GIT_CMD} clone --depth 1 #{branch_cmd}#{repo_path} #{dir}") - unless File.directory?(dir) - say 'Git clone failed, maybe the url is invalid or you don\'t have the permissions?', :red + if !$?.success? + say "Git clone command failed. Make sure git repository exists: #{git_path}", :red exit 1 end @@ -79,6 +89,25 @@ module Middleman::Cli protected + # Copied from Bundler + def git_present? + return @git_present if defined?(@git_present) + @git_present = which(GIT_CMD) || which("git.exe") + end + + # Copied from Bundler + def which(executable) + if File.file?(executable) && File.executable?(executable) + executable + elsif ENV['PATH'] + path = ENV['PATH'].split(File::PATH_SEPARATOR).find do |p| + abs_path = File.join(p, executable) + File.file?(abs_path) && File.executable?(abs_path) + end + path && File.expand_path(executable, path) + end + end + def shortname?(repo) repo.split('/').length == 1 end diff --git a/middleman-core/features/cli_init.feature b/middleman-core/features/cli_init.feature index 52aa8f7b..8591d1be 100644 --- a/middleman-core/features/cli_init.feature +++ b/middleman-core/features/cli_init.feature @@ -63,6 +63,13 @@ Feature: Middleman CLI And the file "Gemfile" should contain "middleman-blog" And the file ".gitignore" should exist + Scenario: Create an invalid project using Middleman directory + When I run `middleman init MY_PROJECT -T does-not-exist-for-reals` + Then a directory named "MY_PROJECT" should exist + When I cd to "MY_PROJECT" + And the file "Gemfile" should contain "middleman-blog" + And the file ".gitignore" should exist + Scenario: Create a new project using github(user/repository) When I run `middleman init MY_PROJECT -T middleman/middleman-templates-default` interactively And I type "y" From 2b88773640fc5c2fd75d06aa010181de86cfada6 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 19 Jan 2016 09:44:56 -0800 Subject: [PATCH 011/140] Fix contract in i18n. Closes #1764 --- middleman-core/lib/middleman-core/core_extensions/i18n.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/i18n.rb b/middleman-core/lib/middleman-core/core_extensions/i18n.rb index b2476796..4b2f35b4 100644 --- a/middleman-core/lib/middleman-core/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-core/core_extensions/i18n.rb @@ -190,7 +190,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension end end - Contract String, Symbol => String + Contract String, Symbol => Maybe[String] def localized_path(path, locale) lookup_path = path.dup lookup_path << app.config[:index_file] if lookup_path.end_with?('/') From 801a83f7cb42ed2cc4c6e846ca035121c67d53a0 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 19 Jan 2016 09:46:55 -0800 Subject: [PATCH 012/140] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b98569ff..6e9ce31c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ master * Fix automatic images with absolute (or images dir missing) paths in markdown. Fixes #1755 * Fix asset_host in combination with Google Analytics snippet. #1751 * Show an error message when git CLI is not available. #1765 +* Correctly show file names of GZIP'ed assets. #1364 # 4.0.0 From 65aebc1887502e99aa21565de6ddd753bd8aa873 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 19 Jan 2016 14:55:47 -0800 Subject: [PATCH 013/140] Move some tests around --- middleman-cli/features/.gitkeep | 0 .../features/cli_extension.feature | 0 .../features/cli_init.feature | 5 +---- .../features}/preview_server-hook.feature | 0 .../features}/preview_server.feature | 0 middleman-cli/features/support/env.rb | 19 +++++++++++++++++++ middleman-cli/fixtures/.gitkeep | 0 .../preview-server-app/bin/dns_server.rb | 0 .../fixtures/preview-server-app/config.rb | 0 .../preview-server-app/source/index.html.erb | 0 .../preview-server-app/source/layout.erb | 0 .../source/layouts/custom.erb | 0 .../preview-server-app/source/real.html | 0 .../source/real/index.html.erb | 0 .../source/should_be_ignored.html | 0 .../source/should_be_ignored2.html | 0 .../source/should_be_ignored3.html | 0 .../preview-server-app/source/static.html | 0 .../preview-server-hook-app/config.rb | 0 .../source/index.html.erb | 0 middleman-cli/lib/middleman-cli/init.rb | 10 +++++----- 21 files changed, 25 insertions(+), 9 deletions(-) delete mode 100644 middleman-cli/features/.gitkeep rename {middleman-core => middleman-cli}/features/cli_extension.feature (100%) rename {middleman-core => middleman-cli}/features/cli_init.feature (94%) rename {middleman-core/features/cli => middleman-cli/features}/preview_server-hook.feature (100%) rename {middleman-core/features/cli => middleman-cli/features}/preview_server.feature (100%) create mode 100644 middleman-cli/features/support/env.rb delete mode 100644 middleman-cli/fixtures/.gitkeep rename {middleman-core => middleman-cli}/fixtures/preview-server-app/bin/dns_server.rb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/config.rb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/index.html.erb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/layout.erb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/layouts/custom.erb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/real.html (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/real/index.html.erb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/should_be_ignored.html (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/should_be_ignored2.html (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/should_be_ignored3.html (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-app/source/static.html (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-hook-app/config.rb (100%) rename {middleman-core => middleman-cli}/fixtures/preview-server-hook-app/source/index.html.erb (100%) diff --git a/middleman-cli/features/.gitkeep b/middleman-cli/features/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/middleman-core/features/cli_extension.feature b/middleman-cli/features/cli_extension.feature similarity index 100% rename from middleman-core/features/cli_extension.feature rename to middleman-cli/features/cli_extension.feature diff --git a/middleman-core/features/cli_init.feature b/middleman-cli/features/cli_init.feature similarity index 94% rename from middleman-core/features/cli_init.feature rename to middleman-cli/features/cli_init.feature index 8591d1be..96595422 100644 --- a/middleman-core/features/cli_init.feature +++ b/middleman-cli/features/cli_init.feature @@ -65,10 +65,7 @@ Feature: Middleman CLI Scenario: Create an invalid project using Middleman directory When I run `middleman init MY_PROJECT -T does-not-exist-for-reals` - Then a directory named "MY_PROJECT" should exist - When I cd to "MY_PROJECT" - And the file "Gemfile" should contain "middleman-blog" - And the file ".gitignore" should exist + Then the exit status should be 1 Scenario: Create a new project using github(user/repository) When I run `middleman init MY_PROJECT -T middleman/middleman-templates-default` interactively diff --git a/middleman-core/features/cli/preview_server-hook.feature b/middleman-cli/features/preview_server-hook.feature similarity index 100% rename from middleman-core/features/cli/preview_server-hook.feature rename to middleman-cli/features/preview_server-hook.feature diff --git a/middleman-core/features/cli/preview_server.feature b/middleman-cli/features/preview_server.feature similarity index 100% rename from middleman-core/features/cli/preview_server.feature rename to middleman-cli/features/preview_server.feature diff --git a/middleman-cli/features/support/env.rb b/middleman-cli/features/support/env.rb new file mode 100644 index 00000000..8044deab --- /dev/null +++ b/middleman-cli/features/support/env.rb @@ -0,0 +1,19 @@ +ENV["TEST"] = "true" + +require 'sassc' + +require 'simplecov' +SimpleCov.root(File.expand_path(File.dirname(__FILE__) + '/../..')) + +require 'phantomjs/poltergeist' +Capybara.javascript_driver = :poltergeist + +require 'coveralls' +Coveralls.wear! + +require 'codeclimate-test-reporter' +CodeClimate::TestReporter.start + +PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__))) +require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman-cli') +require File.join(File.dirname(PROJECT_ROOT_PATH), 'middleman-core', 'lib', 'middleman-core', 'step_definitions') diff --git a/middleman-cli/fixtures/.gitkeep b/middleman-cli/fixtures/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/middleman-core/fixtures/preview-server-app/bin/dns_server.rb b/middleman-cli/fixtures/preview-server-app/bin/dns_server.rb similarity index 100% rename from middleman-core/fixtures/preview-server-app/bin/dns_server.rb rename to middleman-cli/fixtures/preview-server-app/bin/dns_server.rb diff --git a/middleman-core/fixtures/preview-server-app/config.rb b/middleman-cli/fixtures/preview-server-app/config.rb similarity index 100% rename from middleman-core/fixtures/preview-server-app/config.rb rename to middleman-cli/fixtures/preview-server-app/config.rb diff --git a/middleman-core/fixtures/preview-server-app/source/index.html.erb b/middleman-cli/fixtures/preview-server-app/source/index.html.erb similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/index.html.erb rename to middleman-cli/fixtures/preview-server-app/source/index.html.erb diff --git a/middleman-core/fixtures/preview-server-app/source/layout.erb b/middleman-cli/fixtures/preview-server-app/source/layout.erb similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/layout.erb rename to middleman-cli/fixtures/preview-server-app/source/layout.erb diff --git a/middleman-core/fixtures/preview-server-app/source/layouts/custom.erb b/middleman-cli/fixtures/preview-server-app/source/layouts/custom.erb similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/layouts/custom.erb rename to middleman-cli/fixtures/preview-server-app/source/layouts/custom.erb diff --git a/middleman-core/fixtures/preview-server-app/source/real.html b/middleman-cli/fixtures/preview-server-app/source/real.html similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/real.html rename to middleman-cli/fixtures/preview-server-app/source/real.html diff --git a/middleman-core/fixtures/preview-server-app/source/real/index.html.erb b/middleman-cli/fixtures/preview-server-app/source/real/index.html.erb similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/real/index.html.erb rename to middleman-cli/fixtures/preview-server-app/source/real/index.html.erb diff --git a/middleman-core/fixtures/preview-server-app/source/should_be_ignored.html b/middleman-cli/fixtures/preview-server-app/source/should_be_ignored.html similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/should_be_ignored.html rename to middleman-cli/fixtures/preview-server-app/source/should_be_ignored.html diff --git a/middleman-core/fixtures/preview-server-app/source/should_be_ignored2.html b/middleman-cli/fixtures/preview-server-app/source/should_be_ignored2.html similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/should_be_ignored2.html rename to middleman-cli/fixtures/preview-server-app/source/should_be_ignored2.html diff --git a/middleman-core/fixtures/preview-server-app/source/should_be_ignored3.html b/middleman-cli/fixtures/preview-server-app/source/should_be_ignored3.html similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/should_be_ignored3.html rename to middleman-cli/fixtures/preview-server-app/source/should_be_ignored3.html diff --git a/middleman-core/fixtures/preview-server-app/source/static.html b/middleman-cli/fixtures/preview-server-app/source/static.html similarity index 100% rename from middleman-core/fixtures/preview-server-app/source/static.html rename to middleman-cli/fixtures/preview-server-app/source/static.html diff --git a/middleman-core/fixtures/preview-server-hook-app/config.rb b/middleman-cli/fixtures/preview-server-hook-app/config.rb similarity index 100% rename from middleman-core/fixtures/preview-server-hook-app/config.rb rename to middleman-cli/fixtures/preview-server-hook-app/config.rb diff --git a/middleman-core/fixtures/preview-server-hook-app/source/index.html.erb b/middleman-cli/fixtures/preview-server-hook-app/source/index.html.erb similarity index 100% rename from middleman-core/fixtures/preview-server-hook-app/source/index.html.erb rename to middleman-cli/fixtures/preview-server-hook-app/source/index.html.erb diff --git a/middleman-cli/lib/middleman-cli/init.rb b/middleman-cli/lib/middleman-cli/init.rb index 86e2ef91..f1c1927e 100644 --- a/middleman-cli/lib/middleman-cli/init.rb +++ b/middleman-cli/lib/middleman-cli/init.rb @@ -4,7 +4,7 @@ module Middleman::Cli class Init < Thor::Group include Thor::Actions - GIT_CMD = 'git' + GIT_CMD = 'git'.freeze check_unknown_options! @@ -27,8 +27,8 @@ module Middleman::Cli require 'fileutils' require 'tmpdir' - if !git_present? - msg = "You need to install the git command line tool to initialize a new project. " + unless git_present? + msg = 'You need to install the git command line tool to initialize a new project. ' msg << "For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git" say msg, :red exit 1 @@ -63,7 +63,7 @@ module Middleman::Cli git_path = "#{branch_cmd}#{repo_path}" run("#{GIT_CMD} clone --depth 1 #{branch_cmd}#{repo_path} #{dir}") - if !$?.success? + unless $?.success? say "Git clone command failed. Make sure git repository exists: #{git_path}", :red exit 1 end @@ -92,7 +92,7 @@ module Middleman::Cli # Copied from Bundler def git_present? return @git_present if defined?(@git_present) - @git_present = which(GIT_CMD) || which("git.exe") + @git_present = which(GIT_CMD) || which('git.exe') end # Copied from Bundler From 6077ae43e94a3c74fe1a00d2c3d01116f3990457 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 19 Jan 2016 15:35:37 -0800 Subject: [PATCH 014/140] rejigger cop --- .rubocop.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index bf44c2f8..63819945 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,10 +10,13 @@ AllCops: - '**/tmp/**/*' - '**/bin/**/*' - 'middleman-core/lib/middleman-core/step_definitions/**/*' - - 'middleman-cli/lib/middleman-cli/templates/**/*' - 'middleman-core/fixtures/**/*' - 'middleman-core/features/**/*' - 'middleman-core/spec/**/*' + - 'middleman-cli/lib/middleman-cli/templates/**/*' + - 'middleman-cli/fixtures/**/*' + - 'middleman-cli/features/**/*' + - 'middleman-cli/spec/**/*' DoubleNegation: Enabled: false LineLength: From 2864902fa04131f6b76a87c7482d2a1f4156015a Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 20 Jan 2016 10:02:19 -0800 Subject: [PATCH 015/140] Fix #1767 --- .../lib/middleman-core/preview_server.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 93934478..ce127b5f 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -163,14 +163,16 @@ module Middleman path: root, only: match_against - # Hack around node_modules in root. - watcher.listener.ignore(/^node_modules/) + unless config[:watcher_disable] + # Hack around node_modules in root. + watcher.listener.ignore(/^node_modules/) - # Hack around sass cache in root. - watcher.listener.ignore(/^\.sass-cache/) + # Hack around sass cache in root. + watcher.listener.ignore(/^\.sass-cache/) - # Hack around bundler cache in root. - watcher.listener.ignore(/^vendor\/bundle/) + # Hack around bundler cache in root. + watcher.listener.ignore(/^vendor\/bundle/) + end end end From 827d5fbb1db096a5af08335bfa9e86ec0a9160b0 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 20 Jan 2016 10:41:54 -0800 Subject: [PATCH 016/140] Still parse frontmatter on ignored resources. Proxies need it --- middleman-core/lib/middleman-core/application.rb | 6 ------ .../lib/middleman-core/core_extensions/front_matter.rb | 7 ++++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 6915d51e..38c2baf4 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -184,12 +184,6 @@ module Middleman end }, 'Callbacks that can exclude paths from the sitemap' - # Set textual delimiters that denote the start and end of frontmatter - define_setting :frontmatter_delims, { - json: [%w(;;; ;;;)], - yaml: [%w(--- ---), %w(--- ...)] - }, 'Allowed frontmatter delimiters' - define_setting :skip_build_clean, proc { |p| [/\.git/].any? { |r| r.match(p) } }, 'Whether some paths should not be removed during a clean build.' define_setting :watcher_disable, false, 'If the Listen watcher should not run' diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index ffde6b19..ea3f38af 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -14,6 +14,12 @@ module Middleman::CoreExtensions # Try to run after routing but before directory_indexes self.resource_list_manipulator_priority = 20 + # Set textual delimiters that denote the start and end of frontmatter + define_setting :frontmatter_delims, { + json: [%w(;;; ;;;)], + yaml: [%w(--- ---), %w(--- ...)] + }, 'Allowed frontmatter delimiters' + def initialize(app, options_hash={}, &block) super @@ -29,7 +35,6 @@ module Middleman::CoreExtensions def manipulate_resource_list(resources) resources.each do |resource| next if resource.binary? - next if resource.ignored? next if resource.file_descriptor.nil? fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup From ffa662a917aa7d605a5272d068623bf5e26e0799 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 20 Jan 2016 11:50:25 -0800 Subject: [PATCH 017/140] Add system-wide file read cache --- middleman-core/features/import_files.feature | 2 - .../frontmatter-neighbor-app/config.rb | 2 +- .../config.rb | 2 +- .../middleman-core/core_extensions/data.rb | 4 +- .../core_extensions/front_matter.rb | 6 ++- .../lib/middleman-core/file_renderer.rb | 9 ++-- .../lib/middleman-core/preview_server.rb | 4 +- .../lib/middleman-core/renderers/liquid.rb | 2 +- .../lib/middleman-core/sitemap/resource.rb | 2 +- middleman-core/lib/middleman-core/sources.rb | 17 ++++++-- .../middleman-core/sources/source_watcher.rb | 30 +++++++++---- .../lib/middleman-core/template_context.rb | 2 +- middleman-core/lib/middleman-core/util.rb | 42 ++++++++----------- .../lib/middleman-core/util/data.rb | 7 ++-- 14 files changed, 76 insertions(+), 55 deletions(-) diff --git a/middleman-core/features/import_files.feature b/middleman-core/features/import_files.feature index b45f1256..faaf2039 100644 --- a/middleman-core/features/import_files.feature +++ b/middleman-core/features/import_files.feature @@ -13,5 +13,3 @@ Feature: Import files Then I should see 'jQuery' When I go to "/bower_components2/jquery/dist/jquery.js" Then I should see 'jQuery' - - diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb index 6fa6e37c..019d65f7 100644 --- a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb +++ b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb @@ -15,7 +15,7 @@ class NeighborFrontmatter < ::Middleman::Extension next unless file - fmdata = ::Middleman::Util::Data.parse(file[:full_path], app.config[:frontmatter_delims], :yaml).first + fmdata = ::Middleman::Util::Data.parse(file, app.config[:frontmatter_delims], :yaml).first opts = fmdata.extract!(:layout, :layout_engine, :renderer_options, :directory_index, :content_type) opts[:renderer_options].symbolize_keys! if opts.key?(:renderer_options) ignored = fmdata.delete(:ignored) diff --git a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb index a7e0fc55..7adbe389 100644 --- a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb +++ b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb @@ -26,7 +26,7 @@ class NeighborFrontmatter < ::Middleman::Extension end def apply_neighbor_data(resource, file) - fmdata = ::Middleman::Util::Data.parse(file[:full_path], app.config[:frontmatter_delims], :yaml).first + fmdata = ::Middleman::Util::Data.parse(file, app.config[:frontmatter_delims], :yaml).first opts = fmdata.extract!(:layout, :layout_engine, :renderer_options, :directory_index, :content_type) opts[:renderer_options].symbolize_keys! if opts.key?(:renderer_options) ignored = fmdata.delete(:ignored) diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index dca657ac..22fdd4a2 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -100,10 +100,10 @@ module Middleman basename = File.basename(data_path, extension) if %w(.yaml .yml).include?(extension) - data, postscript = ::Middleman::Util::Data.parse(file[:full_path], @app.config[:frontmatter_delims], :yaml) + data, postscript = ::Middleman::Util::Data.parse(file, @app.config[:frontmatter_delims], :yaml) data[:postscript] = postscript if !postscript.nil? && data.is_a?(Hash) elsif extension == '.json' - data, _postscript = ::Middleman::Util::Data.parse(file[:full_path], @app.config[:frontmatter_delims], :json) + data, _postscript = ::Middleman::Util::Data.parse(file, @app.config[:frontmatter_delims], :json) else return end diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index ea3f38af..8809004f 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -72,8 +72,10 @@ module Middleman::CoreExtensions return [{}, nil] unless file - @cache[file[:full_path]] ||= ::Middleman::Util::Data.parse( - file[:full_path], + return @cache[file[:full_path]] if @cache.key?(file[:full_path]) + + @cache[file[:full_path]] = ::Middleman::Util::Data.parse( + file, app.config[:frontmatter_delims] ) end diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index 09c6b5d2..3f385ed6 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -97,11 +97,12 @@ module Middleman Contract String def template_data_for_file if @app.extensions[:front_matter] - @app.extensions[:front_matter].template_data_for_file(@path) || File.read(@path) - else - file = @app.files.find(:source, @path) - file.read if file + result = @app.extensions[:front_matter].template_data_for_file(@path) + return result unless result.nil? end + + file = @app.files.find(:source, @path) + file ? file.read : File.read(@path) end protected diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index ce127b5f..acdb367d 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -235,8 +235,8 @@ module Middleman if ssl_certificate || ssl_private_key raise 'You must provide both :ssl_certificate and :ssl_private_key' unless ssl_private_key && ssl_certificate - http_opts[:SSLCertificate] = OpenSSL::X509::Certificate.new File.read ssl_certificate - http_opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new File.read ssl_private_key + http_opts[:SSLCertificate] = OpenSSL::X509::Certificate.new ::File.read ssl_certificate + http_opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new ::File.read ssl_private_key else # use a generated self-signed cert http_opts[:SSLCertName] = [ diff --git a/middleman-core/lib/middleman-core/renderers/liquid.rb b/middleman-core/lib/middleman-core/renderers/liquid.rb index c50258a9..e58528ed 100644 --- a/middleman-core/lib/middleman-core/renderers/liquid.rb +++ b/middleman-core/lib/middleman-core/renderers/liquid.rb @@ -14,7 +14,7 @@ module Middleman def read_template_file(template_path, _) file = app.files.find(:source, "_#{template_path}.liquid") raise ::Liquid::FileSystemError, "No such template '#{template_path}'" unless file - File.read(file[:full_path]) + file.read end # @return Array diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 380b7faf..adb36cfe 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -54,7 +54,7 @@ module Middleman source = Pathname(source) if source && source.is_a?(String) @file_descriptor = if source && source.is_a?(Pathname) - ::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir), source, @app.source_dir, Set.new([:source])) + ::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir), source, @app.source_dir, Set.new([:source]), 0) else source end diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 4b01d578..267a8069 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -3,7 +3,12 @@ require 'middleman-core/contracts' module Middleman # The standard "record" that contains information about a file on disk. - SourceFile = Struct.new :relative_path, :full_path, :directory, :types + SourceFile = Struct.new(:relative_path, :full_path, :directory, :types, :version) do + def read + ::Middleman::Sources.file_cache[full_path] ||= {} + ::Middleman::Sources.file_cache[full_path][version] ||= ::File.read(full_path) + end + end # Sources handle multiple on-disk collections of files which make up # a Middleman project. They are separated by `type` which can then be @@ -36,6 +41,8 @@ module Middleman # Reference to the global logger. def_delegator :@app, :logger + cattr_accessor :file_cache + # Built-in types # :source, :data, :locales, :reload @@ -50,6 +57,8 @@ module Middleman @watchers = watchers @sorted_watchers = @watchers.dup.freeze + ::Middleman::Sources.file_cache = {} + @options = options # Set of procs wanting to be notified of changes @@ -177,9 +186,10 @@ module Middleman # @return [Middleman::SourceFile, nil] Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String, Maybe[Bool] => Maybe[SourceFile] def find(types, path, glob=false) + array_of_types = Array(types) + watchers - .lazy - .select { |d| Array(types).include?(d.type) } + .select { |d| array_of_types.include?(d.type) } .map { |d| d.find(path, glob) } .reject(&:nil?) .first @@ -193,7 +203,6 @@ module Middleman Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String => Bool def exists?(types, path) watchers - .lazy .select { |d| Array(types).include?(d.type) } .any? { |d| d.exists?(path) } end diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 1af9370c..84c1506b 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -228,11 +228,11 @@ module Middleman Contract ArrayOf[Pathname], ArrayOf[Pathname] => Any def update(updated_paths, removed_paths) valid_updates = updated_paths - .map { |p| ::Middleman::Util.path_to_source_file(p, @directory, @type, @options.fetch(:destination_dir, false)) } + .map { |p| @files[p] || path_to_source_file(p, @directory, @type, @options[:destination_dir]) } .select(&method(:valid?)) valid_updates.each do |f| - add_file_to_cache(f) + record_file_change(f) logger.debug "== Change (#{f[:types].inspect}): #{f[:relative_path]}" end @@ -245,11 +245,9 @@ module Middleman valid_updates |= related_updates valid_removes = removed_paths - .lazy .select(&@files.method(:key?)) .map(&@files.method(:[])) .select(&method(:valid?)) - .to_a .each do |f| remove_file_from_cache(f) logger.debug "== Deletion (#{f[:types].inspect}): #{f[:relative_path]}" @@ -262,10 +260,28 @@ module Middleman ]) unless valid_updates.empty? && valid_removes.empty? end + # Convert a path to a file resprentation. + # + # @param [Pathname] path The path. + # @return [Middleman::SourceFile] + Contract Pathname, Pathname, Symbol, Maybe[String] => ::Middleman::SourceFile + def path_to_source_file(path, directory, type, destination_dir) + types = Set.new([type]) + + relative_path = path.relative_path_from(directory) + relative_path = File.join(destination_dir, relative_path) if destination_dir + + ::Middleman::SourceFile.new(Pathname(relative_path), path, directory, types, 0) + end + Contract IsA['Middleman::SourceFile'] => Any - def add_file_to_cache(f) - @files[f[:full_path]] = f - @extensionless_files[strip_extensions(f[:full_path])] = f + def record_file_change(f) + if @files[f[:full_path]] + @files[f[:full_path]][:version] += 1 + else + @files[f[:full_path]] = f + @extensionless_files[strip_extensions(f[:full_path])] = f + end end Contract IsA['Middleman::SourceFile'] => Any diff --git a/middleman-core/lib/middleman-core/template_context.rb b/middleman-core/lib/middleman-core/template_context.rb index 8bc8d9bc..8d7fd784 100644 --- a/middleman-core/lib/middleman-core/template_context.rb +++ b/middleman-core/lib/middleman-core/template_context.rb @@ -110,7 +110,7 @@ module Middleman r = sitemap.find_resource_by_path(source_path) if (r && !r.template?) || (Tilt[partial_file[:full_path]].nil? && partial_file[:full_path].exist?) - File.read(partial_file[:full_path]) + partial_file.read else opts = options.dup locs = opts.delete(:locals) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index b5d9af71..db1238b2 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -35,20 +35,28 @@ module Middleman # @return [Boolean] Contract Or[String, Pathname] => Bool def binary?(filename) - path = Pathname(filename) - ext = path.extname + @@binary_cache ||= {} - # We hardcode detecting of gzipped SVG files - return true if ext == '.svgz' + return @@binary_cache[filename] if @@binary_cache.key?(filename) - return false if Tilt.registered?(ext.sub('.', '')) + @@binary_cache[filename] = begin + path = Pathname(filename) + ext = path.extname - dot_ext = (ext.to_s[0] == '.') ? ext.dup : ".#{ext}" + # We hardcode detecting of gzipped SVG files + if ext == '.svgz' + true + elsif Tilt.registered?(ext.sub('.', '')) + false + else + dot_ext = (ext.to_s[0] == '.') ? ext.dup : ".#{ext}" - if mime = ::Rack::Mime.mime_type(dot_ext, nil) - !nonbinary_mime?(mime) - else - file_contents_include_binary_bytes?(path.to_s) + if mime = ::Rack::Mime.mime_type(dot_ext, nil) + !nonbinary_mime?(mime) + else + file_contents_include_binary_bytes?(path.to_s) + end + end end end @@ -479,20 +487,6 @@ module Middleman result end - # Convert a path to a file resprentation. - # - # @param [Pathname] path The path. - # @return [Middleman::SourceFile] - Contract Pathname, Pathname, Symbol, Bool => ::Middleman::SourceFile - def path_to_source_file(path, directory, type, destination_dir) - types = Set.new([type]) - - relative_path = path.relative_path_from(directory) - relative_path = File.join(destination_dir, relative_path) if destination_dir - - ::Middleman::SourceFile.new(Pathname(relative_path), path, directory, types) - end - # Finds files which should also be considered to be dirty when # the given file(s) are touched. # diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb index 6670f989..246ae2e1 100644 --- a/middleman-core/lib/middleman-core/util/data.rb +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -15,13 +15,14 @@ module Middleman # Get the frontmatter and plain content from a file # @param [String] path # @return [Array] - Contract Pathname, Maybe[Symbol] => [Hash, Maybe[String]] - def parse(full_path, frontmatter_delims, known_type=nil) + Contract IsA['Middleman::SourceFile'], Maybe[Symbol] => [Hash, Maybe[String]] + def parse(file, frontmatter_delims, known_type=nil) + full_path = file[:full_path] return [{}, nil] if ::Middleman::Util.binary?(full_path) # Avoid weird race condition when a file is renamed begin - content = File.read(full_path) + content = file.read rescue EOFError, IOError, Errno::ENOENT return [{}, nil] end From 6d1c3562a705d06b4f8e09276dc12a10c80c76b4 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 20 Jan 2016 12:20:27 -0800 Subject: [PATCH 018/140] Differentiate polling from find_new_files to remove double reads in build mode --- .../core_extensions/file_watcher.rb | 4 ++-- middleman-core/lib/middleman-core/sources.rb | 15 +++++++++++++-- .../lib/middleman-core/sources/source_watcher.rb | 11 +++++++++++ .../step_definitions/middleman_steps.rb | 4 ++-- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb index b5769b86..82df8f73 100644 --- a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb +++ b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb @@ -47,7 +47,7 @@ module Middleman # @return [void] Contract Any def before_configuration - @sources.find_new_files! + @sources.poll_once! end # After we config, find new files since config can change paths. @@ -60,7 +60,7 @@ module Middleman end @sources.start! - @sources.find_new_files! + @sources.poll_once! end protected diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 267a8069..7114d9f0 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -91,7 +91,7 @@ module Middleman validator: (block_given? ? block : regex)) bump_count - find_new_files! if @running + poll_once! if @running end # Whether this path is ignored. @@ -219,13 +219,24 @@ module Middleman .find { |d| d.exists?(path) } end - # Manually poll all watchers for new content. + # Manually check for new files # # @return [void] Contract ArrayOf[Pathname] def find_new_files! return [] unless @update_count != @last_update_count + @last_update_count = @update_count + watchers.reduce([]) { |sum, w| sum + w.find_new_files! } + end + + # Manually poll all watchers for new content. + # + # @return [void] + Contract ArrayOf[Pathname] + def poll_once! + return [] unless @update_count != @last_update_count + @last_update_count = @update_count watchers.reduce([]) { |sum, w| sum + w.poll_once! } end diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 84c1506b..70f749b0 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -1,6 +1,7 @@ # Watcher Library require 'listen' require 'middleman-core/contracts' +require 'digest' # Monkey patch Listen silencer so `only` works on directories too module Listen @@ -177,6 +178,16 @@ module Middleman @listener = nil end + Contract ArrayOf[Pathname] + def find_new_files! + new_files = ::Middleman::Util.all_files_under(@directory.to_s) + .reject { |p| @files.key?(p) } + + update(new_files, []) + + new_files + end + # Manually trigger update events. # # @return [void] diff --git a/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb b/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb index 63236a10..35a4a681 100644 --- a/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb @@ -31,13 +31,13 @@ end Then /^the file "([^\"]*)" has the contents$/ do |path, contents| write_file(path, contents) - @server_inst.files.find_new_files! + @server_inst.files.poll_once! end Then /^the file "([^\"]*)" is removed$/ do |path| step %Q{I remove the file "#{path}"} - @server_inst.files.find_new_files! + @server_inst.files.poll_once! end Given /^a modification time for a file named "([^\"]*)"$/ do |file| From 5586784947b5426ea360ce8b9ca9b50142c4b583 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 20 Jan 2016 13:34:12 -0800 Subject: [PATCH 019/140] Add some options to watcher to opt out of features later --- .../lib/middleman-core/contracts.rb | 115 ++++++++++++++++-- .../core_extensions/front_matter.rb | 6 + .../extensions/external_pipeline.rb | 3 +- .../lib/middleman-core/file_renderer.rb | 5 +- .../sitemap/extensions/ignores.rb | 4 +- .../sitemap/extensions/import.rb | 4 +- .../lib/middleman-core/sitemap/resource.rb | 2 +- .../middleman-core/sources/source_watcher.rb | 6 +- .../lib/middleman-core/util/data.rb | 2 +- 9 files changed, 125 insertions(+), 22 deletions(-) diff --git a/middleman-core/lib/middleman-core/contracts.rb b/middleman-core/lib/middleman-core/contracts.rb index e99d0d59..55aa0aad 100644 --- a/middleman-core/lib/middleman-core/contracts.rb +++ b/middleman-core/lib/middleman-core/contracts.rb @@ -1,23 +1,112 @@ -require 'contracts' -require 'hamster' +if ENV['CONTRACTS'] != 'false' + require 'contracts' + require 'hamster' -module Contracts - class IsA - def self.[](val) - @lookup ||= {} - @lookup[val] ||= new(val) + module Contracts + class IsA + def self.[](val) + @lookup ||= {} + @lookup[val] ||= new(val) + end + + def initialize(val) + @val = val + end + + def valid?(val) + val.is_a? @val.constantize + end end - def initialize(val) - @val = val + VectorOf = Contracts::CollectionOf::Factory.new(::Hamster::Vector) + ResourceList = Contracts::ArrayOf[IsA['Middleman::Sitemap::Resource']] + end +else + module Contracts + def self.included(base) + base.extend self end - def valid?(val) - val.is_a? @val.constantize + # rubocop:disable MethodName + def Contract(*) + end + + class Callable + def self.[](*) + end + end + + class Bool + end + + class Num + end + + class Pos + end + + class Neg + end + + class Any + end + + class None + end + + class Or < Callable + end + + class Xor < Callable + end + + class And < Callable + end + + class Not < Callable + end + + class RespondTo < Callable + end + + class Send < Callable + end + + class Exactly < Callable + end + + class ArrayOf < Callable + end + + class ResourceList < Callable + end + + class Args < Callable + end + + class HashOf < Callable + end + + class Bool + end + + class Maybe < Callable + end + + class IsA < Callable + end + + class SetOf < Callable + end + + class Frozen < Callable + end + + class VectorOf < Callable end end +end - VectorOf = ::Contracts::CollectionOf::Factory.new(::Hamster::Vector) - ResourceList = ::Contracts::ArrayOf[IsA['Middleman::Sitemap::Resource']] +module Contracts PATH_MATCHER = Or[String, RespondTo[:match], RespondTo[:call], RespondTo[:to_s]] end diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index 8809004f..a59f7bb1 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -36,6 +36,7 @@ module Middleman::CoreExtensions resources.each do |resource| next if resource.binary? next if resource.file_descriptor.nil? + next if resource.file_descriptor[:types].include?(:no_frontmatter) fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup @@ -74,6 +75,11 @@ module Middleman::CoreExtensions return @cache[file[:full_path]] if @cache.key?(file[:full_path]) + if file[:types].include?(:no_frontmatter) + $stderr.puts file[:relative_path].to_s + require 'pry' + end + @cache[file[:full_path]] = ::Middleman::Util::Data.parse( file, app.config[:frontmatter_delims] diff --git a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb index 44a4e6b3..6b51d944 100644 --- a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb +++ b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb @@ -14,7 +14,8 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension @watcher = app.files.watch :source, path: File.expand_path(options[:source], app.root), - latency: options[:latency] + latency: options[:latency], + frontmatter: false logger.info "== Executing: `#{options[:command]}`" diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index 3f385ed6..67f9411f 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -96,12 +96,13 @@ module Middleman # @return [String] Contract String def template_data_for_file - if @app.extensions[:front_matter] + file = @app.files.find(:source, @path) + + if @app.extensions[:front_matter] || (file && !file[:types].include?(:no_frontmatter)) result = @app.extensions[:front_matter].template_data_for_file(@path) return result unless result.nil? end - file = @app.files.find(:source, @path) file ? file.read : File.read(@path) end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index beba7d7a..dfa80304 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -11,7 +11,7 @@ module Middleman # Ignore a path or add an ignore callback # @param [String, Regexp] path Path glob expression, or path regex # @return [IgnoreDescriptor] - Contract Maybe[Or[String, Regexp]], Maybe[Proc] => RespondTo[:execute_descriptor] + Contract Or[String, Regexp, Proc] => RespondTo[:execute_descriptor] def ignore(path=nil, &block) @app.sitemap.invalidate_resources_not_ignored_cache! IgnoreDescriptor.new(path, block) @@ -49,7 +49,7 @@ module Middleman else match_path == path_clean end - elsif block_given? + elsif block block.call(match_path) end end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb index eba04a44..239aa917 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb @@ -12,8 +12,10 @@ module Middleman ImportFileDescriptor = Struct.new(:from, :to) do def execute_descriptor(app, resources) + source = ::Middleman::SourceFile.new(Pathname(from).relative_path_from(app.source_dir), Pathname(from), app.source_dir, Set.new([:source, :binary]), 0) + resources + [ - ::Middleman::Sitemap::Resource.new(app.sitemap, to, from) + ::Middleman::Sitemap::Resource.new(app.sitemap, to, source) ] end end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index adb36cfe..b1f614e4 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -161,7 +161,7 @@ module Middleman # @return [Boolean] Contract Bool def binary? - !file_descriptor.nil? && ::Middleman::Util.binary?(file_descriptor[:full_path].to_s) + !file_descriptor.nil? && (file_descriptor[:types].include?(:binary) || ::Middleman::Util.binary?(file_descriptor[:full_path].to_s)) end # Ignore a resource directly, without going through the whole diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 70f749b0..328afb9e 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -66,6 +66,8 @@ module Middleman @files = {} @extensionless_files = {} + @frontmatter = options.fetch(:frontmatter, true) + @binary = options.fetch(:binary, false) @validator = options.fetch(:validator, proc { true }) @ignored = options.fetch(:ignored, proc { false }) @only = Array(options.fetch(:only, [])) @@ -181,7 +183,7 @@ module Middleman Contract ArrayOf[Pathname] def find_new_files! new_files = ::Middleman::Util.all_files_under(@directory.to_s) - .reject { |p| @files.key?(p) } + .reject { |p| @files.key?(p) } update(new_files, []) @@ -278,6 +280,8 @@ module Middleman Contract Pathname, Pathname, Symbol, Maybe[String] => ::Middleman::SourceFile def path_to_source_file(path, directory, type, destination_dir) types = Set.new([type]) + types << :no_frontmatter unless @frontmatter + types << :@binary if @binary relative_path = path.relative_path_from(directory) relative_path = File.join(destination_dir, relative_path) if destination_dir diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb index 246ae2e1..c18e6975 100644 --- a/middleman-core/lib/middleman-core/util/data.rb +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -18,7 +18,7 @@ module Middleman Contract IsA['Middleman::SourceFile'], Maybe[Symbol] => [Hash, Maybe[String]] def parse(file, frontmatter_delims, known_type=nil) full_path = file[:full_path] - return [{}, nil] if ::Middleman::Util.binary?(full_path) + return [{}, nil] if ::Middleman::Util.binary?(full_path) || file[:types].include?(:binary) # Avoid weird race condition when a file is renamed begin From 68127003b90003993ada0e49106c844e6f2594c8 Mon Sep 17 00:00:00 2001 From: Jim Dalton Date: Wed, 20 Jan 2016 21:11:03 -0800 Subject: [PATCH 020/140] Add option for MM_DATA_DIR env var to define :data_dir default value --- middleman-core/lib/middleman-core/core_extensions/data.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index 22fdd4a2..5f2a789f 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -8,7 +8,7 @@ module Middleman class Data < Extension attr_reader :data_store - define_setting :data_dir, 'data', 'The directory data files are stored in' + define_setting :data_dir, ENV['MM_DATA_DIR'] || 'data', 'The directory data files are stored in' # Make the internal `data_store` method available as `app.data` expose_to_application data: :data_store From 92d96f6604249a662b5cd685bb8c48c567bf6790 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 21 Jan 2016 10:19:52 -0800 Subject: [PATCH 021/140] typo --- middleman-core/lib/middleman-core/sources/source_watcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 328afb9e..0c7356c2 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -281,7 +281,7 @@ module Middleman def path_to_source_file(path, directory, type, destination_dir) types = Set.new([type]) types << :no_frontmatter unless @frontmatter - types << :@binary if @binary + types << :binary if @binary relative_path = path.relative_path_from(directory) relative_path = File.join(destination_dir, relative_path) if destination_dir From 4e8273295bc4fb9d5f22958ce270c75c0167578c Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 21 Jan 2016 10:50:44 -0800 Subject: [PATCH 022/140] tweak some checksums, something slightly changed file output upstream --- .rubocop.yml | 2 + middleman-core/features/asset_hash.feature | 62 +++++++++---------- .../lib/middleman-core/renderers/sass.rb | 5 ++ middleman-core/lib/middleman-core/util.rb | 6 +- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 63819945..0145ceef 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -67,3 +67,5 @@ Style/BlockDelimiters: Enabled: false Style/MultilineBlockChain: Enabled: false +Style/SpecialGlobalVars: + Enabled: false diff --git a/middleman-core/features/asset_hash.feature b/middleman-core/features/asset_hash.feature index 7d23ae6b..3098e73c 100644 --- a/middleman-core/features/asset_hash.feature +++ b/middleman-core/features/asset_hash.feature @@ -63,8 +63,8 @@ Feature: Assets get file hashes appended to them and references to them are upda Given the Server is running at "asset-hash-app" When I go to "/" Then I should see 'href="apple-touch-icon.png"' - And I should see 'href="stylesheets/site-d2959d87.css"' - And I should see 'href="stylesheets/fragment-a06f0dfc.css"' + And I should see 'href="stylesheets/site-d1a750ca.css"' + And I should see 'href="stylesheets/fragment-99b76247.css"' And I should see 'src="javascripts/application-1d8d5276.js"' And I should see 'src="images/100px-5fd6fb90.jpg"' And I should see 'srcset="images/100px-5fd6fb90.jpg 1x, images/200px-c11eb203.jpg 2x, images/300px-59adce76.jpg 3x"' @@ -72,11 +72,11 @@ Feature: Assets get file hashes appended to them and references to them are upda And I should see 'src="images/100px-5fd6fb90.jpg?#test"' And I should see 'src="images/100px-5fd6fb90.jpg#test"' When I go to "/subdir/" - Then I should see 'href="../stylesheets/site-d2959d87.css"' + Then I should see 'href="../stylesheets/site-d1a750ca.css"' And I should see 'src="../javascripts/application-1d8d5276.js"' And I should see 'src="../images/100px-5fd6fb90.jpg"' When I go to "/other/" - Then I should see 'href="../stylesheets/site-d2959d87.css"' + Then I should see 'href="../stylesheets/site-d1a750ca.css"' And I should see 'src="../javascripts/application-1d8d5276.js"' And I should see 'src="../images/100px-5fd6fb90.jpg"' And I should see 'src="../images/100px-5fd6fb90.jpg?test"' @@ -84,8 +84,8 @@ Feature: Assets get file hashes appended to them and references to them are upda And I should see 'src="../images/100px-5fd6fb90.jpg#test"' When I go to "/javascripts/application-1d8d5276.js" Then I should see "img.src = '/images/100px-5fd6fb90.jpg'" - When I go to "/stylesheets/site-d2959d87.css" - Then I should see 'background-image: url("../images/100px-5fd6fb90.jpg")' + When I go to "/stylesheets/site-d1a750ca.css" + Then I should see 'background-image: url("../images/100px-5fd6fb90.jpg");' When I go to "/api.json" Then I should see 'images/100px-5fd6fb90.gif' And I should see 'images/100px-5fd6fb90.jpg' @@ -94,11 +94,11 @@ Feature: Assets get file hashes appended to them and references to them are upda Then I should see 'images/100px-5fd6fb90.gif' And I should see 'images/100px-5fd6fb90.jpg' And I should see 'images/100px-1242c368.png' - When I go to "/stylesheets/fragment-a06f0dfc.css" - And I should see 'url("../images/100px-5fd6fb90.jpg")' - And I should see 'url("../images/100px-5fd6fb90.jpg?test")' - And I should see 'url("../images/100px-5fd6fb90.jpg?#test")' - And I should see 'url("../images/100px-5fd6fb90.jpg#test")' + When I go to "/stylesheets/fragment-99b76247.css" + And I should see 'url("../images/100px-5fd6fb90.jpg");' + And I should see 'url("../images/100px-5fd6fb90.jpg?test");' + And I should see 'url("../images/100px-5fd6fb90.jpg?#test");' + And I should see 'url("../images/100px-5fd6fb90.jpg#test");' Scenario: Hashed assets work with Slim Given the Server is running at "asset-hash-app" @@ -117,26 +117,26 @@ Feature: Assets get file hashes appended to them and references to them are upda """ Given the Server is running at "asset-hash-host-app" When I go to "/" - Then I should see 'href="http://middlemanapp.com/stylesheets/site-4b64a653.css"' - Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-a772891f.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-7000b132.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-4b64a653.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.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-4b64a653.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.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-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")' - And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg#test")' + When I go to "/stylesheets/fragment-7000b132.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");' + And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg#test");' Scenario: Enabling an asset host still produces hashed files and references (host first) Given a fixture app "asset-hash-host-app" @@ -148,22 +148,22 @@ Feature: Assets get file hashes appended to them and references to them are upda """ Given the Server is running at "asset-hash-host-app" When I go to "/" - Then I should see 'href="http://middlemanapp.com/stylesheets/site-4b64a653.css"' - Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-a772891f.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-7000b132.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-4b64a653.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.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-4b64a653.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.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-a772891f.css" + When I go to "/stylesheets/fragment-7000b132.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")' @@ -177,14 +177,14 @@ Feature: Assets get file hashes appended to them and references to them are upda font-size: 14px """ When I go to "/partials/" - Then I should see 'href="../stylesheets/uses_partials-44fb2764.css' + Then I should see 'href="../stylesheets/uses_partials-4d4e34e6.css' And the file "source/stylesheets/_partial.sass" has the contents """ body font-size: 18px !important """ When I go to "/partials/" - Then I should see 'href="../stylesheets/uses_partials-10d8ae33.css' + Then I should see 'href="../stylesheets/uses_partials-ec347271.css' Scenario: The asset hash should change when a Rack-based filter changes Given a fixture app "asset-hash-app" @@ -198,12 +198,10 @@ Feature: Assets get file hashes appended to them and references to them are upda """ Given the Server is running at "asset-hash-app" When I go to "/" - Then I should see 'href="stylesheets/site-30784643.css' - When I go to "stylesheets/site-30784643.css" - Then I should see 'background-image' + Then I should see 'href="stylesheets/site-5ad7def0.css' + When I go to "stylesheets/site-5ad7def0.css" + Then I should see 'background-image: url("../images/100px-5fd6fb90.jpg")' Then I should see 'Added by Rack filter' - When I go to "stylesheets/site-7474cadd.css" - Then I should see 'Not Found' Scenario: Hashed-asset files are not produced for ignored paths Given a fixture app "asset-hash-app" diff --git a/middleman-core/lib/middleman-core/renderers/sass.rb b/middleman-core/lib/middleman-core/renderers/sass.rb index b17acaf8..abd44502 100644 --- a/middleman-core/lib/middleman-core/renderers/sass.rb +++ b/middleman-core/lib/middleman-core/renderers/sass.rb @@ -1,5 +1,10 @@ require 'sass' +begin + require 'sassc' +rescue LoadError +end + module Middleman module Renderers # Sass renderer diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index db1238b2..ae15e3ec 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -35,11 +35,11 @@ module Middleman # @return [Boolean] Contract Or[String, Pathname] => Bool def binary?(filename) - @@binary_cache ||= {} + @binary_cache ||= {} - return @@binary_cache[filename] if @@binary_cache.key?(filename) + return @binary_cache[filename] if @binary_cache.key?(filename) - @@binary_cache[filename] = begin + @binary_cache[filename] = begin path = Pathname(filename) ext = path.extname From e0818e2118d286270c1244470526d12c3235499f Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 21 Jan 2016 14:47:45 -0800 Subject: [PATCH 023/140] remove debug code --- .../lib/middleman-core/core_extensions/front_matter.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index a59f7bb1..49f4195f 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -75,11 +75,6 @@ module Middleman::CoreExtensions return @cache[file[:full_path]] if @cache.key?(file[:full_path]) - if file[:types].include?(:no_frontmatter) - $stderr.puts file[:relative_path].to_s - require 'pry' - end - @cache[file[:full_path]] = ::Middleman::Util::Data.parse( file, app.config[:frontmatter_delims] From b8c0fd34e70d9fab4fb4844798d403c8be614eb7 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Fri, 22 Jan 2016 14:25:02 -0800 Subject: [PATCH 024/140] additional perf work --- middleman-cli/lib/middleman-cli/build.rb | 4 +- middleman-core/lib/middleman-core/builder.rb | 87 ++++++++++++------- .../middleman-core/core_extensions/data.rb | 11 ++- .../lib/middleman-core/file_renderer.rb | 7 +- middleman-core/lib/middleman-core/logger.rb | 1 + .../lib/middleman-core/sitemap/resource.rb | 7 +- .../middleman-core/sources/source_watcher.rb | 12 +-- .../lib/middleman-core/template_renderer.rb | 17 +++- middleman-core/lib/middleman-core/util.rb | 6 +- 9 files changed, 99 insertions(+), 53 deletions(-) diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index e3d098e7..df68c9e4 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -52,7 +52,7 @@ module Middleman::Cli ::Middleman::Logger.singleton(verbose, instrument) - ::Middleman::Util.instrument 'builder_setup' do + ::Middleman::Util.instrument 'builder.setup' do @app = ::Middleman::Application.new do config[:mode] = :build config[:environment] = env @@ -67,7 +67,7 @@ module Middleman::Cli builder.on_build_event(&method(:on_event)) end - ::Middleman::Util.instrument 'builder_run' do + ::Middleman::Util.instrument 'builder.run' do if builder.run! clean_directories! if options['clean'] shell.say 'Project built successfully.' diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index ef289d42..4562dc6c 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -51,18 +51,31 @@ module Middleman @has_error = false @events = {} - @app.execute_callbacks(:before_build, [self]) + ::Middleman::Util.instrument 'builder.before' do + @app.execute_callbacks(:before_build, [self]) + end - queue_current_paths if @cleaning + ::Middleman::Util.instrument 'builder.queue' do + queue_current_paths if @cleaning + end - prerender_css - output_files + ::Middleman::Util.instrument 'builder.prerender' do + prerender_css + end - clean! if @cleaning + ::Middleman::Util.instrument 'builder.output' do + output_files + end + + ::Middleman::Util.instrument 'builder.clean' do + clean! if @cleaning + end ::Middleman::Profiling.report('build') - @app.execute_callbacks(:after_build, [self]) + ::Middleman::Util.instrument 'builder.after' do + @app.execute_callbacks(:after_build, [self]) + end !@has_error end @@ -73,14 +86,18 @@ module Middleman def prerender_css logger.debug '== Prerendering CSS' - css_files = @app.sitemap.resources - .select { |resource| resource.ext == '.css' } - .each(&method(:output_resource)) + css_files = ::Middleman::Util.instrument 'builder.prerender.output' do + @app.sitemap.resources + .select { |resource| resource.ext == '.css' } + .each(&method(:output_resource)) + end - # Double-check for compass sprites - if @app.files.find_new_files!.length > 0 - logger.debug '== Checking for Compass sprites' - @app.sitemap.ensure_resource_list_updated! + ::Middleman::Util.instrument 'builder.prerender.check-files' do + # Double-check for compass sprites + if @app.files.find_new_files!.length > 0 + logger.debug '== Checking for Compass sprites' + @app.sitemap.ensure_resource_list_updated! + end end css_files @@ -92,11 +109,15 @@ module Middleman def output_files logger.debug '== Building files' - @app.sitemap.resources - .sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 } + resources = @app.sitemap.resources .reject { |resource| resource.ext == '.css' } - .select { |resource| !@glob || File.fnmatch(@glob, resource.destination_path) } - .each(&method(:output_resource)) + .sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 } + + if @glob + resources = resources.select { |resource| File.fnmatch(@glob, resource.destination_path) } + end + + resources.each(&method(:output_resource)) end # Figure out the correct event mode. @@ -162,25 +183,29 @@ module Middleman # @return [void] Contract IsA['Middleman::Sitemap::Resource'] => Any def output_resource(resource) - output_file = @build_dir + resource.destination_path.gsub('%20', ' ') + output_file = nil - begin - if resource.binary? - export_file!(output_file, resource.file_descriptor[:full_path]) - else - response = @rack.get(::URI.escape(resource.request_path)) + ::Middleman::Util.instrument "builder.output.resource", path: File.basename(resource.destination_path) do + output_file = @build_dir + resource.destination_path.gsub('%20', ' ') - # If we get a response, save it to a tempfile. - if response.status == 200 - export_file!(output_file, binary_encode(response.body)) + begin + if resource.binary? + export_file!(output_file, resource.file_descriptor[:full_path]) else - @has_error = true - trigger(:error, output_file, response.body) + response = @rack.get(::URI.escape(resource.request_path)) + + # If we get a response, save it to a tempfile. + if response.status == 200 + export_file!(output_file, binary_encode(response.body)) + else + @has_error = true + trigger(:error, output_file, response.body) + end end + rescue => e + @has_error = true + trigger(:error, output_file, "#{e}\n#{e.backtrace.join("\n")}") end - rescue => e - @has_error = true - trigger(:error, output_file, "#{e}\n#{e.backtrace.join("\n")}") end return unless @cleaning diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index 5f2a789f..cce997c6 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -57,6 +57,7 @@ module Middleman @app = app @data_file_matcher = data_file_matcher @local_data = {} + @local_data_enhanced = nil @local_sources = {} @callback_sources = {} end @@ -117,6 +118,8 @@ module Middleman end data_branch[basename] = data + + @local_data_enhanced = nil end # Remove a given file from the internal cache @@ -137,6 +140,8 @@ module Middleman end data_branch.delete(basename) if data_branch.key?(basename) + + @local_data_enhanced = nil end # Get a hash from either internal static data or a callback @@ -151,8 +156,7 @@ module Middleman callbacks[path.to_s].call end - response = ::Middleman::Util.recursively_enhance(response) - response + ::Middleman::Util.recursively_enhance(response) end # "Magically" find namespaces of data if they exist @@ -162,7 +166,8 @@ module Middleman def method_missing(path) if @local_data.key?(path.to_s) # Any way to cache this? - return ::Middleman::Util.recursively_enhance(@local_data[path.to_s]) + @local_data_enhanced ||= ::Middleman::Util.recursively_enhance(@local_data) + return @local_data_enhanced[path.to_s] else result = data_for_path(path) return result if result diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index 67f9411f..64519be0 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -73,9 +73,10 @@ module Middleman # end # Render using Tilt - content = ::Middleman::Util.instrument 'render.tilt', path: path do - template.render(context, locs, &block) - end + # content = ::Middleman::Util.instrument 'render.tilt', path: path do + # template.render(context, locs, &block) + # end + content = template.render(context, locs, &block) # Allow hooks to manipulate the result after render content = @app.callbacks_for(:after_render).reduce(content) do |sum, callback| diff --git a/middleman-core/lib/middleman-core/logger.rb b/middleman-core/lib/middleman-core/logger.rb index d1a1c402..30e28307 100644 --- a/middleman-core/lib/middleman-core/logger.rb +++ b/middleman-core/lib/middleman-core/logger.rb @@ -40,6 +40,7 @@ module Middleman return if @instrumenting.is_a?(String) && @instrumenting != 'instrument' && !message.include?(@instrumenting) evt = ::ActiveSupport::Notifications::Event.new(message, *args) + return unless evt.duration > 30 info "== Instrument (#{evt.name.sub(/.middleman$/, '')}): #{evt.duration}ms\n#{args.last}" end end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index b1f614e4..5d7b9969 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -66,6 +66,8 @@ module Middleman # Page are data that is exposed through this resource's data member. # Note: It is named 'page' for backwards compatibility with older MM. @metadata = { options: {}, locals: {}, page: {} } + + @page_data = nil end # Whether this resource has a template file @@ -91,6 +93,7 @@ module Middleman # Note: It is named 'page' for backwards compatibility with older MM. Contract METADATA_HASH => METADATA_HASH def add_metadata(meta={}) + @page_data = nil @metadata.deep_merge!(meta) end @@ -98,7 +101,7 @@ module Middleman # @return [Hash] Contract RespondTo[:indifferent_access?] def data - ::Middleman::Util.recursively_enhance(metadata[:page]) + @page_data ||= ::Middleman::Util.recursively_enhance(metadata[:page]) end # Options about how this resource is rendered, such as its :layout, @@ -129,7 +132,6 @@ module Middleman def render(opts={}, locs={}) return ::Middleman::FileRenderer.new(@app, file_descriptor[:full_path].to_s).template_data_for_file unless template? - # ::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 +142,6 @@ module Middleman renderer = ::Middleman::TemplateRenderer.new(@app, file_descriptor[:full_path].to_s) renderer.render(locs, opts) - # end end # A path without the directory index - so foo/index.html becomes diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 0c7356c2..e6ad077c 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -185,9 +185,7 @@ module Middleman new_files = ::Middleman::Util.all_files_under(@directory.to_s) .reject { |p| @files.key?(p) } - update(new_files, []) - - new_files + update(new_files, []).flatten.map { |s| s[:full_path] } end # Manually trigger update events. @@ -198,14 +196,14 @@ module Middleman updated = ::Middleman::Util.all_files_under(@directory.to_s) removed = @files.keys.reject { |p| updated.include?(p) } - update(updated, removed) + result = update(updated, removed) if @waiting_for_existence && @directory.exist? @waiting_for_existence = false listen! end - updated + removed + result.flatten.map { |s| s[:full_path] } end # Work around this bug: http://bugs.ruby-lang.org/issues/4521 @@ -238,7 +236,7 @@ module Middleman # # @param [String, Pathname] path The updated file path. # @return [void] - Contract ArrayOf[Pathname], ArrayOf[Pathname] => Any + Contract ArrayOf[Pathname], ArrayOf[Pathname] => ArrayOf[ArrayOf[IsA['Middleman::SourceFile']]] def update(updated_paths, removed_paths) valid_updates = updated_paths .map { |p| @files[p] || path_to_source_file(p, @directory, @type, @options[:destination_dir]) } @@ -271,6 +269,8 @@ module Middleman valid_removes, self ]) unless valid_updates.empty? && valid_removes.empty? + + [valid_updates, valid_removes] end # Convert a path to a file resprentation. diff --git a/middleman-core/lib/middleman-core/template_renderer.rb b/middleman-core/lib/middleman-core/template_renderer.rb index 4af4ce14..1930d434 100644 --- a/middleman-core/lib/middleman-core/template_renderer.rb +++ b/middleman-core/lib/middleman-core/template_renderer.rb @@ -133,12 +133,21 @@ module Middleman # Add extension helpers to context. @app.extensions.add_exposed_to_context(context) - content = _render_with_all_renderers(path, locs, context, opts, &block) + content = ::Middleman::Util.instrument 'builder.output.resource.render-template', path: File.basename(path) do + _render_with_all_renderers(path, locs, context, opts, &block) + end # If we need a layout and have a layout, use it - if layout_file = fetch_layout(engine, options) - layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s) - content = layout_renderer.render(locals, options, context) { content } + layout_file = fetch_layout(engine, options) + if layout_file + content = ::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do + if layout_file = fetch_layout(engine, options) + layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s) + layout_renderer.render(locals, options, context) { content } + else + content + end + end end # Return result diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index ae15e3ec..a2cd1eef 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -98,7 +98,7 @@ module Middleman # @private # @param [Hash] data Normal hash # @return [Hash] - Contract Maybe[Hash] => Maybe[Or[Array, EnhancedHash]] + Contract Any => Maybe[Or[Array, EnhancedHash]] def recursively_enhance(obj) if obj.is_a? ::Array obj.map { |e| recursively_enhance(e) } @@ -480,6 +480,8 @@ module Middleman # @return [String] Contract String => ArrayOf[String] def collect_extensions(path) + return [] if File.basename(path).start_with?('.') + result = [] step_through_extensions(path) { |e| result << e } @@ -495,6 +497,8 @@ module Middleman # @return [Middleman::SourceFile] All related file paths, not including the source file paths. Contract ::Middleman::Application, ArrayOf[Pathname] => ArrayOf[::Middleman::SourceFile] def find_related_files(app, files) + return [] if files.empty? + all_extensions = files.flat_map { |f| collect_extensions(f.to_s) } sass_type_aliasing = ['.scss', '.sass'] From c7a46181664bf47e5dd149932d2f0302e212030a Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Fri, 22 Jan 2016 15:57:07 -0800 Subject: [PATCH 025/140] Perf work and Parallel builds --- CHANGELOG.md | 1 + middleman-cli/bin/middleman | 2 +- middleman-cli/lib/middleman-cli/build.rb | 4 +++ .../lib/middleman-core/application.rb | 4 +-- middleman-core/lib/middleman-core/builder.rb | 32 ++++++++++++++----- .../middleman-core/core_extensions/data.rb | 4 +-- .../core_extensions/default_helpers.rb | 12 +++---- .../middleman-core/core_extensions/i18n.rb | 2 +- .../core_extensions/inline_url_rewriter.rb | 4 +-- .../lib/middleman-core/extension.rb | 2 +- .../lib/middleman-core/extensions.rb | 2 +- .../extensions/automatic_image_sizes.rb | 2 +- .../middleman-core/extensions/minify_css.rb | 2 +- .../lib/middleman-core/file_renderer.rb | 2 +- .../lib/middleman-core/renderers/haml.rb | 2 +- .../lib/middleman-core/renderers/less.rb | 2 +- .../lib/middleman-core/renderers/sass.rb | 4 +-- middleman-core/lib/middleman-core/sources.rb | 11 +++---- .../middleman-core/sources/source_watcher.rb | 2 +- middleman-core/lib/middleman-core/util.rb | 9 +++--- middleman-core/middleman-core.gemspec | 1 + 21 files changed, 63 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e9ce31c..1ce7548e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ master * Fix asset_host in combination with Google Analytics snippet. #1751 * Show an error message when git CLI is not available. #1765 * Correctly show file names of GZIP'ed assets. #1364 +* Build file output is not parallel-ized! Use `middleman build --no-parallel` to disable. # 4.0.0 diff --git a/middleman-cli/bin/middleman b/middleman-cli/bin/middleman index 165b7bc9..43297984 100755 --- a/middleman-cli/bin/middleman +++ b/middleman-cli/bin/middleman @@ -4,7 +4,7 @@ require 'middleman-core/profiling' if ARGV.include? '--profile' Middleman::Profiling.profiler = Middleman::Profiling::RubyProfProfiler.new end -Middleman::Profiling.start +# Middleman::Profiling.start require "middleman-core/load_paths" Middleman.setup_load_paths diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index df68c9e4..c00acd2f 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -14,6 +14,10 @@ module Middleman::Cli type: :boolean, default: true, desc: 'Remove orphaned files from build (--no-clean to disable)' + class_option :parallel, + type: :boolean, + default: true, + desc: 'Output files in parallel (--no-parallel to disable)' class_option :glob, type: :string, aliases: '-g', diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 38c2baf4..9000db79 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -184,7 +184,7 @@ module Middleman end }, 'Callbacks that can exclude paths from the sitemap' - define_setting :skip_build_clean, proc { |p| [/\.git/].any? { |r| r.match(p) } }, 'Whether some paths should not be removed during a clean build.' + define_setting :skip_build_clean, proc { |p| [/\.git/].any? { |r| p =~ r } }, 'Whether some paths should not be removed during a clean build.' define_setting :watcher_disable, false, 'If the Listen watcher should not run' define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode' @@ -314,7 +314,7 @@ module Middleman # Clean up missing Tilt exts def prune_tilt_templates! - ::Tilt.mappings.each do |key, _| + ::Tilt.mappings.each_key do |key| begin ::Tilt[".#{key}"] rescue LoadError, NameError diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index 4562dc6c..5bdedfe8 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -1,6 +1,7 @@ require 'pathname' require 'fileutils' require 'tempfile' +require 'parallel' require 'middleman-core/rack' require 'middleman-core/callback_manager' require 'middleman-core/contracts' @@ -36,6 +37,7 @@ module Middleman @glob = opts.fetch(:glob) @cleaning = opts.fetch(:clean) + @parallel = opts.fetch(:parallel, true) rack_app = ::Middleman::Rack.new(@app).to_app @rack = ::Rack::MockRequest.new(rack_app) @@ -63,16 +65,18 @@ module Middleman prerender_css end + ::Middleman::Profiling.start + ::Middleman::Util.instrument 'builder.output' do output_files end + ::Middleman::Profiling.report('build') + ::Middleman::Util.instrument 'builder.clean' do clean! if @cleaning end - ::Middleman::Profiling.report('build') - ::Middleman::Util.instrument 'builder.after' do @app.execute_callbacks(:after_build, [self]) end @@ -87,9 +91,8 @@ module Middleman logger.debug '== Prerendering CSS' css_files = ::Middleman::Util.instrument 'builder.prerender.output' do - @app.sitemap.resources - .select { |resource| resource.ext == '.css' } - .each(&method(:output_resource)) + resources = @app.sitemap.resources.select { |resource| resource.ext == '.css' } + output_resources(resources) end ::Middleman::Util.instrument 'builder.prerender.check-files' do @@ -117,7 +120,20 @@ module Middleman resources = resources.select { |resource| File.fnmatch(@glob, resource.destination_path) } end - resources.each(&method(:output_resource)) + output_resources(resources) + end + + Contract ResourceList => ResourceList + def output_resources(resources) + cleaned_paths = if @parallel + ::Parallel.map(resources, &method(:output_resource)) + else + resources.map(&method(:output_resource)) + end + + cleaned_paths.each { |p| @to_clean.delete(p) } if @cleaning + + resources end # Figure out the correct event mode. @@ -181,7 +197,7 @@ module Middleman # Try to output a resource and capture errors. # @param [Middleman::Sitemap::Resource] resource The resource. # @return [void] - Contract IsA['Middleman::Sitemap::Resource'] => Any + Contract IsA['Middleman::Sitemap::Resource'] => Maybe[Pathname] def output_resource(resource) output_file = nil @@ -218,7 +234,7 @@ module Middleman output_file end - @to_clean.delete(Pathname(cleaned_name)) + Pathname(cleaned_name) end # Get a list of all the paths in the destination folder and save them diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index cce997c6..7ff60f41 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -203,11 +203,11 @@ module Middleman def to_h data = {} - store.each do |k, _| + store.each_key do |k| data[k] = data_for_path(k) end - callbacks.each do |k, _| + callbacks.each_key do |k| data[k] = data_for_path(k) end diff --git a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb index 745ca71c..8a7c90f6 100644 --- a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb @@ -113,7 +113,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension path_options = {} path_options[:relative] = options.delete(:relative) if options.key?(:relative) - sources.flatten.inject(::ActiveSupport::SafeBuffer.new) do |all, source| + sources.flatten.reduce(::ActiveSupport::SafeBuffer.new) do |all, source| all << tag(:link, { href: asset_path(:css, source, path_options) }.update(options)) @@ -127,7 +127,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension path_options = {} path_options[:relative] = options.delete(:relative) if options.key?(:relative) - sources.flatten.inject(::ActiveSupport::SafeBuffer.new) do |all, source| + sources.flatten.reduce(::ActiveSupport::SafeBuffer.new) do |all, source| all << content_tag(:script, nil, { src: asset_path(:js, source, path_options) }.update(options)) @@ -152,7 +152,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # If the basename of the request as no extension, assume we are serving a # directory and join index_file to the path. path = File.join(asset_dir, current_resource.path) - path = path.sub(/#{Regexp.escape(File.extname(path))}$/, ".#{asset_ext}") + path = path[0..-(File.extname(path).length + 1)] + ".#{asset_ext}" yield path if sitemap.find_resource_by_path(path) end @@ -191,7 +191,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # @param [Hash] options Data to pass through. # @return [String] def asset_path(kind, source, options={}) - options_with_resource = options.merge(current_resource: current_resource) + options_with_resource = {}.merge!(options).merge!(current_resource: current_resource) ::Middleman::Util.asset_path(app, kind, source, options_with_resource) end @@ -202,7 +202,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # @param [Hash] options Additional options. # @return [String] The fully qualified asset url def asset_url(path, prefix='', options={}) - options_with_resource = options.merge(current_resource: current_resource) + options_with_resource = {}.merge!(options).merge!(current_resource: current_resource) ::Middleman::Util.asset_url(app, path, prefix, options_with_resource) end @@ -210,7 +210,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # or a Resource, this will produce the nice URL configured for that # path, respecting :relative_links, directory indexes, etc. def url_for(path_or_resource, options={}) - options_with_resource = options.merge(current_resource: current_resource) + options_with_resource = {}.merge!(options).merge!(current_resource: current_resource) ::Middleman::Util.url_for(app, path_or_resource, options_with_resource) end diff --git a/middleman-core/lib/middleman-core/core_extensions/i18n.rb b/middleman-core/lib/middleman-core/core_extensions/i18n.rb index 4b2f35b4..9f7503b8 100644 --- a/middleman-core/lib/middleman-core/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-core/core_extensions/i18n.rb @@ -203,7 +203,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension if (options[:mount_at_root] == locale) || (options[:mount_at_root].nil? && locales[0] == locale) '/' else - replacement = options[:locale_map].fetch(locale, locale) + replacement = options[:locale_map][locale] || locale options[:path].sub(':locale', replacement.to_s).sub(':lang', replacement.to_s) # Backward compat end end diff --git a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb index 7d42b667..280c8db0 100644 --- a/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/inline_url_rewriter.rb @@ -108,7 +108,7 @@ module Middleman ignore = rewriter.fetch(:ignore) next if ignore.any? { |r| should_ignore?(r, full_asset_path) } - rewrite_ignore = Array(rewriter.fetch(:rewrite_ignore, [])) + rewrite_ignore = Array(rewriter[:rewrite_ignore] || []) next if rewrite_ignore.any? { |i| ::Middleman::Util.path_match(i, path) } proc = rewriter.fetch(:proc) @@ -132,7 +132,7 @@ module Middleman def should_ignore?(validator, value) if validator.is_a? Regexp # Treat as Regexp - !value.match(validator).nil? + !!(value =~ validator) elsif validator.respond_to? :call # Treat as proc validator.call(value) diff --git a/middleman-core/lib/middleman-core/extension.rb b/middleman-core/lib/middleman-core/extension.rb index 1a8b8fa4..e8e36af0 100644 --- a/middleman-core/lib/middleman-core/extension.rb +++ b/middleman-core/lib/middleman-core/extension.rb @@ -432,7 +432,7 @@ module Middleman {} end - sum.merge(resource_definitions) + sum.merge!(resource_definitions) end resources + generator_defs.map do |path, g| diff --git a/middleman-core/lib/middleman-core/extensions.rb b/middleman-core/lib/middleman-core/extensions.rb index c295efe3..fba0e488 100644 --- a/middleman-core/lib/middleman-core/extensions.rb +++ b/middleman-core/lib/middleman-core/extensions.rb @@ -106,7 +106,7 @@ module Middleman # A flattened list of all extensions which are automatically activated # @return [Array] A list of extension names which are automatically activated. def auto_activated - @auto_activate.values.map(&:to_a).flatten.map(&:name) + @auto_activate.values.map(&:to_a).flat_map(&:name) end # @api private diff --git a/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb b/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb index 5bd0f14d..5d12501f 100644 --- a/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb +++ b/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb @@ -19,7 +19,7 @@ class Middleman::Extensions::AutomaticImageSizes < ::Middleman::Extension real_path = path.dup real_path = File.join(config[:images_dir], real_path) unless real_path.start_with?('/') - file = app.files.find(:source, real_path) || app.files.find(:source, real_path.gsub(/^\//, '')) + file = app.files.find(:source, real_path) || app.files.find(:source, real_path.sub(/^\//, '')) if file && file[:full_path].exist? begin diff --git a/middleman-core/lib/middleman-core/extensions/minify_css.rb b/middleman-core/lib/middleman-core/extensions/minify_css.rb index caf54262..cc513b6c 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_css.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_css.rb @@ -23,7 +23,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension class SassCompressor def self.compress(style, options={}) root_node = ::Sass::SCSS::CssParser.new(style, 'middleman-css-input', 1).parse - root_node.options = options.merge(style: :compressed) + root_node.options = {}.merge!(options).merge!(style: :compressed) root_node.render.strip end end diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index 64519be0..ae1212b4 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -51,7 +51,7 @@ module Middleman # Merge per-extension options from config extension = File.extname(path) - options = opts.merge(options_for_ext(extension)) + options = {}.merge!(opts).merge!(options_for_ext(extension)) options[:outvar] ||= '@_out_buf' options[:context] = context options.delete(:layout) diff --git a/middleman-core/lib/middleman-core/renderers/haml.rb b/middleman-core/lib/middleman-core/renderers/haml.rb index 24cdced4..c5bf4699 100644 --- a/middleman-core/lib/middleman-core/renderers/haml.rb +++ b/middleman-core/lib/middleman-core/renderers/haml.rb @@ -30,7 +30,7 @@ module Middleman end def evaluate(scope, locals, &block) - options = @options.merge(filename: eval_file, line: line, context: @context || scope) + options = {}.merge!(@options).merge!(filename: eval_file, line: line, context: @context || scope) @engine = ::Haml::Engine.new(data, options) output = @engine.render(scope, locals, &block) diff --git a/middleman-core/lib/middleman-core/renderers/less.rb b/middleman-core/lib/middleman-core/renderers/less.rb index 7830b137..c47d84d3 100644 --- a/middleman-core/lib/middleman-core/renderers/less.rb +++ b/middleman-core/lib/middleman-core/renderers/less.rb @@ -26,7 +26,7 @@ module Middleman if ::Less.const_defined? :Engine @engine = ::Less::Engine.new(data) else - parser = ::Less::Parser.new(options.merge(filename: eval_file, line: line, paths: ['.', File.dirname(eval_file)])) + parser = ::Less::Parser.new({}.merge!(options).merge!(filename: eval_file, line: line, paths: ['.', File.dirname(eval_file)])) @engine = parser.parse(data) end end diff --git a/middleman-core/lib/middleman-core/renderers/sass.rb b/middleman-core/lib/middleman-core/renderers/sass.rb index abd44502..ef040f74 100644 --- a/middleman-core/lib/middleman-core/renderers/sass.rb +++ b/middleman-core/lib/middleman-core/renderers/sass.rb @@ -81,7 +81,7 @@ module Middleman filename: eval_file, line: line, syntax: syntax, - custom: (options[:custom] || {}).merge( + custom: {}.merge!(options[:custom] || {}).merge!( middleman_context: ctx.app, current_resource: ctx.current_resource ) @@ -97,7 +97,7 @@ module Middleman more_opts[:css_filename] = file.sub(/\.s[ac]ss$/, '') end - options.merge(more_opts) + {}.merge!(options).merge!(more_opts) end end diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 7114d9f0..54702570 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -189,6 +189,7 @@ module Middleman array_of_types = Array(types) watchers + .lazy .select { |d| array_of_types.include?(d.type) } .map { |d| d.find(path, glob) } .reject(&:nil?) @@ -202,9 +203,7 @@ module Middleman # @return [Boolean] Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String => Bool def exists?(types, path) - watchers - .select { |d| Array(types).include?(d.type) } - .any? { |d| d.exists?(path) } + watchers.any? { |d| Array(types).include?(d.type) && d.exists?(path) } end # Check if a file for a given type exists. @@ -214,9 +213,7 @@ module Middleman # @return [Boolean] Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String => Maybe[HANDLER] def watcher_for_path(types, path) - watchers - .select { |d| Array(types).include?(d.type) } - .find { |d| d.exists?(path) } + watchers.detect { |d| Array(types).include?(d.type) && d.exists?(path) } end # Manually check for new files @@ -317,7 +314,7 @@ module Middleman def matches?(validator, file) path = file[:relative_path] if validator.is_a? Regexp - !!validator.match(path.to_s) + !!(path.to_s =~ validator) else !!validator.call(path, @app) end diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index e6ad077c..e1a3fdd4 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -322,7 +322,7 @@ module Middleman if @only.empty? !@ignored.call(file) else - @only.any? { |reg| reg.match(file[:relative_path].to_s) } + @only.any? { |reg| file[:relative_path].to_s =~ reg } end end end diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index a2cd1eef..f492a54d 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -79,7 +79,7 @@ module Middleman path == matcher end when matcher.respond_to?(:match) - !matcher.match(path).nil? + !!(path =~ matcher) when matcher.respond_to?(:call) matcher.call(path) else @@ -357,7 +357,7 @@ module Middleman begin uri = ::Addressable::URI.parse(asset_path) - if uri.relative? && uri.host.nil? && !asset_path.match(/^[^\/].*[a-z]+\.[a-z]+\/.*/) && (result = yield(asset_path)) + if uri.relative? && uri.host.nil? && !(asset_path =~ /^[^\/].*[a-z]+\.[a-z]+\/.*/) && (result = yield(asset_path)) "#{opening_character}#{result}" else match @@ -456,10 +456,11 @@ module Middleman Contract String => String def step_through_extensions(path) while ::Tilt[path] - yield File.extname(path) if block_given? + ext = File.extname(path) + yield ext if block_given? # Strip templating extensions as long as Tilt knows them - path = path.sub(/#{::Regexp.escape(File.extname(path))}$/, '') + path = path[0..-(ext.length + 1)] end yield File.extname(path) if block_given? diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 894bf470..f9bb6235 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -24,6 +24,7 @@ Gem::Specification.new do |s| s.add_dependency('tilt', ['~> 1.4.1']) s.add_dependency('erubis') s.add_dependency('fast_blank') + s.add_dependency('parallel') # Helpers s.add_dependency('activesupport', ['~> 4.2']) From 4deaa65a6d5dc594abb9362cd77b25886d2219fc Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 23 Jan 2016 17:14:35 -0800 Subject: [PATCH 026/140] update donate link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b7203403..1efe8b5d 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ The best way to get quick responses to your issues and swift fixes to your bugs ## Donate -[Click here to lend your support to Middleman](https://spacebox.io/s/4dXbHBorC3) +[Click here to lend your support to Middleman](https://plasso.co/s/4dXbHBorC3) ## Versioning From deae5d2216f5105e0de68d8eb51f3bc3cc10c8b2 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 24 Jan 2016 12:30:53 -0800 Subject: [PATCH 027/140] Fix #1778 --- middleman-core/lib/middleman-core/sources.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 54702570..d30f0124 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -184,7 +184,7 @@ module Middleman # @param [String] path The file path. # @param [Boolean] glob If the path contains wildcard or glob characters. # @return [Middleman::SourceFile, nil] - Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String, Maybe[Bool] => Maybe[SourceFile] + Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], Or[Pathname, String], Maybe[Bool] => Maybe[SourceFile] def find(types, path, glob=false) array_of_types = Array(types) From e7d9c8ad0e0dd45b3df3b1239cbd9e0c5783b2dc Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 24 Jan 2016 13:02:39 -0800 Subject: [PATCH 028/140] Fix a threading issue caused by parallel --- middleman-core/lib/middleman-core/builder.rb | 37 +++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index 5bdedfe8..3549fc34 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -125,13 +125,28 @@ module Middleman Contract ResourceList => ResourceList def output_resources(resources) - cleaned_paths = if @parallel + results = if @parallel ::Parallel.map(resources, &method(:output_resource)) else resources.map(&method(:output_resource)) end - cleaned_paths.each { |p| @to_clean.delete(p) } if @cleaning + @has_error = true if results.any? { |r| r == false } + + if @cleaning && !@has_error + results.each do |p| + next unless p.exist? + + # handle UTF-8-MAC filename on MacOS + cleaned_name = if RUBY_PLATFORM =~ /darwin/ + p.to_s.encode('UTF-8', 'UTF-8-MAC') + else + p + end + + @to_clean.delete(Pathname(cleaned_name)) + end + end resources end @@ -197,10 +212,8 @@ module Middleman # Try to output a resource and capture errors. # @param [Middleman::Sitemap::Resource] resource The resource. # @return [void] - Contract IsA['Middleman::Sitemap::Resource'] => Maybe[Pathname] + Contract IsA['Middleman::Sitemap::Resource'] => Or[Pathname, Bool] def output_resource(resource) - output_file = nil - ::Middleman::Util.instrument "builder.output.resource", path: File.basename(resource.destination_path) do output_file = @build_dir + resource.destination_path.gsub('%20', ' ') @@ -214,27 +227,17 @@ module Middleman if response.status == 200 export_file!(output_file, binary_encode(response.body)) else - @has_error = true trigger(:error, output_file, response.body) + return false end end rescue => e - @has_error = true trigger(:error, output_file, "#{e}\n#{e.backtrace.join("\n")}") + return false end - end - return unless @cleaning - return unless output_file.exist? - - # handle UTF-8-MAC filename on MacOS - cleaned_name = if RUBY_PLATFORM =~ /darwin/ - output_file.to_s.encode('UTF-8', 'UTF-8-MAC') - else output_file end - - Pathname(cleaned_name) end # Get a list of all the paths in the destination folder and save them From 8881389b42f22b5e2406e999997303fffd8ff1e6 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sun, 24 Jan 2016 22:55:48 -0800 Subject: [PATCH 029/140] Minify inline JS when there are other attributes. --- .../lib/middleman-core/extensions/minify_javascript.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb index 7472e561..acd71224 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb @@ -112,7 +112,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension # Only compress script tags that contain JavaScript (as opposed to # something like jQuery templates, identified with a "text/html" type). - if first.include?('