From 7efa5e9dd9bae62ac5f0e2a96af9fc07f2dd844d Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 20 Jan 2016 15:57:20 -0800 Subject: [PATCH 001/122] Another domain checker --- middleman-core/lib/middleman-core/util.rb | 3 ++- middleman-core/middleman-core.gemspec | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index db1238b2..b5a5174c 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -18,6 +18,7 @@ require 'middleman-core/sitemap/resource' require 'hashie' # For URI templating +require 'public_suffix' require 'addressable/uri' require 'addressable/template' require 'active_support/inflector' @@ -357,7 +358,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? && !::PublicSuffix.valid?(asset_path) && (result = yield(asset_path)) "#{opening_character}#{result}" else match diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 894bf470..2e34e6fd 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('public_suffix') # Helpers s.add_dependency('activesupport', ['~> 4.2']) From 68127003b90003993ada0e49106c844e6f2594c8 Mon Sep 17 00:00:00 2001 From: Jim Dalton Date: Wed, 20 Jan 2016 21:11:03 -0800 Subject: [PATCH 002/122] 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 003/122] 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 004/122] 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 005/122] 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 006/122] 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 007/122] 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 008/122] 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 009/122] 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 010/122] 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 011/122] 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?('