From 0e620a1ba194d11b0bb2a90535e05f6d87ec1b12 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 14 Dec 2015 10:22:27 -0800 Subject: [PATCH 001/178] Resolve Contracts warning --- .../middleman-core/core_extensions/i18n.rb | 10 ++++++++- middleman-core/lib/middleman-core/sources.rb | 21 +++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/i18n.rb b/middleman-core/lib/middleman-core/core_extensions/i18n.rb index ada6dd0c..1b59a385 100644 --- a/middleman-core/lib/middleman-core/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-core/core_extensions/i18n.rb @@ -10,7 +10,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension option :data, 'locales', 'The directory holding your locale configurations' # Exposes `locales` to templates - expose_to_template :locales, :langs + expose_to_template :locales, :langs, :locale, :lang def initialize(*) super @@ -129,6 +129,14 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension # Backwards API compat alias_method :langs, :locales + Contract Symbol + def locale + ::I18n.locale + end + + # Backwards API compat + alias_method :lang, :locale + # Update the main sitemap resource list # @return Array Contract ResourceList => ResourceList diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index 026f854b..6b888a87 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -14,8 +14,11 @@ module Middleman extend Forwardable include Contracts - # Types which trigger a livereload - LIVERELOAD_TYPES = [:source, :locales, :data] + # Types which could cause output to change. + OUTPUT_TYPES = [:source, :locales, :data] + + # Types which require a reload to eval ruby + CODE_TYPES = [:reload] Matcher = Or[Regexp, RespondTo[:call]] @@ -172,7 +175,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]], String, Maybe[Bool] => Maybe[SourceFile] + Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String, Maybe[Bool] => Maybe[SourceFile] def find(types, path, glob=false) watchers .lazy @@ -187,7 +190,7 @@ module Middleman # @param [Symbol,Array] types The list of file "type". # @param [String] path The file path relative to it's source root. # @return [Boolean] - Contract Or[Symbol, ArrayOf[Symbol]], String => Bool + Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String => Bool def exists?(types, path) watchers .lazy @@ -200,7 +203,7 @@ module Middleman # @param [Symbol,Array] types The list of file "type". # @param [String] path The file path relative to it's source root. # @return [Boolean] - Contract Or[Symbol, ArrayOf[Symbol]], String => Maybe[HANDLER] + Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], String => Maybe[HANDLER] def watcher_for_path(types, path) watchers .select { |d| Array(types).include?(d.type) } @@ -243,7 +246,7 @@ module Middleman # # @param [Symbol,Array] types The change types to register the callback. # @return [void] - Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any + Contract Or[Symbol, ArrayOf[Symbol], SetOf[Symbol]], Proc => Any def on_change(types, &block) Array(types).each do |type| @on_change_callbacks = @on_change_callbacks.push(CallbackDescriptor.new(type, block)) @@ -255,7 +258,7 @@ module Middleman # @param [nil,Regexp] matcher A Regexp to match the change path against Contract Maybe[Matcher] => Any def changed(matcher=nil, &block) - on_change LIVERELOAD_TYPES do |updated, _removed| + on_change OUTPUT_TYPES do |updated, _removed| updated .select { |f| matcher.nil? ? true : matches?(matcher, f) } .each { |f| block.call(f[:relative_path]) } @@ -267,7 +270,7 @@ module Middleman # @param [nil,Regexp] matcher A Regexp to match the change path against Contract Maybe[Matcher] => Any def deleted(matcher=nil, &block) - on_change LIVERELOAD_TYPES do |_updated, removed| + on_change OUTPUT_TYPES do |_updated, removed| removed .select { |f| matcher.nil? ? true : matches?(matcher, f) } .each { |f| block.call(f[:relative_path]) } @@ -279,7 +282,7 @@ module Middleman # @param [Pathname,String] path The path to check. Contract Or[Pathname, String] => Bool def ignored?(path) - descriptor = find(LIVERELOAD_TYPES, path) + descriptor = find(OUTPUT_TYPES, path) !descriptor || globally_ignored?(descriptor) end From 6af784d5d50b35af09e839fb49206ed0dcb3b909 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 14 Dec 2015 11:02:07 -0800 Subject: [PATCH 002/178] One more RC --- CHANGELOG.md | 3 +++ middleman-core/lib/middleman-core/version.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 486acada..158de44e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ master === +# 4.0.0.rc.3 + +* Add `:locales` and `:data` source types to the list of files which trigger a live-reload. * Rename i18n `lang` and `langs` to `locale` and `locales`. * Avoid matching URLs across new lines. #1689 * Load Middleman Directory when doing `init` over SSL diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index 78c81a07..44d6ca6e 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.0.0.rc.2' unless const_defined?(:VERSION) + VERSION = '4.0.0.rc.3' unless const_defined?(:VERSION) end From 9e5b137ed8f6299fec6479b14bf58a4716d39d2e Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 15 Dec 2015 09:58:22 -0800 Subject: [PATCH 003/178] Really fix #1689 --- middleman-cli/lib/middleman-cli/build.rb | 2 +- middleman-core/features/relative_assets.feature | 5 +++++ .../source/stylesheets/fonts2.css.scss | 10 ++++++++++ middleman-core/lib/middleman-core/util.rb | 9 ++++++++- 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 middleman-core/fixtures/relative-assets-app/source/stylesheets/fonts2.css.scss diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index cf2d58a8..1ef884b2 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -64,7 +64,7 @@ module Middleman::Cli if builder.run! clean_directories! if options['clean'] - shell.say "Project built successfully." + shell.say 'Project built successfully.' else msg = 'There were errors during this build' unless options['verbose'] diff --git a/middleman-core/features/relative_assets.feature b/middleman-core/features/relative_assets.feature index 0f782761..a4b6fc68 100644 --- a/middleman-core/features/relative_assets.feature +++ b/middleman-core/features/relative_assets.feature @@ -41,6 +41,11 @@ Feature: Relative Assets And I should see 'url(../fonts/roboto/roboto-regular-webfont.woff' And I should see 'url(../fonts/roboto/roboto-regular-webfont.ttf' And I should see 'url(../fonts/roboto/roboto-regular-webfont.svg' + When I go to "/stylesheets/fonts2.css" + Then I should see 'url(../fonts/roboto/roboto-regular-webfont.eot' + And I should see 'url(../fonts/roboto/roboto-regular-webfont.woff' + And I should see 'url(../fonts/roboto/roboto-regular-webfont.ttf' + And I should see 'url(../fonts/roboto/roboto-regular-webfont.svg' Scenario: Building css with the feature enabled Given a fixture app "relative-assets-app" diff --git a/middleman-core/fixtures/relative-assets-app/source/stylesheets/fonts2.css.scss b/middleman-core/fixtures/relative-assets-app/source/stylesheets/fonts2.css.scss new file mode 100644 index 00000000..ef6c7dfe --- /dev/null +++ b/middleman-core/fixtures/relative-assets-app/source/stylesheets/fonts2.css.scss @@ -0,0 +1,10 @@ +@font-face { + font-family: 'Roboto'; + src: url(/fonts/roboto/roboto-regular-webfont.eot); + src: url(/fonts/roboto/roboto-regular-webfont.eot?#iefix) format('embedded-opentype'), + url(/fonts/roboto/roboto-regular-webfont.woff) format('woff'), + url(/fonts/roboto/roboto-regular-webfont.ttf) format('truetype'), + url(/fonts/roboto/roboto-regular-webfont.svg#robotoregular) format('svg'); + font-weight: normal; + font-style: normal; +} diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 4d700e0e..db29cf92 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -332,12 +332,19 @@ module Middleman Contract String, String, ArrayOf[String], Proc => String def rewrite_paths(body, _path, exts, &_block) - matcher = /([=\'\"\(,] *)([^\s\'\"\)>]+(#{Regexp.union(exts)}))/ + matcher = /([=\'\"\(,]\s*)([^\s\'\"\)>]+(#{Regexp.union(exts)}))/ + + url_fn_prefix = 'url(' body.dup.gsub(matcher) do |match| opening_character = $1 asset_path = $2 + if asset_path.start_with?(url_fn_prefix) + opening_character << url_fn_prefix + asset_path = asset_path[url_fn_prefix.length..-1] + end + begin uri = ::Addressable::URI.parse(asset_path) From b2b461935d132ffbc38e59884fb50ae657d5b4b9 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 15 Dec 2015 19:58:04 -0800 Subject: [PATCH 004/178] Here we go --- 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 44d6ca6e..6c697cbd 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.0.0.rc.3' unless const_defined?(:VERSION) + VERSION = '4.0.0' unless const_defined?(:VERSION) end From e035d625c82afa6113858640d735905919c36108 Mon Sep 17 00:00:00 2001 From: jordanandree Date: Thu, 17 Dec 2015 14:01:37 -0500 Subject: [PATCH 005/178] skip front matter on ingored resources --- .../lib/middleman-core/core_extensions/front_matter.rb | 1 + 1 file changed, 1 insertion(+) 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 b1488c1a..739b49fd 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.ignored? next if resource.file_descriptor.nil? fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup From 6aeda854c0911e489f511d32c6b1e41c6d1bc258 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 20 Dec 2015 12:48:01 -0800 Subject: [PATCH 006/178] Update local extension template --- middleman-cli/lib/middleman-cli/extension.rb | 2 +- .../templates/extension/lib/lib.rb | 40 ++----------------- .../templates/extension/lib/lib/extension.rb | 31 ++++++++++++++ .../extension/lib/middleman_extension.rb | 1 - 4 files changed, 36 insertions(+), 38 deletions(-) create mode 100644 middleman-cli/lib/middleman-cli/templates/extension/lib/lib/extension.rb delete mode 100644 middleman-cli/lib/middleman-cli/templates/extension/lib/middleman_extension.rb diff --git a/middleman-cli/lib/middleman-cli/extension.rb b/middleman-cli/lib/middleman-cli/extension.rb index 1b079f4d..fd6c6f26 100644 --- a/middleman-cli/lib/middleman-cli/extension.rb +++ b/middleman-cli/lib/middleman-cli/extension.rb @@ -30,8 +30,8 @@ module Middleman::Cli template 'extension/Rakefile', File.join(name, 'Rakefile') template 'extension/gemspec', File.join(name, "#{name}.gemspec") template 'extension/Gemfile', File.join(name, 'Gemfile') - template 'extension/lib/middleman_extension.rb', File.join(name, 'lib', 'middleman_extension.rb') template 'extension/lib/lib.rb', File.join(name, 'lib', "#{name}.rb") + template 'extension/lib/lib/extension.rb', File.join(name, 'lib', name, "extension.rb") template 'extension/features/support/env.rb', File.join(name, 'features', 'support', 'env.rb') empty_directory File.join(name, 'fixtures') end diff --git a/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb b/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb index 8a3c5dc6..48038a71 100644 --- a/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb +++ b/middleman-cli/lib/middleman-cli/templates/extension/lib/lib.rb @@ -1,38 +1,6 @@ -# Require core library -require 'middleman-core' +require "middleman-core" -# Extension namespace -class MyExtension < ::Middleman::Extension - option :my_option, 'default', 'An example option' - - def initialize(app, options_hash={}, &block) - # Call super to build options from the options_hash - super - - # Require libraries only when activated - # require 'necessary/library' - - # set up your extension - # puts options.my_option - end - - def after_configuration - # Do something - end - - # A Sitemap Manipulator - # def manipulate_resource_list(resources) - # end - - # helpers do - # def a_helper - # end - # end +Middleman::Extensions.register :<%= name %> do + require "my-extension/extension" + MyExtension end - -# Register extensions which can be activated -# Make sure we have the version of Middleman we expect -# Name param may be omited, it will default to underscored -# version of class name - -# MyExtension.register(:my_extension) diff --git a/middleman-cli/lib/middleman-cli/templates/extension/lib/lib/extension.rb b/middleman-cli/lib/middleman-cli/templates/extension/lib/lib/extension.rb new file mode 100644 index 00000000..f831386f --- /dev/null +++ b/middleman-cli/lib/middleman-cli/templates/extension/lib/lib/extension.rb @@ -0,0 +1,31 @@ +# Require core library +require 'middleman-core' + +# Extension namespace +class MyExtension < ::Middleman::Extension + option :my_option, 'default', 'An example option' + + def initialize(app, options_hash={}, &block) + # Call super to build options from the options_hash + super + + # Require libraries only when activated + # require 'necessary/library' + + # set up your extension + # puts options.my_option + end + + def after_configuration + # Do something + end + + # A Sitemap Manipulator + # def manipulate_resource_list(resources) + # end + + # helpers do + # def a_helper + # end + # end +end diff --git a/middleman-cli/lib/middleman-cli/templates/extension/lib/middleman_extension.rb b/middleman-cli/lib/middleman-cli/templates/extension/lib/middleman_extension.rb deleted file mode 100644 index 6fba3c06..00000000 --- a/middleman-cli/lib/middleman-cli/templates/extension/lib/middleman_extension.rb +++ /dev/null @@ -1 +0,0 @@ -require '<%= name %>' From ba0416b330973af9f543f0a40e00f1c2aaabe6c1 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 20 Dec 2015 13:47:18 -0800 Subject: [PATCH 007/178] Set min version in gemspec --- CHANGELOG.md | 2 +- middleman-cli/middleman-cli.gemspec | 2 +- middleman/middleman.gemspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 158de44e..e5351d07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,7 @@ master * Add `resources` class method to extensions to allow simple string-based resource generation. * rename `app.add_to_instance` to `Extension.expose_to_application` for adding extension-local methods to the shared app instance. * rename `app.add_to_config_context` to `Extension.expose_to_config` for adding extension-local methods to the sandboxed scope of `config.rb` -* Add `Extension.expose_to_templates`, which auto binds copies of extension-local methods into a Template context. +* Add `Extension.expose_to_template`, which auto binds copies of extension-local methods into a Template context. * Remove side-loading of CLI tasks from `tasks/` * Add the option of naming `config.rb` as `middleman.rb`. * Builder extracted from Thor. `after_build` hook now passes an instance of a Builder instead of the Thor CLI. diff --git a/middleman-cli/middleman-cli.gemspec b/middleman-cli/middleman-cli.gemspec index 05f5c456..f2719efc 100644 --- a/middleman-cli/middleman-cli.gemspec +++ b/middleman-cli/middleman-cli.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0") s.executable = 'middleman' s.require_path = 'lib' - s.required_ruby_version = '>= 1.9.3' + s.required_ruby_version = '>= 2.0.0' # CLI s.add_dependency('thor', ['>= 0.17.0', '< 2.0']) diff --git a/middleman/middleman.gemspec b/middleman/middleman.gemspec index 33167d3d..06dd3144 100644 --- a/middleman/middleman.gemspec +++ b/middleman/middleman.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.files = `git ls-files -z`.split("\0") s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0") s.require_path = 'lib' - s.required_ruby_version = '>= 1.9.3' + s.required_ruby_version = '>= 2.0.0' s.add_dependency('middleman-core', Middleman::VERSION) s.add_dependency('middleman-cli', Middleman::VERSION) From a5821bccec03a3b86349d0eb2dfa7a2bfb199dae Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 21 Dec 2015 13:07:01 -0800 Subject: [PATCH 008/178] Fix asset hash with query string or hash params. Closes #1411 --- middleman-core/features/asset_hash.feature | 24 ++++++++++ .../asset-hash-app/source/index.html.erb | 3 ++ .../fixtures/asset-hash-app/source/layout.erb | 6 +-- .../asset-hash-app/source/other.html.erb | 3 ++ .../source/stylesheets/fragment.css.scss | 7 +++ .../asset-hash-host-app/source/index.html.erb | 3 ++ .../asset-hash-host-app/source/layout.erb | 6 +-- .../asset-hash-host-app/source/other.html.erb | 3 ++ .../source/stylesheets/fragment.css.scss | 3 ++ middleman-core/lib/middleman-core/util.rb | 48 +++++++++++-------- 10 files changed, 79 insertions(+), 27 deletions(-) create mode 100644 middleman-core/fixtures/asset-hash-app/source/stylesheets/fragment.css.scss diff --git a/middleman-core/features/asset_hash.feature b/middleman-core/features/asset_hash.feature index 4e9b293d..78755818 100644 --- a/middleman-core/features/asset_hash.feature +++ b/middleman-core/features/asset_hash.feature @@ -64,9 +64,13 @@ Feature: Assets get file hashes appended to them and references to them are upda 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 '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"' + And I should see 'src="images/100px-5fd6fb90.jpg?test"' + 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"' And I should see 'src="../javascripts/application-1d8d5276.js"' @@ -75,6 +79,9 @@ Feature: Assets get file hashes appended to them and references to them are upda Then I should see 'href="../stylesheets/site-d2959d87.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"' + And I should see 'src="../images/100px-5fd6fb90.jpg?#test"' + 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" @@ -87,6 +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")' Scenario: Hashed assets work with Slim Given the Server is running at "asset-hash-app" @@ -99,13 +111,25 @@ 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-e587b659.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-7af0b5ab.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"' 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"' 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" + 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: The asset hash should change when a SASS partial changes Given the Server is running at "asset-hash-app" diff --git a/middleman-core/fixtures/asset-hash-app/source/index.html.erb b/middleman-core/fixtures/asset-hash-app/source/index.html.erb index 59a9c54f..de017654 100644 --- a/middleman-core/fixtures/asset-hash-app/source/index.html.erb +++ b/middleman-core/fixtures/asset-hash-app/source/index.html.erb @@ -4,6 +4,9 @@

Image url:

+<%= image_tag('100px.jpg?test') %> +<%= image_tag('100px.jpg?#test') %> +<%= image_tag('100px.jpg#test') %>

Ignored path:

diff --git a/middleman-core/fixtures/asset-hash-app/source/layout.erb b/middleman-core/fixtures/asset-hash-app/source/layout.erb index a21259a3..3a1079a7 100644 --- a/middleman-core/fixtures/asset-hash-app/source/layout.erb +++ b/middleman-core/fixtures/asset-hash-app/source/layout.erb @@ -3,16 +3,16 @@ - <%= stylesheet_link_tag "site" %> + <%= stylesheet_link_tag "site", "fragment" %> <%= javascript_include_tag "application" %> <%= yield_content :head %> - +
<%= yield %>
- + diff --git a/middleman-core/fixtures/asset-hash-app/source/other.html.erb b/middleman-core/fixtures/asset-hash-app/source/other.html.erb index 2e6f276f..cc258936 100644 --- a/middleman-core/fixtures/asset-hash-app/source/other.html.erb +++ b/middleman-core/fixtures/asset-hash-app/source/other.html.erb @@ -1,2 +1,5 @@

Image url:

+ + + diff --git a/middleman-core/fixtures/asset-hash-app/source/stylesheets/fragment.css.scss b/middleman-core/fixtures/asset-hash-app/source/stylesheets/fragment.css.scss new file mode 100644 index 00000000..4e175489 --- /dev/null +++ b/middleman-core/fixtures/asset-hash-app/source/stylesheets/fragment.css.scss @@ -0,0 +1,7 @@ +#main { + padding: 50px; + background-image: image-url('100px.jpg'); + background-image: image-url('100px.jpg?test'); + background-image: image-url('100px.jpg?#test'); + background-image: image-url('100px.jpg#test'); +} 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 3616ba64..ea81c790 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 @@ -4,3 +4,6 @@

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/fixtures/asset-hash-host-app/source/layout.erb b/middleman-core/fixtures/asset-hash-host-app/source/layout.erb index 443b3645..a6aa4a0c 100644 --- a/middleman-core/fixtures/asset-hash-host-app/source/layout.erb +++ b/middleman-core/fixtures/asset-hash-host-app/source/layout.erb @@ -3,15 +3,15 @@ - <%= stylesheet_link_tag "site" %> + <%= stylesheet_link_tag "site", "fragment" %> <%= yield_content :head %> - +
<%= yield %>
- + diff --git a/middleman-core/fixtures/asset-hash-host-app/source/other.html.erb b/middleman-core/fixtures/asset-hash-host-app/source/other.html.erb index 2e6f276f..cc258936 100644 --- a/middleman-core/fixtures/asset-hash-host-app/source/other.html.erb +++ b/middleman-core/fixtures/asset-hash-host-app/source/other.html.erb @@ -1,2 +1,5 @@

Image url:

+ + + diff --git a/middleman-core/fixtures/asset-hash-host-app/source/stylesheets/fragment.css.scss b/middleman-core/fixtures/asset-hash-host-app/source/stylesheets/fragment.css.scss index b169b432..4e175489 100644 --- a/middleman-core/fixtures/asset-hash-host-app/source/stylesheets/fragment.css.scss +++ b/middleman-core/fixtures/asset-hash-host-app/source/stylesheets/fragment.css.scss @@ -1,4 +1,7 @@ #main { padding: 50px; + background-image: image-url('100px.jpg'); + background-image: image-url('100px.jpg?test'); + background-image: image-url('100px.jpg?#test'); background-image: image-url('100px.jpg#test'); } diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index db29cf92..1ea5ace8 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -201,31 +201,37 @@ module Middleman Contract IsA['Middleman::Application'], String, String, Hash => String def asset_url(app, path, prefix='', options={}) # Don't touch assets which already have a full path - if path.include?('//') || path.start_with?('data:') - path - else # rewrite paths to use their destination path - result = if resource = app.sitemap.find_resource_by_destination_path(url_for(app, path)) + return path if path.include?('//') || path.start_with?('data:') + + uri = URI(path) + path = uri.path + + result = if resource = app.sitemap.find_resource_by_destination_path(url_for(app, path)) + resource.url + else + path = File.join(prefix, path) + if resource = app.sitemap.find_resource_by_path(path) resource.url else - path = File.join(prefix, path) - if resource = app.sitemap.find_resource_by_path(path) - resource.url - else - File.join(app.config[:http_prefix], path) - end - end - - if options[:relative] != true - result - else - unless options[:current_resource] - raise ArgumentError, '#asset_url must be run in a context with current_resource if relative: true' - end - - current_dir = Pathname('/' + options[:current_resource].destination_path) - Pathname(result).relative_path_from(current_dir.dirname).to_s + File.join(app.config[:http_prefix], path) end end + + final_result = if options[:relative] != true + result + else + unless options[:current_resource] + raise ArgumentError, '#asset_url must be run in a context with current_resource if relative: true' + end + + current_dir = Pathname('/' + options[:current_resource].destination_path) + Pathname(result).relative_path_from(current_dir.dirname).to_s + end + + result_uri = URI(final_result) + result_uri.query = uri.query + result_uri.fragment = uri.fragment + result_uri.to_s end # Given a source path (referenced either absolutely or relatively) From 4a8cd4c3d24210bbe50421bf871ba4940b31cf9e Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 21 Dec 2015 13:27:44 -0800 Subject: [PATCH 009/178] fix extension test --- middleman-core/features/cli_extension.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/features/cli_extension.feature b/middleman-core/features/cli_extension.feature index b762664c..5385a622 100644 --- a/middleman-core/features/cli_extension.feature +++ b/middleman-core/features/cli_extension.feature @@ -9,6 +9,6 @@ Feature: Middleman New Extension CLI | Rakefile | | my-extension-library.gemspec | | features/support/env.rb | - | lib/middleman_extension.rb | + | lib/my-extension-library/extension.rb | | lib/my-extension-library.rb | | .gitignore | From 3fdd963923ffbf1a98d6a828bd34d53aba8cc829 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Wed, 23 Dec 2015 23:54:04 +0900 Subject: [PATCH 010/178] Test against 2.2.4 that is the latest of Ruby 2.2 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f3150364..21396add 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_script: - bundle update rvm: - ruby-head - - 2.2.2 + - 2.2.4 - 2.1 - 2.0 os: From 2dcd2c5b1daf6c63e0bbcddb1a961effa323502c Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Sat, 26 Dec 2015 01:11:15 +0900 Subject: [PATCH 011/178] Test against Ruby 2.3.0 on Travis CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 21396add..528eef8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ before_script: - bundle update rvm: - ruby-head + - 2.3.0 - 2.2.4 - 2.1 - 2.0 From e56227c945ba430e0fe91094ae36b59dac9a6682 Mon Sep 17 00:00:00 2001 From: Ryunosuke SATO Date: Wed, 23 Dec 2015 23:29:16 +0900 Subject: [PATCH 012/178] Exit with error code on `init` command failed --- middleman-cli/lib/middleman-cli/init.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-cli/lib/middleman-cli/init.rb b/middleman-cli/lib/middleman-cli/init.rb index 5bdfb6e3..469d9d4c 100644 --- a/middleman-cli/lib/middleman-cli/init.rb +++ b/middleman-cli/lib/middleman-cli/init.rb @@ -39,7 +39,7 @@ module Middleman::Cli rescue ::OpenURI::HTTPError say "Template `#{options[:template]}` not found in Middleman Directory." say 'Did you mean to use a full `user/repo` path?' - exit + exit 1 end else repo_name, repo_branch = options[:template].split('#') @@ -55,7 +55,7 @@ module Middleman::Cli unless File.directory?(dir) say 'Git clone failed, maybe the url is invalid or you don\'t have the permissions?', :red - exit + exit 1 end inside(target) do From d464162e8e5bdf7045748fe96a58180cd957e6a4 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Mon, 28 Dec 2015 17:40:21 -0800 Subject: [PATCH 013/178] Fix #1715 by passing along path in DefaultHelpers#asset_url. --- .../lib/middleman-core/core_extensions/default_helpers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 8b10e456..3187bf22 100644 --- a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb @@ -201,9 +201,9 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # @param [String] prefix The type prefix (such as "images") # @param [Hash] options Additional options. # @return [String] The fully qualified asset url - def asset_url(_path, prefix='', options={}) + def asset_url(path, prefix='', options={}) options_with_resource = options.merge(current_resource: current_resource) - ::Middleman::Util.asset_url(app, prefix, options_with_resource) + ::Middleman::Util.asset_url(app, path, prefix, options_with_resource) end # Given a source path (referenced either absolutely or relatively) From 412f6ac1fc77a3520aee1a3480086b978b58b213 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Mon, 28 Dec 2015 20:03:47 -0800 Subject: [PATCH 014/178] Fix #1721 by passing through options to url_for. --- middleman-core/lib/middleman-core/util.rb | 19 ++++++++----------- .../spec/middleman-core/util_spec.rb | 11 ++++++++++- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 1ea5ace8..4097c9dd 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -203,10 +203,14 @@ module Middleman # Don't touch assets which already have a full path return path if path.include?('//') || path.start_with?('data:') + if options[:relative] && !options[:current_resource] + raise ArgumentError, '#asset_url must be run in a context with current_resource if relative: true' + end + uri = URI(path) path = uri.path - result = if resource = app.sitemap.find_resource_by_destination_path(url_for(app, path)) + result = if resource = app.sitemap.find_resource_by_destination_path(url_for(app, path, options)) resource.url else path = File.join(prefix, path) @@ -217,15 +221,11 @@ module Middleman end end - final_result = if options[:relative] != true - result - else - unless options[:current_resource] - raise ArgumentError, '#asset_url must be run in a context with current_resource if relative: true' - end - + final_result = if options[:relative] current_dir = Pathname('/' + options[:current_resource].destination_path) Pathname(result).relative_path_from(current_dir.dirname).to_s + else + result end result_uri = URI(final_result) @@ -296,9 +296,6 @@ module Middleman else resource_url end - else - # If they explicitly asked for relative links but we can't find a resource... - raise "No resource exists at #{url}" if relative end # Support a :query option that can be a string or hash diff --git a/middleman-core/spec/middleman-core/util_spec.rb b/middleman-core/spec/middleman-core/util_spec.rb index ccac1885..ce175e35 100644 --- a/middleman-core/spec/middleman-core/util_spec.rb +++ b/middleman-core/spec/middleman-core/util_spec.rb @@ -98,6 +98,15 @@ describe Middleman::Util do end end + it "returns path relative to the provided current_resource" do + Given.fixture 'clean-dir-app' + Given.file 'source/a-path/index.html', '' + Given.file 'source/a-path/images/blank.gif', '' + @mm = Middleman::Application.new + current_resource = @mm.sitemap.find_resource_by_path('a-path/index.html') + expect( Middleman::Util.asset_url( @mm, 'images/blank.gif', 'images', current_resource: current_resource ) ).to eq '/a-path/images/blank.gif' + end + context "when relative is true" do before(:each) do @@ -106,7 +115,7 @@ describe Middleman::Util do end it "returns path relative to the provided current_resource" do - current_resource = instance_double("Middleman::Sitemap::Resource", destination_path: 'a-path/index.html') + current_resource = instance_double("Middleman::Sitemap::Resource", destination_path: 'a-path/index.html', path: 'a-path/index.html') expect( Middleman::Util.asset_url( @mm, 'blank.gif', 'images', current_resource: current_resource, relative: true ) ).to eq '../images/blank.gif' end From 9311a72e4aa45813c06c7387883ae0734766e234 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Mon, 28 Dec 2015 20:50:55 -0800 Subject: [PATCH 015/178] Use our relative_path_from_resource helper in asset_url. --- middleman-core/lib/middleman-core/util.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 4097c9dd..ffd76eb6 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -221,12 +221,7 @@ module Middleman end end - final_result = if options[:relative] - current_dir = Pathname('/' + options[:current_resource].destination_path) - Pathname(result).relative_path_from(current_dir.dirname).to_s - else - result - end + final_result = URI.encode(relative_path_from_resource(options[:current_resource], result, options[:relative])) result_uri = URI(final_result) result_uri.query = uri.query From b0a4d539636610ea6dd4d0d79dafd27bd806612a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20G=C3=BCnnewig?= Date: Fri, 1 Jan 2016 20:36:01 +0100 Subject: [PATCH 016/178] Added phantomjs as gem to make test suite pass --- Gemfile | 1 + middleman-core/features/support/env.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 18832cec..b446cdcd 100644 --- a/Gemfile +++ b/Gemfile @@ -28,6 +28,7 @@ gem 'rubydns', '~> 1.0.1', require: false # To test javascript gem 'poltergeist', '~> 1.8', require: false +gem 'phantomjs', '~> 1.9.8.0', require: false # For less, note there is no compatible JS runtime for windows gem 'therubyrhino', '>= 2.0', platforms: :jruby diff --git a/middleman-core/features/support/env.rb b/middleman-core/features/support/env.rb index 29799086..77cfbb06 100644 --- a/middleman-core/features/support/env.rb +++ b/middleman-core/features/support/env.rb @@ -5,7 +5,7 @@ require 'sassc' require 'simplecov' SimpleCov.root(File.expand_path(File.dirname(__FILE__) + '/../..')) -require 'capybara/poltergeist' +require 'phantomjs/poltergeist' Capybara.javascript_driver = :poltergeist require 'coveralls' From bdeb19059aa64ab3aa9320dcdafd27a6e70dddb2 Mon Sep 17 00:00:00 2001 From: Ulrich Gabor Date: Tue, 5 Jan 2016 15:08:26 +0100 Subject: [PATCH 017/178] Test for issue 1709; parent relations with localized and non-localized sources --- .../features/i18n_mixed_sources.feature | 38 +++++++++++++++++++ .../fixtures/i18n-mixed-sources/config.rb | 1 + .../i18n-mixed-sources/locales/en.yml | 4 ++ .../i18n-mixed-sources/locales/es.yml | 4 ++ .../i18n-mixed-sources/source/a/sub.html.erb | 9 +++++ .../source/b/index.html.erb | 9 +++++ .../i18n-mixed-sources/source/index.html.erb | 9 +++++ .../source/localizable/a/index.html.erb | 9 +++++ .../source/localizable/b/sub.html.erb | 9 +++++ .../source/localizable/index.html.erb | 9 +++++ 10 files changed, 101 insertions(+) create mode 100644 middleman-core/features/i18n_mixed_sources.feature create mode 100644 middleman-core/fixtures/i18n-mixed-sources/config.rb create mode 100644 middleman-core/fixtures/i18n-mixed-sources/locales/en.yml create mode 100644 middleman-core/fixtures/i18n-mixed-sources/locales/es.yml create mode 100644 middleman-core/fixtures/i18n-mixed-sources/source/a/sub.html.erb create mode 100644 middleman-core/fixtures/i18n-mixed-sources/source/b/index.html.erb create mode 100644 middleman-core/fixtures/i18n-mixed-sources/source/index.html.erb create mode 100644 middleman-core/fixtures/i18n-mixed-sources/source/localizable/a/index.html.erb create mode 100644 middleman-core/fixtures/i18n-mixed-sources/source/localizable/b/sub.html.erb create mode 100644 middleman-core/fixtures/i18n-mixed-sources/source/localizable/index.html.erb diff --git a/middleman-core/features/i18n_mixed_sources.feature b/middleman-core/features/i18n_mixed_sources.feature new file mode 100644 index 00000000..c287d871 --- /dev/null +++ b/middleman-core/features/i18n_mixed_sources.feature @@ -0,0 +1,38 @@ +Feature: i18n merging path trees + + Scenario: Mixing localized and non-localized sources and merging the path trees (see issue #1709) + Given a fixture app "i18n-test-app" + And a file named "config.rb" with: + """ + activate :i18n, mount_at_root: :en, langs: [:en, :es] + """ + Given the Server is running at "i18n-mixed-sources" + + When I go to "/" + Then I should see "Current locale: en" + Then I should see "path: is-localized Home" + When I go to "/es" + Then I should see "Current locale: es" + Then I should see "path: is-localized Home" + + When I go to "/a/" + Then I should see "Current locale: en" + Then I should see "path: is-localized Home # a/index.html.erb" + When I go to "/es/a/" + Then I should see "Current locale: es" + Then I should see "path: is-localized Home # a/index.html.erb" + + When I go to "/b/" + Then I should see "Current locale: en" + Then I should see "path: is-localized Home # b/index.html.erb" + + When I go to "/a/sub.html" + Then I should see "Current locale: en" + Then I should see "path: is-localized Home # a/index.html.erb # a/sub.html.erb" + + When I go to "/b/sub.html" + Then I should see "Current locale: en" + Then I should see "path: is-localized Home # b/index.html.erb # b/sub.html.erb" + Then I should see "Current locale: es" + When I go to "/es/b/sub.html" + Then I should see "path: is-localized Home # b/index.html.erb # b/sub.html.erb" diff --git a/middleman-core/fixtures/i18n-mixed-sources/config.rb b/middleman-core/fixtures/i18n-mixed-sources/config.rb new file mode 100644 index 00000000..4815436f --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/config.rb @@ -0,0 +1 @@ +activate :i18n, mount_at_root: :en, langs: [:en, :es] diff --git a/middleman-core/fixtures/i18n-mixed-sources/locales/en.yml b/middleman-core/fixtures/i18n-mixed-sources/locales/en.yml new file mode 100644 index 00000000..91519342 --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/locales/en.yml @@ -0,0 +1,4 @@ +--- +en: + greetings: "Howdy" + hi: "Hello" \ No newline at end of file diff --git a/middleman-core/fixtures/i18n-mixed-sources/locales/es.yml b/middleman-core/fixtures/i18n-mixed-sources/locales/es.yml new file mode 100644 index 00000000..38c7e31e --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/locales/es.yml @@ -0,0 +1,4 @@ +--- +es: + greetings: "Como Esta?" + hi: "Hola" \ No newline at end of file diff --git a/middleman-core/fixtures/i18n-mixed-sources/source/a/sub.html.erb b/middleman-core/fixtures/i18n-mixed-sources/source/a/sub.html.erb new file mode 100644 index 00000000..b92d02f1 --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/source/a/sub.html.erb @@ -0,0 +1,9 @@ +--- +title: a/sub.html.erb +--- +Current locale: <%= I18n.locale %> +path: <%= +hierarchy = [current_page] +hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent +hierarchy.collect {|page| page.data.title }.join(" # ") +%> diff --git a/middleman-core/fixtures/i18n-mixed-sources/source/b/index.html.erb b/middleman-core/fixtures/i18n-mixed-sources/source/b/index.html.erb new file mode 100644 index 00000000..c238d925 --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/source/b/index.html.erb @@ -0,0 +1,9 @@ +--- +title: b/index.html.erb +--- +Current locale: <%= I18n.locale %> +path: <%= +hierarchy = [current_page] +hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent +hierarchy.collect {|page| page.data.title }.join(" # ") +%> diff --git a/middleman-core/fixtures/i18n-mixed-sources/source/index.html.erb b/middleman-core/fixtures/i18n-mixed-sources/source/index.html.erb new file mode 100644 index 00000000..1d47ed2e --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/source/index.html.erb @@ -0,0 +1,9 @@ +--- +title: non-localized Home +--- +Current locale: <%= I18n.locale %> +path: <%= +hierarchy = [current_page] +hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent +hierarchy.collect {|page| page.data.title }.join(" # ") +%> diff --git a/middleman-core/fixtures/i18n-mixed-sources/source/localizable/a/index.html.erb b/middleman-core/fixtures/i18n-mixed-sources/source/localizable/a/index.html.erb new file mode 100644 index 00000000..dc8aa51f --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/source/localizable/a/index.html.erb @@ -0,0 +1,9 @@ +--- +title: a/index.html.erb +--- +Current locale: <%= I18n.locale %> +path: <%= +hierarchy = [current_page] +hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent +hierarchy.collect {|page| page.data.title }.join(" # ") +%> diff --git a/middleman-core/fixtures/i18n-mixed-sources/source/localizable/b/sub.html.erb b/middleman-core/fixtures/i18n-mixed-sources/source/localizable/b/sub.html.erb new file mode 100644 index 00000000..40d65942 --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/source/localizable/b/sub.html.erb @@ -0,0 +1,9 @@ +--- +title: b/sub.html.erb +--- +Current locale: <%= I18n.locale %> +path: <%= +hierarchy = [current_page] +hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent +hierarchy.collect {|page| page.data.title }.join(" # ") +%> diff --git a/middleman-core/fixtures/i18n-mixed-sources/source/localizable/index.html.erb b/middleman-core/fixtures/i18n-mixed-sources/source/localizable/index.html.erb new file mode 100644 index 00000000..79449a82 --- /dev/null +++ b/middleman-core/fixtures/i18n-mixed-sources/source/localizable/index.html.erb @@ -0,0 +1,9 @@ +--- +title: is-localized Home +--- +Current locale: <%= I18n.locale %> +path: <%= +hierarchy = [current_page] +hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent +hierarchy.collect {|page| page.data.title }.join(" # ") +%> From 1ca5be7b1927c4b2fa061ac3955bb121bb186fb8 Mon Sep 17 00:00:00 2001 From: Ulrich Gabor Date: Tue, 5 Jan 2016 15:10:49 +0100 Subject: [PATCH 018/178] Tests for issue #1702 --- .../features/encoding_option.feature | 23 +++++++++++++++++++ .../fixtures/i-8859-1-app/config.rb | 1 + .../i-8859-1-app/source/index.html.erb | 1 + .../step_definitions/server_steps.rb | 4 ++++ 4 files changed, 29 insertions(+) create mode 100644 middleman-core/features/encoding_option.feature create mode 100644 middleman-core/fixtures/i-8859-1-app/config.rb create mode 100644 middleman-core/fixtures/i-8859-1-app/source/index.html.erb diff --git a/middleman-core/features/encoding_option.feature b/middleman-core/features/encoding_option.feature new file mode 100644 index 00000000..b2aeed6b --- /dev/null +++ b/middleman-core/features/encoding_option.feature @@ -0,0 +1,23 @@ +# encoding: iso-8859-1 +Feature: encoding option + + Scenario: No encoding set + Given a fixture app "clean-app" + Given the Server is running at "clean-app" + + When I go to "/index.html" + Then the "Content-Type" header should contain "text/html" + Then the "Content-Type" header should contain "charset=utf-8" + + Scenario: Custom encoding set + Given a fixture app "i-8859-1-app" + And a file named "config.rb" with: + """ + set :encoding, "ISO-8859-1" + """ + Given the Server is running at "i-8859-1-app" + + When I go to "/index.html" + Then the "Content-Type" header should contain "text/html" + Then the "Content-Type" header should contain "charset=iso-8859-1" + Then I should see "äöü" diff --git a/middleman-core/fixtures/i-8859-1-app/config.rb b/middleman-core/fixtures/i-8859-1-app/config.rb new file mode 100644 index 00000000..3252ee63 --- /dev/null +++ b/middleman-core/fixtures/i-8859-1-app/config.rb @@ -0,0 +1 @@ +set :encoding, "ISO-8859-1" diff --git a/middleman-core/fixtures/i-8859-1-app/source/index.html.erb b/middleman-core/fixtures/i-8859-1-app/source/index.html.erb new file mode 100644 index 00000000..3c015801 --- /dev/null +++ b/middleman-core/fixtures/i-8859-1-app/source/index.html.erb @@ -0,0 +1 @@ +äöü 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 9ff79474..7defbbc0 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -75,6 +75,10 @@ Then /^the content type should be "([^\"]*)"$/ do |expected| expect(page.response_headers['Content-Type']).to start_with expected end +Then /^the "([^\"]*)" header should contain "([^\"]*)"$/ do |header, expected| + expect(page.response_headers[header]).to include expected +end + Then /^I should see "([^\"]*)"$/ do |expected| expect(page.body).to include expected end From 298b3909ed970cc7c5e6c70af45d073e16c55039 Mon Sep 17 00:00:00 2001 From: Ulrich Gabor Date: Tue, 5 Jan 2016 15:11:14 +0100 Subject: [PATCH 019/178] First fix to actually use the encoding option again --- middleman-core/lib/middleman-core/application.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index ff2d4e4f..5818548b 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -253,11 +253,6 @@ module Middleman # Initialize the Sitemap @sitemap = ::Middleman::Sitemap::Store.new(self) - if Object.const_defined?(:Encoding) - Encoding.default_internal = config[:encoding] - Encoding.default_external = config[:encoding] - end - ::Middleman::Extension.clear_after_extension_callbacks after_configuration_eval(&method(:prune_tilt_templates)) @@ -276,6 +271,10 @@ module Middleman # Eval config. evaluate_configuration! + if Object.const_defined?(:Encoding) + Encoding.default_external = config[:encoding] + end + # Run any `configure` blocks for the current environment. execute_callbacks([:configure, config[:environment]]) From 1605f425e87248590e739187045c00a6817fd7c2 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 5 Jan 2016 10:58:11 -0800 Subject: [PATCH 020/178] Fixes #1733 --- .rubocop.yml | 2 +- .../features/cli/preview_server.feature | 7 +++++-- .../features/i18n_mixed_sources.feature | 3 ++- .../lib/middleman-core/core_extensions/i18n.rb | 17 +++++++++++------ .../sitemap/extensions/traversal.rb | 14 +++++++++++++- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8346729e..c1b86127 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -11,7 +11,7 @@ AllCops: - '**/bin/**/*' - 'middleman-core/lib/middleman-core/step_definitions/**/*' - 'middleman-core/lib/vendored-middleman-deps/**/*' - - 'middleman-cli/lib/middleman-templates/**/*' + - 'middleman-cli/lib/middleman-cli/templates/**/*' - 'middleman-core/fixtures/**/*' - 'middleman-core/features/**/*' - 'middleman-core/spec/**/*' diff --git a/middleman-core/features/cli/preview_server.feature b/middleman-core/features/cli/preview_server.feature index ab65683e..5fedc091 100644 --- a/middleman-core/features/cli/preview_server.feature +++ b/middleman-core/features/cli/preview_server.feature @@ -115,6 +115,7 @@ Feature: Run the preview server Inspect your site configuration at "http://127.0.0.1:4567/__middleman" """ + @wip Scenario: Start the server with bind address 127.0.0.5 This will have no hostname attached because the hosts file, the DNS server @@ -469,7 +470,8 @@ Feature: Run the preview server Inspect your site configuration at "http://www.example.com:4567/__middleman", "http://127.0.0.1:4567/__middleman" """ - @ruby-2.1 + @ruby-2.1 + @wip Scenario: Start the server with server name "host.local" and the link local name server is used to resolve the server name To make the mdns resolver resolve a name, it needs to end with ".local". @@ -501,7 +503,8 @@ Feature: Run the preview server Inspect your site configuration at "http://host.local:4567/__middleman", "http://127.0.0.1:4567/__middleman" """ - @ruby-2.1 + @ruby-2.1 + @wip Scenario: Start the server with server name "host" and the link local name server is used to resolve the server name To make the mdns resolver resolve a name, it needs to end with ".local". If diff --git a/middleman-core/features/i18n_mixed_sources.feature b/middleman-core/features/i18n_mixed_sources.feature index c287d871..7ea92028 100644 --- a/middleman-core/features/i18n_mixed_sources.feature +++ b/middleman-core/features/i18n_mixed_sources.feature @@ -33,6 +33,7 @@ Feature: i18n merging path trees When I go to "/b/sub.html" Then I should see "Current locale: en" Then I should see "path: is-localized Home # b/index.html.erb # b/sub.html.erb" - Then I should see "Current locale: es" + When I go to "/es/b/sub.html" + Then I should see "Current locale: es" Then I should see "path: is-localized Home # b/index.html.erb # b/sub.html.erb" diff --git a/middleman-core/lib/middleman-core/core_extensions/i18n.rb b/middleman-core/lib/middleman-core/core_extensions/i18n.rb index 1b59a385..99731402 100644 --- a/middleman-core/lib/middleman-core/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-core/core_extensions/i18n.rb @@ -196,6 +196,16 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension @lookup[lookup_path] && @lookup[lookup_path][locale] end + Contract Symbol => String + def path_root(locale) + if (options[:mount_at_root] == locale) || (options[:mount_at_root].nil? && locales[0] == locale) + '/' + else + replacement = options[:locale_map].fetch(locale, locale) + options[:path].sub(':locale', replacement.to_s).sub(':lang', replacement.to_s) # Backward compat + end + end + private def on_file_changed(_updated_files, _removed_files) @@ -267,12 +277,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension path = "#{partially_localized_path}/#{File.basename(path)}" - prefix = if (options[:mount_at_root] == locale) || (options[:mount_at_root].nil? && locales[0] == locale) - '/' - else - replacement = options[:locale_map].fetch(locale, locale) - options[:path].sub(':locale', replacement.to_s).sub(':lang', replacement.to_s) # Backward compat - end + prefix = path_root(locale) # path needs to be changed if file has a localizable extension. (options[mount_at_root] == locale) path = ::Middleman::Util.normalize_path( diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb b/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb index e542b503..2b456df8 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/traversal.rb @@ -2,10 +2,22 @@ module Middleman module Sitemap module Extensions module Traversal + def traversal_root + root = if !@app.extensions[:i18n] + '/' + else + @app.extensions[:i18n].path_root(::I18n.locale) + end + + root.sub(/^\//, '') + end + # This resource's parent resource # @return [Middleman::Sitemap::Resource, nil] def parent - parts = path.split('/') + root = path.sub(/^#{::Regexp.escape(traversal_root)}/, '') + parts = root.split('/') + tail = parts.pop is_index = (tail == @app.config[:index_file]) From 133c02d05c65493b8628c58276af111c37117ee5 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Thu, 7 Jan 2016 09:43:35 +0900 Subject: [PATCH 021/178] Add SVG to the default list of gzipped exts --- middleman-core/lib/middleman-core/extensions/gzip.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/extensions/gzip.rb b/middleman-core/lib/middleman-core/extensions/gzip.rb index 2620eb6f..cc1a7fea 100644 --- a/middleman-core/lib/middleman-core/extensions/gzip.rb +++ b/middleman-core/lib/middleman-core/extensions/gzip.rb @@ -10,7 +10,7 @@ # to .html, .htm, .js and .css. # class Middleman::Extensions::Gzip < ::Middleman::Extension - option :exts, %w(.js .css .html .htm), 'File extensions to Gzip when building.' + option :exts, %w(.js .css .html .htm .svg), 'File extensions to Gzip when building.' option :ignore, [], 'Patterns to avoid gzipping' option :overwrite, false, 'Overwrite original files instead of adding .gz extension.' From a7631b2f0d0ed42e485b50ae747dfd9845c5398a Mon Sep 17 00:00:00 2001 From: Tiou Lims Date: Thu, 7 Jan 2016 23:23:50 +0800 Subject: [PATCH 022/178] Fixes #1723 --- middleman-core/lib/middleman-core/load_paths.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/load_paths.rb b/middleman-core/lib/middleman-core/load_paths.rb index 7daffe4c..d8937864 100644 --- a/middleman-core/lib/middleman-core/load_paths.rb +++ b/middleman-core/lib/middleman-core/load_paths.rb @@ -22,7 +22,7 @@ module Middleman # Set BUNDLE_GEMFILE and run Bundler setup. Raises an exception if there is no Gemfile def setup_bundler - ENV['BUNDLE_GEMFILE'] ||= findup('Gemfile', ENV['MM_ROOT']) + ENV['BUNDLE_GEMFILE'] ||= File.join(findup('Gemfile', ENV['MM_ROOT']), "Gemfile") unless File.exist?(ENV['BUNDLE_GEMFILE']) ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__) From 0563523a81aa1ca9aa80d0ce9614029dbb1ba55a Mon Sep 17 00:00:00 2001 From: Nick Muerdter Date: Fri, 8 Jan 2016 14:56:42 -0700 Subject: [PATCH 023/178] Add rewrite_ignore option to asset_hash extension. This allows for configuring the files that will be skipped when performing URL rewriting on the file content. This differs from the existing `ignore` option, which configures the files that won't have hashes added to the filename. --- middleman-core/features/asset_hash.feature | 39 +++++++++++++++++++ .../middleman-core/extensions/asset_hash.rb | 2 + .../middleware/inline_url_rewriter.rb | 12 +++++- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/middleman-core/features/asset_hash.feature b/middleman-core/features/asset_hash.feature index 78755818..0a05c1a6 100644 --- a/middleman-core/features/asset_hash.feature +++ b/middleman-core/features/asset_hash.feature @@ -203,6 +203,45 @@ Feature: Assets get file hashes appended to them and references to them are upda | javascripts/application-1d8d5276.js | | stylesheets/site-7474cadd.css | + Scenario: Hashed-asset files are not replaced for rewrite ignored paths + Given a fixture app "asset-hash-app" + And a file named "config.rb" with: + """ + is_stylesheet = proc { |path| path.start_with? '/stylesheets' } + activate :asset_hash, rewrite_ignore: [ + %r(javascripts/*), + '/subdir/*', + is_stylesheet + ] + activate :relative_assets + activate :directory_indexes + """ + And a successfully built app at "asset-hash-app" + When I cd to "build" + Then the following files should exist: + | index.html | + | subdir/index.html | + | images/100px-5fd6fb90.jpg | + | javascripts/application-1d8d5276.js | + | stylesheets/site-8bc55985.css | + And the following files should not exist: + | images/100px.jpg | + | javascripts/application.js | + | stylesheets/site.css | + And the file "javascripts/application-1d8d5276.js" should contain "img.src = '/images/100px.jpg'" + And the file "stylesheets/site-8bc55985.css" should contain: + """ + background-image: url("../images/100px.jpg") + """ + And the file "index.html" should contain 'href="stylesheets/site-8bc55985.css"' + And the file "index.html" should contain 'src="javascripts/application-1d8d5276.js"' + And the file "index.html" should contain 'src="images/100px-5fd6fb90.jpg"' + And the file "subdir/index.html" should contain: + """ +

Image url3:

+

+ """ + Scenario: Already minified files should still be hashed Given a successfully built app at "asset-hash-minified-app" When I cd to "build" diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index 8b9b606b..da84a23d 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -5,6 +5,7 @@ require 'middleman-core/rack' class Middleman::Extensions::AssetHash < ::Middleman::Extension 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' def initialize(app, options_hash={}, &block) super @@ -23,6 +24,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension 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) end diff --git a/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb index 34312060..b76c3285 100644 --- a/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb +++ b/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb @@ -34,13 +34,16 @@ module Middleman @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 upstream request to skip all rewriting - return [status, headers, response] if env['bypass_inline_url_rewriter'] == 'true' + # 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 @@ -96,6 +99,11 @@ module Middleman false end end + + Contract String => Bool + def rewrite_ignore?(path) + @rewrite_ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) } + end end end end From 37be89ed68321554f4aeeaf1f17250e15e8cceb7 Mon Sep 17 00:00:00 2001 From: Nick Muerdter Date: Sat, 9 Jan 2016 08:06:47 -0700 Subject: [PATCH 024/178] Add rewrite_ignore option to asset_host, cache_buster, relative_assets. --- middleman-core/features/asset_host.feature | 14 ++++++++++++++ middleman-core/features/cache_buster.feature | 16 +++++++++++++++- middleman-core/features/relative_assets.feature | 14 ++++++++++++++ .../lib/middleman-core/extensions/asset_host.rb | 2 ++ .../middleman-core/extensions/cache_buster.rb | 2 ++ .../middleman-core/extensions/relative_assets.rb | 2 ++ 6 files changed, 49 insertions(+), 1 deletion(-) diff --git a/middleman-core/features/asset_host.feature b/middleman-core/features/asset_host.feature index a8778d29..d223b997 100644 --- a/middleman-core/features/asset_host.feature +++ b/middleman-core/features/asset_host.feature @@ -35,3 +35,17 @@ Feature: Alternate between multiple asset hosts When I go to "/stylesheets/asset_host.css" Then I should see content matching %r{http://assets1.example.com/} Then I should not see content matching %r{http://assets1.example.com//} + + Scenario: Hosts are not rewritten for rewrite ignored paths + Given a fixture app "asset-host-app" + And a file named "config.rb" with: + """ + activate :asset_host, host: "http://assets1.example.com", rewrite_ignore: [ + '/stylesheets/asset_host.css', + ] + """ + And the Server is running + When I go to "/asset_host.html" + Then I should see content matching %r{http://assets1.example.com/} + When I go to "/stylesheets/asset_host.css" + Then I should not see content matching %r{http://assets1.example.com/} diff --git a/middleman-core/features/cache_buster.feature b/middleman-core/features/cache_buster.feature index d452234e..bea898e3 100644 --- a/middleman-core/features/cache_buster.feature +++ b/middleman-core/features/cache_buster.feature @@ -39,4 +39,18 @@ Feature: Generate mtime-based query string for busting browser caches And the Server is running at "cache-buster-app" When I go to "/cache-buster.html" Then I should see "site.css?" - Then I should see "blank.gif?" \ No newline at end of file + Then I should see "blank.gif?" + + Scenario: URLs are not rewritten for rewrite ignored paths + Given a fixture app "cache-buster-app" + And a file named "config.rb" with: + """ + activate :cache_buster, rewrite_ignore: [ + '/cache-buster.html', + ] + """ + And the Server is running at "cache-buster-app" + When I go to "/cache-buster.html" + Then I should see 'site.css"' + Then I should see 'empty-with-include.js"' + Then I should see 'blank.gif"' diff --git a/middleman-core/features/relative_assets.feature b/middleman-core/features/relative_assets.feature index a4b6fc68..ea6cbff0 100644 --- a/middleman-core/features/relative_assets.feature +++ b/middleman-core/features/relative_assets.feature @@ -132,3 +132,17 @@ Feature: Relative Assets And the Server is running at "relative-assets-app" When I go to "/sub/image_tag.html" Then I should see '' + + Scenario: URLs are not rewritten for rewrite ignored paths + Given a fixture app "relative-assets-app" + And a file named "config.rb" with: + """ + activate :relative_assets, rewrite_ignore: [ + '/stylesheets/fonts.css', + ] + """ + And the Server is running at "relative-assets-app" + When I go to "/stylesheets/relative_assets.css" + Then I should see 'url("../images/blank.gif' + When I go to "/stylesheets/fonts.css" + Then I should see 'url(/fonts/roboto/roboto-regular-webfont.eot' diff --git a/middleman-core/lib/middleman-core/extensions/asset_host.rb b/middleman-core/lib/middleman-core/extensions/asset_host.rb index d0487591..05b4509f 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_host.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_host.rb @@ -6,6 +6,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif), 'List of extensions that get cache busters strings appended to them.' option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.' 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, @@ -13,6 +14,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension url_extensions: options.exts, source_extensions: options.sources, ignore: options.ignore, + rewrite_ignore: options.rewrite_ignore, middleman_app: app, proc: method(:rewrite_url) end diff --git a/middleman-core/lib/middleman-core/extensions/cache_buster.rb b/middleman-core/lib/middleman-core/extensions/cache_buster.rb index 7cc41a36..8f1ceb64 100644 --- a/middleman-core/lib/middleman-core/extensions/cache_buster.rb +++ b/middleman-core/lib/middleman-core/extensions/cache_buster.rb @@ -3,6 +3,7 @@ class Middleman::Extensions::CacheBuster < ::Middleman::Extension option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif), 'List of extensions that get cache busters strings appended to them.' option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.' option :ignore, [], 'Regexes of filenames to skip adding query strings to' + option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites' def initialize(app, options_hash={}, &block) super @@ -16,6 +17,7 @@ class Middleman::Extensions::CacheBuster < ::Middleman::Extension url_extensions: options.exts, source_extensions: options.sources, ignore: options.ignore, + rewrite_ignore: options.rewrite_ignore, middleman_app: app, proc: method(:rewrite_url) end diff --git a/middleman-core/lib/middleman-core/extensions/relative_assets.rb b/middleman-core/lib/middleman-core/extensions/relative_assets.rb index 4de2f2d5..f232f6a4 100644 --- a/middleman-core/lib/middleman-core/extensions/relative_assets.rb +++ b/middleman-core/lib/middleman-core/extensions/relative_assets.rb @@ -5,6 +5,7 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif .ttf .otf .woff .woff2 .eot), 'List of extensions that get cache busters strings appended to them.' option :sources, %w(.htm .html .css), 'List of extensions that are searched for relative assets.' option :ignore, [], 'Regexes of filenames to skip adding query strings to' + option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites' def initialize(app, options_hash={}, &block) super @@ -18,6 +19,7 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension url_extensions: options.exts, source_extensions: options.sources, ignore: options.ignore, + rewrite_ignore: options.rewrite_ignore, middleman_app: app, proc: method(:rewrite_url) end From 17df162e7bbad0ad3809f81d0a07bbdadbdd1228 Mon Sep 17 00:00:00 2001 From: Nathan Feaver Date: Sun, 10 Jan 2016 06:28:18 -0700 Subject: [PATCH 025/178] consider all MS Office files to be binary --- middleman-core/lib/middleman-core/util.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index ffd76eb6..e994e09c 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -366,7 +366,7 @@ module Middleman case when mime.start_with?('text/') true - when mime.include?('xml') + when mime.include?('xml') && !mime.include?('officedocument') true when mime.include?('json') true From 47d0e1cb7bfae25c5e4db1bca539be54d04acc8b Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 10 Jan 2016 16:37:12 -0800 Subject: [PATCH 026/178] update changelog --- CHANGELOG.md | 13 ++++++++++++- middleman-core/lib/middleman-core/version.rb | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5351d07..ee99078c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,18 @@ master === -# 4.0.0.rc.3 +# 4.1.0 + +* Add rewrite_ignore option to asset_hash, asset_host, cache_buster & relative_assets. This proc let's you opt-out of the extension behavior on a per-path basis. +* gzip extension now compresses svgs by default +* Fix the `encoding` option. +* Fix relative paths on `image_tag` helper. +* Correctly exit with error code on failed `init` +* Fixed `asset_hash` when path has query string or #hashes +* Fix new extension template +* Don't parse frontmatter on ignored files. + +# 4.0.0 * Add `:locales` and `:data` source types to the list of files which trigger a live-reload. * Rename i18n `lang` and `langs` to `locale` and `locales`. diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index 6c697cbd..236fd14d 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.0.0' unless const_defined?(:VERSION) + VERSION = '4.1.0' unless const_defined?(:VERSION) end From b4a6a503b3590ac754e0de724ec1d3ac8941db77 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 10 Jan 2016 16:47:15 -0800 Subject: [PATCH 027/178] Fixes #1719 --- CHANGELOG.md | 1 + .../lib/middleman-core/meta_pages/sitemap_resource.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee99078c..b0e80a88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ master * Fixed `asset_hash` when path has query string or #hashes * Fix new extension template * Don't parse frontmatter on ignored files. +* Fix displaying frontmatter on `/__middleman/sitemap` # 4.0.0 diff --git a/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb b/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb index d746be95..fecaef96 100644 --- a/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb +++ b/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb @@ -42,7 +42,7 @@ module Middleman props['Source File'] = @resource.file_descriptor ? @resource.file_descriptor[:full_path].to_s.sub(/^#{Regexp.escape(ENV['MM_ROOT'] + '/')}/, '') : 'Dynamic' data = @resource.data - props['Data'] = data.inspect unless data.empty? + props['Data'] = data.to_hash(symbolize_keys: true).inspect unless data.empty? options = @resource.options props['Options'] = options.inspect unless options.empty? From 5cac6a18966a1b93a71942adc26c7cffd6699d01 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 10 Jan 2016 16:56:18 -0800 Subject: [PATCH 028/178] Add test for #1718 --- middleman-core/features/directory_index.feature | 4 +++- middleman-core/fixtures/indexable-app/config.rb | 1 + .../fixtures/indexable-app/source/regex_leave_me_alone2.html | 1 + middleman-core/lib/middleman-core/core_extensions/routing.rb | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 middleman-core/fixtures/indexable-app/source/regex_leave_me_alone2.html diff --git a/middleman-core/features/directory_index.feature b/middleman-core/features/directory_index.feature index f8c87a21..ddbd703f 100644 --- a/middleman-core/features/directory_index.feature +++ b/middleman-core/features/directory_index.feature @@ -9,6 +9,7 @@ Feature: Directory Index | a_folder/needs_index/index.html | | leave_me_alone.html | | wildcard_leave_me_alone.html | + | regex_leave_me_alone2.html | | evil spaces/index.html | | regular/index.html | | .htaccess | @@ -21,12 +22,13 @@ Feature: Directory Index | a_folder/needs_index.html | | leave_me_alone/index.html | | wildcard_leave_me_alone/index.html | + | regex_leave_me_alone2/index.html | And the file "needs_index/index.html" should contain "Indexable" And the file "a_folder/needs_index/index.html" should contain "Indexable" And the file "leave_me_alone.html" should contain "Stay away" And the file "regular/index.html" should contain "Regular" And the file "evil spaces/index.html" should contain "Filled with Evil Spaces" - + Scenario: Preview normal file Given the Server is running at "indexable-app" When I go to "/needs_index/" diff --git a/middleman-core/fixtures/indexable-app/config.rb b/middleman-core/fixtures/indexable-app/config.rb index fdccfcbb..17c25ecf 100644 --- a/middleman-core/fixtures/indexable-app/config.rb +++ b/middleman-core/fixtures/indexable-app/config.rb @@ -2,3 +2,4 @@ activate :directory_indexes page "/leave_me_alone.html", directory_index: false page "/wildcard*", directory_index: false +page /regex_.*/, directory_index: false diff --git a/middleman-core/fixtures/indexable-app/source/regex_leave_me_alone2.html b/middleman-core/fixtures/indexable-app/source/regex_leave_me_alone2.html new file mode 100644 index 00000000..5ff5317a --- /dev/null +++ b/middleman-core/fixtures/indexable-app/source/regex_leave_me_alone2.html @@ -0,0 +1 @@ +Stay away, wildcards! diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb index db773d29..dcbea0ec 100644 --- a/middleman-core/lib/middleman-core/core_extensions/routing.rb +++ b/middleman-core/lib/middleman-core/core_extensions/routing.rb @@ -44,7 +44,7 @@ module Middleman # @option opts [Hash] locals Local variables for the template. These will be available when the template renders. # @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}. # @return [void] - Contract String, Hash => Any + Contract Or[String, Regexp], Hash => Any def page(path, opts={}) options = opts.dup From c6401f1cd9ac36b63cd0ee077239fe4828ef1ec0 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 10 Jan 2016 17:14:41 -0800 Subject: [PATCH 029/178] Fixes #1716 --- CHANGELOG.md | 1 + middleman-core/features/clean_build.feature | 16 ++++++++++++++++ middleman-core/lib/middleman-core/application.rb | 2 ++ middleman-core/lib/middleman-core/builder.rb | 10 +++++++--- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0e80a88..370a5e81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ master * Fix new extension template * 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 # 4.0.0 diff --git a/middleman-core/features/clean_build.feature b/middleman-core/features/clean_build.feature index eaa9942e..60c18578 100644 --- a/middleman-core/features/clean_build.feature +++ b/middleman-core/features/clean_build.feature @@ -16,6 +16,22 @@ Feature: Build Clean | build/should_be_ignored3.html | And the file "build/index.html" should contain "Comment in layout" + Scenario: Clean build has a whitelist + Given a fixture app "clean-app" + When a file named "build/.test" with: + """ + Hello + """ + When a file named "config.rb" with: + """ + set :skip_build_clean do |path| + path =~ /\.test/ + end + """ + Given a built app at "clean-app" + Then the following files should exist: + | build/.test | + Scenario: Clean build an app with newly ignored files and a nested output directory Given a fixture app "clean-nested-app" When a file named "config.rb" with: diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 5818548b..4efca949 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -191,6 +191,8 @@ module Middleman 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' define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode' define_setting :watcher_latency, nil, 'The Listen watcher latency' diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index 4166dcf5..02feb15b 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -58,7 +58,7 @@ module Middleman prerender_css output_files - clean if @cleaning + clean! if @cleaning ::Middleman::Profiling.report('build') @@ -219,8 +219,12 @@ module Middleman # Remove files which were not built in this cycle Contract ArrayOf[Pathname] - def clean - @to_clean.each do |f| + def clean! + to_remove = @to_clean.reject do |f| + app.config[:skip_build_clean].call(f.to_s) + end + + to_remove.each do |f| FileUtils.rm(f) trigger(:deleted, f) end From 98fe7ce7d2c327fe9f32d814582ff75720594fc0 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 10 Jan 2016 17:24:43 -0800 Subject: [PATCH 030/178] WIP encoding test --- middleman-core/features/encoding_option.feature | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/middleman-core/features/encoding_option.feature b/middleman-core/features/encoding_option.feature index b2aeed6b..6244e420 100644 --- a/middleman-core/features/encoding_option.feature +++ b/middleman-core/features/encoding_option.feature @@ -9,15 +9,20 @@ Feature: encoding option Then the "Content-Type" header should contain "text/html" Then the "Content-Type" header should contain "charset=utf-8" + @wip Scenario: Custom encoding set Given a fixture app "i-8859-1-app" And a file named "config.rb" with: """ set :encoding, "ISO-8859-1" + + ::Rack::Mime::MIME_TYPES['.html'] = 'text/html; charset=iso-8859-1' + ::Rack::Mime::MIME_TYPES['.htm'] = 'text/html; charset=iso-8859-1' + ::Rack::Mime::MIME_TYPES['.map'] = 'application/json; charset=iso-8859-1' """ Given the Server is running at "i-8859-1-app" When I go to "/index.html" Then the "Content-Type" header should contain "text/html" Then the "Content-Type" header should contain "charset=iso-8859-1" - Then I should see "äöü" + Then I should see "äöü" From 8f66077dd06f2ce07debce174133bafad12c4273 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sun, 10 Jan 2016 17:25:11 -0800 Subject: [PATCH 031/178] Allow 2.3.0 failure until frozen string bug is fixed upstream --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 528eef8f..ef9608ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ os: matrix: fast_finish: true allow_failures: + - 2.3.0 - rvm: ruby-head env: global: From 179268a4f6efb514ea004c43f8fd8146f25f810b Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 2 Jan 2016 17:37:11 -0800 Subject: [PATCH 032/178] Create ConfigExtension to simplify the APIs for config vs Step. Fixes #1743. Fixes #1745 --- middleman-cli/lib/middleman-cli/extension.rb | 2 +- .../features/cli/preview_server.feature | 3 +- middleman-core/features/ignore.feature | 37 +++++++- middleman-core/fixtures/import-app/config.rb | 2 +- .../core_extensions/collections.rb | 4 +- .../collections/step_context.rb | 13 ++- .../middleman-core/core_extensions/i18n.rb | 8 +- .../lib/middleman-core/extension.rb | 34 +++++++ .../extensions/external_pipeline.rb | 2 - .../lib/middleman-core/load_paths.rb | 2 +- .../sitemap/extensions/ignores.rb | 82 +++++++++-------- .../sitemap/extensions/import.rb | 90 +++++-------------- .../sitemap/extensions/move_file.rb | 47 ++-------- .../sitemap/extensions/proxies.rb | 72 +++++---------- .../lib/middleman-core/sitemap/resource.rb | 13 +-- .../lib/middleman-core/sitemap/store.rb | 19 ++-- 16 files changed, 192 insertions(+), 238 deletions(-) diff --git a/middleman-cli/lib/middleman-cli/extension.rb b/middleman-cli/lib/middleman-cli/extension.rb index fd6c6f26..69e073fb 100644 --- a/middleman-cli/lib/middleman-cli/extension.rb +++ b/middleman-cli/lib/middleman-cli/extension.rb @@ -31,7 +31,7 @@ module Middleman::Cli template 'extension/gemspec', File.join(name, "#{name}.gemspec") template 'extension/Gemfile', File.join(name, 'Gemfile') template 'extension/lib/lib.rb', File.join(name, 'lib', "#{name}.rb") - template 'extension/lib/lib/extension.rb', File.join(name, 'lib', name, "extension.rb") + template 'extension/lib/lib/extension.rb', File.join(name, 'lib', name, 'extension.rb') template 'extension/features/support/env.rb', File.join(name, 'features', 'support', 'env.rb') empty_directory File.join(name, 'fixtures') end diff --git a/middleman-core/features/cli/preview_server.feature b/middleman-core/features/cli/preview_server.feature index 5fedc091..94ecc5b2 100644 --- a/middleman-core/features/cli/preview_server.feature +++ b/middleman-core/features/cli/preview_server.feature @@ -42,7 +42,7 @@ Feature: Run the preview server Inspect your site configuration at "http:// """ - @ruby-2.1 + @wip Scenario: Start the server with defaults in verbose mode, when a local mdns server resolves the local hostname Given I start a mdns server for the local hostname When I run `middleman server --verbose` interactively @@ -360,7 +360,6 @@ Feature: Run the preview server The Middleman preview server is bound to ":::65432", "0.0.0.0:65432" """ - @ruby-2.1 @wip Scenario: Start the server when port is blocked by other middleman instance Given `middleman server` is running in background diff --git a/middleman-core/features/ignore.feature b/middleman-core/features/ignore.feature index 166002c5..9e3d4688 100644 --- a/middleman-core/features/ignore.feature +++ b/middleman-core/features/ignore.feature @@ -12,7 +12,7 @@ Feature: Ignoring paths And the following files should not exist: | build/plain.html | | build/about.html | - + Scenario: Ignore a single path (server) Given a fixture app "ignore-app" And a file named "config.rb" with: @@ -28,6 +28,35 @@ Feature: Ignoring paths When I go to "/about.html" Then I should see "File Not Found" + Scenario: Ignoring collected values + Given a fixture app "ignore-app" + And a file named "data/ignores.yaml" with: + """ + --- + - "plain" + """ + And a file named "config.rb" with: + """ + data.ignores.each do |name| + ignore "#{name}.html" + end + """ + And the Server is running + When I go to "/plain.html" + Then I should see "File Not Found" + When I go to "/about.html" + Then I should not see "File Not Found" + + When the file "data/ignores.yaml" has the contents + """ + --- + - "about" + """ + When I go to "/plain.html" + Then I should not see "File Not Found" + When I go to "/about.html" + Then I should see "File Not Found" + Scenario: Ignore a globbed path (build) Given a fixture app "ignore-app" And a file named "config.rb" with: @@ -47,7 +76,7 @@ Feature: Ignoring paths | build/reports/index.html | | build/reports/another.html | | build/images/icons/messages.png | - + Scenario: Ignore a globbed path (server) Given a fixture app "ignore-app" And a file named "config.rb" with: @@ -93,7 +122,7 @@ Feature: Ignoring paths | build/reports/index.html | | build/reports/another.html | | build/images/icons/messages.png | - + Scenario: Ignore a regex (server) Given a fixture app "ignore-app" And a file named "config.rb" with: @@ -118,4 +147,4 @@ Feature: Ignoring paths When I go to "/reports/another.html" Then I should see "File Not Found" When I go to "/images/icons/messages.png" - Then I should see "File Not Found" \ No newline at end of file + Then I should see "File Not Found" diff --git a/middleman-core/fixtures/import-app/config.rb b/middleman-core/fixtures/import-app/config.rb index f41b6dff..7846f1e5 100644 --- a/middleman-core/fixtures/import-app/config.rb +++ b/middleman-core/fixtures/import-app/config.rb @@ -4,4 +4,4 @@ import_path File.expand_path("bower_components/", root) import_path File.expand_path("bower_components", root) do |target_path, original_path| target_path.sub('bower_components', 'bower_components2') -end \ No newline at end of file +end diff --git a/middleman-core/lib/middleman-core/core_extensions/collections.rb b/middleman-core/lib/middleman-core/core_extensions/collections.rb index 3491d894..434455f1 100644 --- a/middleman-core/lib/middleman-core/core_extensions/collections.rb +++ b/middleman-core/lib/middleman-core/core_extensions/collections.rb @@ -100,7 +100,9 @@ module Middleman end # Inject descriptors - resources + ctx.descriptors.map { |d| d.to_resource(app) } + ctx.descriptors.reduce(resources) do |sum, d| + d.execute_descriptor(app, sum) + end end end end diff --git a/middleman-core/lib/middleman-core/core_extensions/collections/step_context.rb b/middleman-core/lib/middleman-core/core_extensions/collections/step_context.rb index c33c0833..2ce90b83 100644 --- a/middleman-core/lib/middleman-core/core_extensions/collections/step_context.rb +++ b/middleman-core/lib/middleman-core/core_extensions/collections/step_context.rb @@ -1,5 +1,3 @@ -require 'hamster' - module Middleman module CoreExtensions module Collections @@ -11,15 +9,16 @@ module Middleman attr_reader :descriptors def initialize - @descriptors = ::Hamster::Set.empty + @descriptors = [] end def method_missing(name, *args, &block) internal = :"_internal_#{name}" - if respond_to?(internal) - @descriptors = @descriptors.add(send(internal, *args, &block)) - else - super + + return super unless respond_to?(internal) + + send(internal, *args, &block).tap do |r| + @descriptors << r if r.respond_to?(:execute_descriptor) end end end diff --git a/middleman-core/lib/middleman-core/core_extensions/i18n.rb b/middleman-core/lib/middleman-core/core_extensions/i18n.rb index 99731402..ce16ab48 100644 --- a/middleman-core/lib/middleman-core/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-core/core_extensions/i18n.rb @@ -185,7 +185,9 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension sum[abs_path][desc.locale] = '/' + desc.path end - resources + new_resources.map { |r| r.to_resource(app) } + new_resources.reduce(resources) do |sum, r| + r.execute_descriptor(app, sum) + end end Contract String, Symbol => String @@ -255,10 +257,10 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension end LocalizedPageDescriptor = Struct.new(:path, :source_path, :locale) do - def to_resource(app) + def execute_descriptor(app, resources) r = ::Middleman::Sitemap::ProxyResource.new(app.sitemap, path, source_path) r.add_metadata options: { locale: locale } - r + resources + [r] end end diff --git a/middleman-core/lib/middleman-core/extension.rb b/middleman-core/lib/middleman-core/extension.rb index a44273a3..5fd80a76 100644 --- a/middleman-core/lib/middleman-core/extension.rb +++ b/middleman-core/lib/middleman-core/extension.rb @@ -469,4 +469,38 @@ module Middleman @app.ready(&method(:ready)) if respond_to?(:ready) end end + + class ConfigExtension < Extension + def initialize(app, config={}, &block) + @descriptors = {} + @wrapped = {} + + self.class.exposed_to_config.each do |k, v| + @descriptors[k] = [] + + define_singleton_method(:"__original_#{v}", &method(v)) + define_singleton_method(v) do |*args, &block| + @descriptors[k] << method(:"__original_#{v}").call(*args, &block) + @app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}") + end + end + + super + end + + def after_configuration + self.class.exposed_to_config.each do |k, v| + ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(k, &method(:"__original_#{v}")) + end + end + + # Update the main sitemap resource list + # @return Array + Contract ResourceList => ResourceList + def manipulate_resource_list(resources) + @descriptors.values.flatten.reduce(resources) do |sum, c| + c.execute_descriptor(app, sum) + end + end + end end diff --git a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb index 63befc21..44a4e6b3 100644 --- a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb +++ b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb @@ -15,9 +15,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension @watcher = app.files.watch :source, path: File.expand_path(options[:source], app.root), latency: options[:latency] - end - def ready logger.info "== Executing: `#{options[:command]}`" if app.build? || options[:disable_background_execution] diff --git a/middleman-core/lib/middleman-core/load_paths.rb b/middleman-core/lib/middleman-core/load_paths.rb index d8937864..c0bda7b2 100644 --- a/middleman-core/lib/middleman-core/load_paths.rb +++ b/middleman-core/lib/middleman-core/load_paths.rb @@ -22,7 +22,7 @@ module Middleman # Set BUNDLE_GEMFILE and run Bundler setup. Raises an exception if there is no Gemfile def setup_bundler - ENV['BUNDLE_GEMFILE'] ||= File.join(findup('Gemfile', ENV['MM_ROOT']), "Gemfile") + ENV['BUNDLE_GEMFILE'] ||= File.join(findup('Gemfile', ENV['MM_ROOT']), 'Gemfile') unless File.exist?(ENV['BUNDLE_GEMFILE']) ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__) diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index 35788d61..3a0fa464 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -2,58 +2,56 @@ module Middleman module Sitemap module Extensions # Class to handle managing ignores - class Ignores < Extension + class Ignores < ConfigExtension self.resource_list_manipulator_priority = 0 - # Expose `create_ignore` as `app.ignore` - expose_to_application ignore: :create_ignore - - # Expose `create_ignore` to config as `ignore` expose_to_config ignore: :create_ignore - def initialize(app, config={}, &block) - super - - # Array of callbacks which can assign ignored - @ignored_callbacks = Set.new - - @app.sitemap.define_singleton_method(:ignored?, &method(:ignored?)) - end - # Ignore a path or add an ignore callback # @param [String, Regexp] path Path glob expression, or path regex - # @return [void] - Contract Maybe[Or[String, Regexp]], Maybe[Proc] => Any + # @return [IgnoreDescriptor] + Contract Maybe[Or[String, Regexp]], Maybe[Proc] => RespondTo[:execute_descriptor] def create_ignore(path=nil, &block) - if path.is_a? Regexp - @ignored_callbacks << proc { |p| p =~ path } - elsif path.is_a? String - path_clean = ::Middleman::Util.normalize_path(path) - if path_clean.include?('*') # It's a glob - if defined? File::FNM_EXTGLOB - @ignored_callbacks << proc { |p| File.fnmatch(path_clean, p, File::FNM_EXTGLOB) } - else - @ignored_callbacks << proc { |p| File.fnmatch(path_clean, p) } - end - else - # Add a specific-path ignore unless that path is already covered - return if ignored?(path_clean) - @ignored_callbacks << proc { |p| p == path_clean } - end - elsif block_given? - @ignored_callbacks << block - end - @app.sitemap.invalidate_resources_not_ignored_cache! + IgnoreDescriptor.new(path, block) end - # Whether a path is ignored - # @param [String] path - # @return [Boolean] - Contract String => Bool - def ignored?(path) - path_clean = ::Middleman::Util.normalize_path(path) - @ignored_callbacks.any? { |b| b.call(path_clean) } + IgnoreDescriptor = Struct.new(:path, :block) do + def execute_descriptor(_app, resources) + resources.map do |r| + # Ignore based on the source path (without template extensions) + if ignored?(r.path) + r.ignore! + else + # 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) + end + + r + end + end + + def ignored?(match_path) + match_path = ::Middleman::Util.normalize_path(match_path) + + if path.is_a? Regexp + match_path =~ path + elsif path.is_a? String + path_clean = ::Middleman::Util.normalize_path(path) + + if path_clean.include?('*') # It's a glob + if defined?(::File::FNM_EXTGLOB) + ::File.fnmatch(path_clean, match_path, ::File::FNM_EXTGLOB) + else + ::File.fnmatch(path_clean, match_path) + end + else + match_path == path_clean + end + elsif block_given? + block.call(match_path) + end + end end 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 37978a19..eb7bd4e5 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb @@ -4,46 +4,45 @@ require 'middleman-core/contracts' module Middleman module Sitemap module Extensions - class Import < Extension + class Import < ConfigExtension self.resource_list_manipulator_priority = 1 - ImportFileDescriptor = Struct.new(:from, :to) - ImportPathDescriptor = Struct.new(:from, :renameProc) - # Expose `create_import_file` to config as `import_file` expose_to_config import_file: :create_import_file # Expose `create_import_path` to config as `import_path` expose_to_config import_path: :create_import_path - def initialize(app, config={}, &block) - super - - @import_file_configs = Set.new - @import_path_configs = Set.new + ImportFileDescriptor = Struct.new(:from, :to) do + def execute_descriptor(app, resources) + resources + [ + ::Middleman::Sitemap::Resource.new(app.sitemap, to, from) + ] + end end - def after_configuration - ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:import_file, &method(:create_import_file)) - ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:import_path, &method(:create_import_path)) + ImportPathDescriptor = Struct.new(:from, :renameProc) do + def execute_descriptor(app, resources) + 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 + + ::Middleman::Sitemap::Resource.new( + app.sitemap, + renameProc.call(target_path, path), + path + ) + end + end end # Import an external file into `source` # @param [String] from The original path. # @param [String] to The new path. # @return [void] - Contract String, String => Any - def create_import_file(from, to) - @import_file_configs << create_anonymous_import_file(from, to) - @app.sitemap.rebuild_resource_list!(:added_import_file) - end - - # Import an external file into `source` - # @param [String] from The original path. - # @param [String] to The new path. - # @return [ImportFileDescriptor] Contract String, String => ImportFileDescriptor - def create_anonymous_import_file(from, to) + def create_import_file(from, to) ImportFileDescriptor.new( File.expand_path(from, @app.root), ::Middleman::Util.normalize_path(to) @@ -54,54 +53,13 @@ module Middleman # @param [String] from The original path. # @param [Proc] block Renaming method # @return [void] - Contract String, Maybe[Proc] => Any + Contract String, Maybe[Proc] => ImportPathDescriptor def create_import_path(from, &block) - rename_proc = block_given? ? block : proc { |path| path } - @import_path_configs << create_anonymous_import_path(from, rename_proc) - @app.sitemap.rebuild_resource_list!(:added_import_path) - end - - # Import an external glob into `source` - # @param [String] from The original path. - # @param [Proc] block Renaming method - # @return [ImportPathDescriptor] - Contract String, Proc => ImportPathDescriptor - def create_anonymous_import_path(from, block) ImportPathDescriptor.new( from, - block + block_given? ? block : proc { |path| path } ) end - - Contract IsA['Middleman::SourceFile'] => Bool - def ignored?(file) - @app.config[:ignored_sitemap_matchers].any? { |_, fn| fn.call(file, @app) } - end - - # Update the main sitemap resource list - # @return Array - Contract ResourceList => ResourceList - def manipulate_resource_list(resources) - resources + @import_file_configs.map { |c| - ::Middleman::Sitemap::Resource.new( - @app.sitemap, - c[:to], - c[:from] - ) - } + @import_path_configs.flat_map { |c| - ::Middleman::Util.glob_directory(File.join(c[:from], '**/*')) - .reject { |path| File.directory?(path) } - .map do |path| - target_path = Pathname(path).relative_path_from(Pathname(c[:from]).parent).to_s - - ::Middleman::Sitemap::Resource.new( - @app.sitemap, - c[:renameProc].call(target_path, path), - path - ) - end - } - end end end end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb b/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb index e889e4b6..7f8a11bb 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb @@ -6,62 +6,33 @@ module Middleman module Extensions # Manages the list of proxy configurations and manipulates the sitemap # to include new resources based on those configurations - class MoveFile < Extension - MoveFileDescriptor = Struct.new(:from, :to) - + class MoveFile < ConfigExtension self.resource_list_manipulator_priority = 101 # Expose `create_move_file` to config as `move_file` expose_to_config move_file: :create_move_file - def initialize(app, config={}, &block) - super + MoveFileDescriptor = Struct.new(:from, :to) do + def execute_descriptor(_app, resources) + resources.each do |r| + r.destination_path = to if from == r.path || from == r.destination_path + end - @move_configs = Set.new - end - - def after_configuration - ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:move_file, &method(:create_move_file)) + resources + end end # Setup a move from one path to another # @param [String] from The original path. # @param [String] to The new path. # @return [void] - Contract String, String => Any - def create_move_file(from, to) - @move_configs << create_anonymous_move(from, to) - @app.sitemap.rebuild_resource_list!(:added_move_file) - end - - # Setup a move from one path to another - # @param [String] from The original path. - # @param [String] to The new path. - # @return [MoveFileDescriptor] Contract String, String => MoveFileDescriptor - def create_anonymous_move(from, to) + def create_move_file(from, to) MoveFileDescriptor.new( ::Middleman::Util.normalize_path(from), ::Middleman::Util.normalize_path(to) ) end - - # Update the main sitemap resource list - # @return Array - Contract ResourceList => ResourceList - def manipulate_resource_list(resources) - resources.each do |r| - matches = @move_configs.select do |c| - c.from == r.path || c.from == r.destination_path - end - - if c = matches.last - r.destination_path = c.to - end - end - - resources - end 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 82856aa3..8ff8087f 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -6,28 +6,12 @@ module Middleman module Extensions # Manages the list of proxy configurations and manipulates the sitemap # to include new resources based on those configurations - class Proxies < Extension + class Proxies < ConfigExtension self.resource_list_manipulator_priority = 0 - # Expose `create_proxy` as `app.proxy` - expose_to_application proxy: :create_proxy - # Expose `create_proxy` to config as `proxy` expose_to_config proxy: :create_proxy - def initialize(app, config={}, &block) - super - - @proxy_configs = Set.new - @post_config = false - end - - def after_configuration - @post_config = true - - ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:proxy, &method(:create_anonymous_proxy)) - end - # Setup a proxy from a path to a target # @param [String] path The new, proxied path to create # @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy. @@ -36,51 +20,35 @@ module Middleman # @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths. # @option opts [Hash] locals Local variables for the template. These will be available when the template renders. # @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}. - # @return [void] - Contract String, String, Maybe[Hash] => Any + # @return [ProxyDescriptor] + Contract String, String, Maybe[Hash] => RespondTo[:execute_descriptor] def create_proxy(path, target, opts={}) - options = opts.dup - @app.ignore(target) if options.delete(:ignore) - - @proxy_configs << create_anonymous_proxy(path, target, options) - @app.sitemap.rebuild_resource_list!(:added_proxy) - end - - # Setup a proxy from a path to a target - # @param [String] path The new, proxied path to create - # @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy. - # @option opts [Boolean] ignore Ignore the target from the sitemap (so only the new, proxy resource ends up in the output) - # @option opts [Symbol, Boolean, String] layout The layout name to use (e.g. `:article`) or `false` to disable layout. - # @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths. - # @option opts [Hash] locals Local variables for the template. These will be available when the template renders. - # @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}. - # @return [void] - def create_anonymous_proxy(path, target, options={}) ProxyDescriptor.new( ::Middleman::Util.normalize_path(path), ::Middleman::Util.normalize_path(target), - options + opts.dup ) end - - # Update the main sitemap resource list - # @return Array - Contract ResourceList => ResourceList - def manipulate_resource_list(resources) - resources + @proxy_configs.map { |c| c.to_resource(@app) } - end end ProxyDescriptor = Struct.new(:path, :target, :metadata) do - def to_resource(app) - ProxyResource.new(app.sitemap, path, target).tap do |p| - md = metadata.dup - p.add_metadata( - locals: md.delete(:locals) || {}, - page: md.delete(:data) || {}, - options: md - ) + def execute_descriptor(app, resources) + md = metadata.dup + should_ignore = md.delete(:ignore) + + r = ProxyResource.new(app.sitemap, path, target) + r.add_metadata( + locals: md.delete(:locals) || {}, + page: md.delete(:data) || {}, + options: md + ) + + if should_ignore + d = ::Middleman::Sitemap::Extensions::Ignores::IgnoreDescriptor.new(target) + d.execute_descriptor(app, resources) end + + resources + [r] end end end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 980927ca..7a13e9f9 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -38,6 +38,8 @@ module Middleman Contract METADATA_HASH attr_reader :metadata + attr_accessor :ignored + # Initialize resource with parent store and URL # @param [Middleman::Sitemap::Store] store # @param [String] path @@ -47,6 +49,7 @@ module Middleman @store = store @app = @store.app @path = path + @ignored = false source = Pathname(source) if source && source.is_a?(String) @@ -173,15 +176,7 @@ module Middleman # @return [Boolean] Contract Bool def ignored? - return true if @ignored - # Ignore based on the source path (without template extensions) - return true if @app.sitemap.ignored?(path) - # This allows files to be ignored by their source file name (with template extensions) - if !self.is_a?(ProxyResource) && file_descriptor && @app.sitemap.ignored?(file_descriptor[:relative_path].to_s) - true - else - false - end + @ignored end # The preferred MIME content type for this resource based on extension or metadata diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index a3ad3eb8..b433417f 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -3,12 +3,6 @@ require 'active_support/core_ext/hash/deep_merge' require 'monitor' require 'hamster' -# Ignores -Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do - require 'middleman-core/sitemap/extensions/ignores' - Middleman::Sitemap::Extensions::Ignores -end - # Files on Disk Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/on_disk' @@ -45,6 +39,12 @@ Middleman::Extensions.register :sitemap_move_files, auto_activate: :before_confi Middleman::Sitemap::Extensions::MoveFile end +# Ignores +Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do + require 'middleman-core/sitemap/extensions/ignores' + Middleman::Sitemap::Extensions::Ignores +end + require 'middleman-core/contracts' module Middleman @@ -108,14 +108,15 @@ module Middleman [m[:priority], n] end - rebuild_resource_list!(:registered_new) + rebuild_resource_list!(:"registered_new_manipulator_#{name}") end # Rebuild the list of resources from scratch, using registed manipulators # @return [void] Contract Maybe[Symbol] => Any - def rebuild_resource_list!(_name=nil) + def rebuild_resource_list!(name=nil) @lock.synchronize do + @app.logger.debug "== Requesting resource list rebuilding: #{name}" @needs_sitemap_rebuild = true end end @@ -159,7 +160,7 @@ module Middleman end end - # Invalidate our cached view of resource that are not ingnored. If your extension + # Invalidate our cached view of resource that are not ignored. If your extension # adds ways to ignore files, you should call this to make sure #resources works right. def invalidate_resources_not_ignored_cache! @resources_not_ignored = nil From edd5eb205746678f41550ad6e2c579bac9c4bad9 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 11 Jan 2016 13:58:19 -0800 Subject: [PATCH 033/178] 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 236fd14d..be0be167 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' unless const_defined?(:VERSION) + VERSION = '4.1.0.rc.1' unless const_defined?(:VERSION) end From f954415c95d76f2beb1bc3f4fbcf4c0a472be55f Mon Sep 17 00:00:00 2001 From: Jim Dalton Date: Mon, 11 Jan 2016 14:24:28 -0800 Subject: [PATCH 034/178] Add app method to detect mode --- middleman-core/lib/middleman-core/application.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 4efca949..88b6385a 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -327,18 +327,26 @@ module Middleman end end + # Whether we're in a specific mode + # @param [Symbol] key + # @return [Boolean] + Contract Symbol => Bool + def mode?(key) + config[:mode] == key + end + # Whether we're in server mode # @return [Boolean] If we're in dev mode Contract Bool def server? - config[:mode] == :server + mode?(:server) end # Whether we're in build mode # @return [Boolean] If we're in dev mode Contract Bool def build? - config[:mode] == :build + mode?(:build) end # Whether we're in a specific environment From 95c7a53291521ce4b96d349e04dad254c4079e01 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 12 Jan 2016 10:35:12 -0800 Subject: [PATCH 035/178] Convert more basic config commands to ConfigExtensions --- .../lib/middleman-core/contracts.rb | 127 +++--------------- .../middleman-core/core_extensions/routing.rb | 50 +++---- .../sitemap/extensions/ignores.rb | 4 +- .../sitemap/extensions/import.rb | 11 +- .../sitemap/extensions/move_file.rb | 6 +- .../sitemap/extensions/proxies.rb | 6 +- .../sitemap/extensions/redirects.rb | 44 +++--- .../sitemap/extensions/request_endpoints.rb | 52 +++---- .../lib/middleman-core/sitemap/store.rb | 30 +++-- middleman-core/lib/middleman-core/util.rb | 29 ++-- 10 files changed, 118 insertions(+), 241 deletions(-) diff --git a/middleman-core/lib/middleman-core/contracts.rb b/middleman-core/lib/middleman-core/contracts.rb index 3afedbfe..e99d0d59 100644 --- a/middleman-core/lib/middleman-core/contracts.rb +++ b/middleman-core/lib/middleman-core/contracts.rb @@ -1,112 +1,23 @@ -if ENV['TEST'] || ENV['CONTRACTS'] == 'true' - require 'contracts' - require 'hamster' - - 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 - - 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 - - # 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 +require 'contracts' +require 'hamster' 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 + + VectorOf = ::Contracts::CollectionOf::Factory.new(::Hamster::Vector) + ResourceList = ::Contracts::ArrayOf[IsA['Middleman::Sitemap::Resource']] PATH_MATCHER = Or[String, RespondTo[:match], RespondTo[:call], RespondTo[:to_s]] end diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb index dcbea0ec..cf024d7d 100644 --- a/middleman-core/lib/middleman-core/core_extensions/routing.rb +++ b/middleman-core/lib/middleman-core/core_extensions/routing.rb @@ -1,7 +1,7 @@ # Routing extension module Middleman module CoreExtensions - class Routing < Extension + class Routing < ConfigExtension # This should always run late, but not as late as :directory_indexes, # so it can add metadata to any pages generated by other extensions self.resource_list_manipulator_priority = 10 @@ -9,24 +9,28 @@ module Middleman # Expose the `page` method to config. expose_to_config :page - def initialize(app, options_hash={}, &block) - super + PageDescriptor = Struct.new(:path, :metadata) do + def execute_descriptor(app, resources) + normalized_path = path.dup - @page_configs = Set.new - end - - # @return Array - Contract ResourceList => ResourceList - def manipulate_resource_list(resources) - resources.each do |resource| - @page_configs.each do |p| - resource.add_metadata(p[:metadata]) if Middleman::Util.path_match(p[:path], "/#{resource.path}") + if normalized_path.is_a?(String) && !normalized_path.include?('*') + # Normalize path + normalized_path = ::Middleman::Util.normalize_path(normalized_path) + if normalized_path.end_with?('/') || app.files.by_type(:source).watchers.any? { |w| (w.directory + Pathname(normalized_path)).directory? } + normalized_path = ::File.join(normalized_path, app.config[:index_file]) + end end + + 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) } + + resources end end - PageDescriptor = Struct.new(:path, :metadata) - # The page method allows options to be set for a given source path, regex, or glob. # Options that may be set include layout, locals, andx ignore. # @@ -44,28 +48,18 @@ module Middleman # @option opts [Hash] locals Local variables for the template. These will be available when the template renders. # @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}. # @return [void] - Contract Or[String, Regexp], Hash => Any + Contract Or[String, Regexp], Hash => PageDescriptor def page(path, opts={}) options = opts.dup # Default layout metadata = { - options: options, locals: options.delete(:locals) || {}, - page: options.delete(:data) || {} + page: options.delete(:data) || {}, + options: options } - if path.is_a?(String) && !path.include?('*') - # Normalize path - path = Middleman::Util.normalize_path(path) - if path.end_with?('/') || app.files.by_type(:source).watchers.any? { |w| (w.directory + Pathname(path)).directory? } - path = File.join(path, @app.config[:index_file]) - end - end - - path = '/' + Util.strip_leading_slash(path) if path.is_a?(String) - - @page_configs << PageDescriptor.new(path, metadata) + PageDescriptor.new(path, metadata) end end end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index 3a0fa464..4caa2156 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -5,13 +5,13 @@ module Middleman class Ignores < ConfigExtension self.resource_list_manipulator_priority = 0 - expose_to_config ignore: :create_ignore + expose_to_config :ignore # 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] - def create_ignore(path=nil, &block) + def ignore(path=nil, &block) @app.sitemap.invalidate_resources_not_ignored_cache! IgnoreDescriptor.new(path, block) end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb index eb7bd4e5..63b06e13 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/import.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/import.rb @@ -7,11 +7,8 @@ module Middleman class Import < ConfigExtension self.resource_list_manipulator_priority = 1 - # Expose `create_import_file` to config as `import_file` - expose_to_config import_file: :create_import_file - - # Expose `create_import_path` to config as `import_path` - expose_to_config import_path: :create_import_path + # Expose methods + expose_to_config :import_file, :import_path ImportFileDescriptor = Struct.new(:from, :to) do def execute_descriptor(app, resources) @@ -42,7 +39,7 @@ module Middleman # @param [String] to The new path. # @return [void] Contract String, String => ImportFileDescriptor - def create_import_file(from, to) + def import_file(from, to) ImportFileDescriptor.new( File.expand_path(from, @app.root), ::Middleman::Util.normalize_path(to) @@ -54,7 +51,7 @@ module Middleman # @param [Proc] block Renaming method # @return [void] Contract String, Maybe[Proc] => ImportPathDescriptor - def create_import_path(from, &block) + def import_path(from, &block) ImportPathDescriptor.new( from, block_given? ? block : proc { |path| path } diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb b/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb index 7f8a11bb..97c6d6f9 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/move_file.rb @@ -9,8 +9,8 @@ module Middleman class MoveFile < ConfigExtension self.resource_list_manipulator_priority = 101 - # Expose `create_move_file` to config as `move_file` - expose_to_config move_file: :create_move_file + # Expose `move_file` + expose_to_config :move_file MoveFileDescriptor = Struct.new(:from, :to) do def execute_descriptor(_app, resources) @@ -27,7 +27,7 @@ module Middleman # @param [String] to The new path. # @return [void] Contract String, String => MoveFileDescriptor - def create_move_file(from, to) + def move_file(from, to) MoveFileDescriptor.new( ::Middleman::Util.normalize_path(from), ::Middleman::Util.normalize_path(to) diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb index 8ff8087f..ca0b7895 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -9,8 +9,8 @@ module Middleman class Proxies < ConfigExtension self.resource_list_manipulator_priority = 0 - # Expose `create_proxy` to config as `proxy` - expose_to_config proxy: :create_proxy + # Expose `proxy` + expose_to_config :proxy # Setup a proxy from a path to a target # @param [String] path The new, proxied path to create @@ -22,7 +22,7 @@ module Middleman # @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}. # @return [ProxyDescriptor] Contract String, String, Maybe[Hash] => RespondTo[:execute_descriptor] - def create_proxy(path, target, opts={}) + def proxy(path, target, opts={}) ProxyDescriptor.new( ::Middleman::Util.normalize_path(path), ::Middleman::Util.normalize_path(target), diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb b/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb index f6ac7bcc..47ffd726 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb @@ -6,43 +6,31 @@ module Middleman module Extensions # Manages the list of proxy configurations and manipulates the sitemap # to include new resources based on those configurations - class Redirects < Extension + class Redirects < ConfigExtension self.resource_list_manipulator_priority = 0 - # Expose `create_redirect` to config as `redirect` - expose_to_config redirect: :create_redirect + # Expose `redirect` + expose_to_config :redirect - def initialize(app, config={}, &block) - super + RedirectDescriptor = Struct.new(:path, :to, :template) do + def execute_descriptor(app, resources) + r = RedirectResource.new( + app.sitemap, + path, + to + ) + r.output = template if template - @redirects = {} + resources + [r] + end end # 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, IsA['Middleman::Sitemap::Resource']] }), Maybe[Proc] => Any - def create_redirect(path, opts={}, &block) - opts[:template] = block if block_given? - - @redirects[path] = opts - - @app.sitemap.rebuild_resource_list!(:added_redirect) - end - - # Update the main sitemap resource list - # @return Array - Contract ResourceList => ResourceList - def manipulate_resource_list(resources) - resources + @redirects.map do |path, opts| - r = RedirectResource.new( - @app.sitemap, - path, - opts[:to] - ) - r.output = opts[:template] if opts[:template] - r - end + 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 end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb b/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb index 245df873..ede1cc64 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb @@ -3,53 +3,35 @@ require 'middleman-core/sitemap/resource' module Middleman module Sitemap module Extensions - class RequestEndpoints < Extension + class RequestEndpoints < ConfigExtension self.resource_list_manipulator_priority = 0 - # Expose `create_endpoint` to config as `endpoint` - expose_to_config endpoint: :create_endpoint + # Expose `endpoint` + expose_to_config :endpoint - # Manages the list of proxy configurations and manipulates the sitemap - # to include new resources based on those configurations - def initialize(app, config={}, &block) - super + EndpointDescriptor = Struct.new(:path, :request_path, :block) do + def execute_descriptor(app, resources) + r = EndpointResource.new( + app.sitemap, + path, + request_path + ) + r.output = block if block - @endpoints = {} + resources + [r] + end end # Setup a proxy from a path to a target # @param [String] path # @param [Hash] opts The :path value gives a request path if it # differs from the output path - Contract String, Or[({ path: String }), Proc] => Any - def create_endpoint(path, opts={}, &block) - endpoint = { - request_path: path - } - + Contract String, Or[{ path: String }, Proc] => EndpointDescriptor + def endpoint(path, opts={}, &block) if block_given? - endpoint[:output] = block + EndpointDescriptor.new(path, path, block) else - endpoint[:request_path] = opts[:path] if opts.key?(:path) - end - - @endpoints[path] = endpoint - - @app.sitemap.rebuild_resource_list!(:added_endpoint) - end - - # Update the main sitemap resource list - # @return Array - Contract ResourceList => ResourceList - def manipulate_resource_list(resources) - resources + @endpoints.map do |path, config| - r = EndpointResource.new( - @app.sitemap, - path, - config[:request_path] - ) - r.output = config[:output] if config.key?(:output) - r + EndpointDescriptor.new(path, opts[:path] || path, nil) end end end diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index b433417f..985b3ae4 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -3,46 +3,48 @@ require 'active_support/core_ext/hash/deep_merge' require 'monitor' require 'hamster' +require 'middleman-core/extensions' + # Files on Disk -Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/on_disk' - Middleman::Sitemap::Extensions::OnDisk + ::Middleman::Sitemap::Extensions::OnDisk end # Files on Disk (outside the project root) -Middleman::Extensions.register :sitemap_import, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_import, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/import' - Middleman::Sitemap::Extensions::Import + ::Middleman::Sitemap::Extensions::Import end # Endpoints -Middleman::Extensions.register :sitemap_endpoint, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_endpoint, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/request_endpoints' - Middleman::Sitemap::Extensions::RequestEndpoints + ::Middleman::Sitemap::Extensions::RequestEndpoints end # Proxies -Middleman::Extensions.register :sitemap_proxies, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_proxies, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/proxies' - Middleman::Sitemap::Extensions::Proxies + ::Middleman::Sitemap::Extensions::Proxies end # Redirects -Middleman::Extensions.register :sitemap_redirects, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_redirects, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/redirects' - Middleman::Sitemap::Extensions::Redirects + ::Middleman::Sitemap::Extensions::Redirects end # Move Files -Middleman::Extensions.register :sitemap_move_files, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_move_files, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/move_file' - Middleman::Sitemap::Extensions::MoveFile + ::Middleman::Sitemap::Extensions::MoveFile end # Ignores -Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do +::Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do require 'middleman-core/sitemap/extensions/ignores' - Middleman::Sitemap::Extensions::Ignores + ::Middleman::Sitemap::Extensions::Ignores end require 'middleman-core/contracts' diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index e994e09c..c4210a0e 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -10,6 +10,9 @@ require 'rack/mime' # DbC require 'middleman-core/contracts' +require 'middleman-core/application' +require 'middleman-core/sources' +require 'middleman-core/sitemap/resource' # Indifferent Access require 'hashie' @@ -104,7 +107,7 @@ module Middleman Contract String => String def normalize_path(path) # The tr call works around a bug in Ruby's Unicode handling - URI.decode(path).sub(%r{^/}, '').tr('', '') + ::URI.decode(path).sub(%r{^/}, '').tr('', '') end # This is a separate method from normalize_path in case we @@ -167,7 +170,7 @@ module Middleman # @param [String, Symbol] source The path to the file # @param [Hash] options Data to pass through. # @return [String] - Contract IsA['Middleman::Application'], Symbol, Or[String, Symbol], Hash => String + Contract ::Middleman::Application, Symbol, Or[String, Symbol], Hash => String def asset_path(app, kind, source, options={}) return source if source.to_s.include?('//') || source.to_s.start_with?('data:') @@ -198,7 +201,7 @@ module Middleman # @param [String] prefix The type prefix (such as "images") # @param [Hash] options Data to pass through. # @return [String] The fully qualified asset url - Contract IsA['Middleman::Application'], String, String, Hash => String + Contract ::Middleman::Application, String, String, Hash => String def asset_url(app, path, prefix='', options={}) # Don't touch assets which already have a full path return path if path.include?('//') || path.start_with?('data:') @@ -221,7 +224,7 @@ module Middleman end end - final_result = URI.encode(relative_path_from_resource(options[:current_resource], result, options[:relative])) + final_result = ::URI.encode(relative_path_from_resource(options[:current_resource], result, options[:relative])) result_uri = URI(final_result) result_uri.query = uri.query @@ -232,7 +235,7 @@ module Middleman # Given a source path (referenced either absolutely or relatively) # or a Resource, this will produce the nice URL configured for that # path, respecting :relative_links, directory indexes, etc. - Contract IsA['Middleman::Application'], Or[String, IsA['Middleman::Sitemap::Resource']], Hash => String + Contract ::Middleman::Application, Or[String, ::Middleman::Sitemap::Resource], Hash => String def url_for(app, path_or_resource, options={}) # Handle Resources and other things which define their own url method url = if path_or_resource.respond_to?(:url) @@ -244,7 +247,7 @@ module Middleman # Try to parse URL begin uri = URI(url) - rescue URI::InvalidURIError + rescue ::URI::InvalidURIError # Nothing we can do with it, it's not really a URI return url end @@ -287,7 +290,7 @@ module Middleman if resource uri.path = if this_resource - URI.encode(relative_path_from_resource(this_resource, resource_url, effective_relative)) + ::URI.encode(relative_path_from_resource(this_resource, resource_url, effective_relative)) else resource_url end @@ -311,7 +314,7 @@ module Middleman # @param [String] path Request path/ # @param [Middleman::Application] app The requesting app. # @return [String] Path with index file if necessary. - Contract String, IsA['Middleman::Application'] => String + Contract String, ::Middleman::Application => String def full_path(path, app) resource = app.sitemap.find_resource_by_destination_path(path) @@ -422,7 +425,7 @@ module Middleman # @param [String] resource_url The target url. # @param [Boolean] relative If the path should be relative. # @return [String] - Contract IsA['Middleman::Sitemap::Resource'], String, Bool => String + Contract ::Middleman::Sitemap::Resource, String, Bool => String def relative_path_from_resource(curr_resource, resource_url, relative) # Switch to the relative path between resource and the given resource # if we've been asked to. @@ -480,7 +483,7 @@ module Middleman # # @param [Pathname] path The path. # @return [Middleman::SourceFile] - Contract Pathname, Pathname, Symbol, Bool => IsA['Middleman::SourceFile'] + Contract Pathname, Pathname, Symbol, Bool => ::Middleman::SourceFile def path_to_source_file(path, directory, type, destination_dir) types = Set.new([type]) @@ -496,7 +499,7 @@ module Middleman # @param [Middleman::Application] app The app. # @param [Pathname] files The original touched file paths. # @return [Middleman::SourceFile] All related file paths, not including the source file paths. - Contract IsA['Middleman::Application'], ArrayOf[Pathname] => ArrayOf[IsA['Middleman::SourceFile']] + Contract ::Middleman::Application, ArrayOf[Pathname] => ArrayOf[::Middleman::SourceFile] def find_related_files(app, files) all_extensions = files.flat_map { |f| collect_extensions(f.to_s) } @@ -546,7 +549,7 @@ module Middleman tmpl_src = tmpl_src.gsub(/:([A-Za-z0-9]+)/, '{\1}') end - Addressable::Template.new ::Middleman::Util.normalize_path(tmpl_src) + ::Addressable::Template.new ::Middleman::Util.normalize_path(tmpl_src) end # Apply a URI template with the given data, producing a normalized @@ -556,7 +559,7 @@ module Middleman # @param [Hash] data # @return [String] normalized path def apply_uri_template(template, data) - ::Middleman::Util.normalize_path Addressable::URI.unencode(template.expand(data)).to_s + ::Middleman::Util.normalize_path ::Addressable::URI.unencode(template.expand(data)).to_s end # Use a template to extract parameters from a path, and validate some special (date) From 18e4ee41d014dc36b3fc1626863ff560abf71ec6 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 12 Jan 2016 10:46:50 -0800 Subject: [PATCH 036/178] Allow 2.3 failure --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ef9608ce..42c2903d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ os: matrix: fast_finish: true allow_failures: - - 2.3.0 + - rvm: 2.3.0 - rvm: ruby-head env: global: From 8daa5eba3efde9dd7b478b61e2444aff28e974b4 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 12 Jan 2016 10:53:25 -0800 Subject: [PATCH 037/178] Add back app.ignore --- middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index 4caa2156..dfd513c2 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -5,6 +5,7 @@ module Middleman class Ignores < ConfigExtension self.resource_list_manipulator_priority = 0 + expose_to_application :ignore expose_to_config :ignore # Ignore a path or add an ignore callback From c213bd19dfb1b5b804d60fb83902c77f97b1d357 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 12 Jan 2016 16:03:23 -0800 Subject: [PATCH 038/178] Move block run --- .../lib/middleman-core/application.rb | 34 ++-- .../middleman-core/core_extensions/data.rb | 3 +- .../core_extensions/default_helpers.rb | 4 +- .../core_extensions/external_helpers.rb | 17 +- .../middleman-core/core_extensions/routing.rb | 4 +- .../core_extensions/show_exceptions.rb | 8 +- .../lib/middleman-core/extension.rb | 17 ++ .../lib/middleman-core/extension_manager.rb | 2 + .../lib/middleman-core/extensions.rb | 12 ++ .../lib/middleman-core/renderers/less.rb | 5 +- .../lib/middleman-core/renderers/markdown.rb | 10 +- .../lib/middleman-core/renderers/sass.rb | 21 ++- .../lib/middleman-core/renderers/stylus.rb | 6 +- .../lib/middleman-core/util/data.rb | 168 +++++++++--------- 14 files changed, 161 insertions(+), 150 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 88b6385a..be603df4 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -70,27 +70,27 @@ module Middleman # Which port preview should start on. # @return [Fixnum] - config.define_setting :port, 4567, 'The preview server port' + define_setting :port, 4567, 'The preview server port' # Which server name should be used # @return [NilClass, String] - config.define_setting :server_name, nil, 'The server name of preview server' + define_setting :server_name, nil, 'The server name of preview server' # Which bind address the preview server should use # @return [NilClass, String] - config.define_setting :bind_address, nil, 'The bind address of the preview server' + define_setting :bind_address, nil, 'The bind address of the preview server' # Whether to serve the preview server over HTTPS. # @return [Boolean] - config.define_setting :https, false, 'Serve the preview server over SSL/TLS' + define_setting :https, false, 'Serve the preview server over SSL/TLS' # The (optional) path to the SSL cert to use for the preview server. # @return [String] - config.define_setting :ssl_certificate, nil, 'Path to an X.509 certificate to use for the preview server' + define_setting :ssl_certificate, nil, 'Path to an X.509 certificate to use for the preview server' # The (optional) private key for the certificate in :ssl_certificate. # @return [String] - config.define_setting :ssl_private_key, nil, "Path to an RSA private key for the preview server's certificate" + define_setting :ssl_private_key, nil, "Path to an RSA private key for the preview server's certificate" # Name of the source directory # @return [String] @@ -214,6 +214,7 @@ module Middleman @callbacks.install_methods!(self, [ :initialized, :configure, + :before_extensions, :before_sitemap, :before_configuration, :after_configuration, @@ -245,6 +246,8 @@ module Middleman ::Middleman::FileRenderer.cache.clear ::Middleman::TemplateRenderer.cache.clear + execute_callbacks(:before_extensions) + @extensions = ::Middleman::ExtensionManager.new(self) # Evaluate a passed block if given @@ -257,13 +260,6 @@ module Middleman ::Middleman::Extension.clear_after_extension_callbacks - after_configuration_eval(&method(:prune_tilt_templates)) - - start_lifecycle - end - - # Boot the app. - def start_lifecycle # Before config is parsed, before extensions get to it. execute_callbacks(:initialized) @@ -273,10 +269,6 @@ module Middleman # Eval config. evaluate_configuration! - if Object.const_defined?(:Encoding) - Encoding.default_external = config[:encoding] - end - # Run any `configure` blocks for the current environment. execute_callbacks([:configure, config[:environment]]) @@ -286,6 +278,12 @@ module Middleman # Post parsing, pre-extension callback execute_callbacks(:after_configuration_eval) + if Object.const_defined?(:Encoding) + Encoding.default_external = config[:encoding] + end + + prune_tilt_templates! + # After extensions have worked after_config execute_callbacks(:after_configuration) @@ -317,7 +315,7 @@ module Middleman end # Clean up missing Tilt exts - def prune_tilt_templates + def prune_tilt_templates! ::Tilt.mappings.each do |key, _| begin ::Tilt[".#{key}"] diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index f1762e43..22d571be 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -8,6 +8,8 @@ module Middleman class Data < Extension attr_reader :data_store + define_setting :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 @@ -21,7 +23,6 @@ module Middleman super @data_store = DataStore.new(app, DATA_FILE_MATCHER) - app.config.define_setting :data_dir, 'data', 'The directory data files are stored in' start_watching(app.config[:data_dir]) 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 3187bf22..be6371c1 100644 --- a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb @@ -17,6 +17,8 @@ class Padrino::Helpers::OutputHelpers::ErbHandler end class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension + define_setting :relative_links, false, 'Whether to generate relative links instead of absolute ones' + def initialize(app, options_hash={}, &block) super @@ -30,8 +32,6 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension ::Middleman::TemplateContext.send :include, ::Padrino::Helpers::RenderHelpers ::Middleman::TemplateContext.send :include, ::Padrino::Helpers::NumberHelpers # ::Middleman::TemplateContext.send :include, ::Padrino::Helpers::TranslationHelpers - - app.config.define_setting :relative_links, false, 'Whether to generate relative links instead of absolute ones' end # The helpers diff --git a/middleman-core/lib/middleman-core/core_extensions/external_helpers.rb b/middleman-core/lib/middleman-core/core_extensions/external_helpers.rb index 7f662aec..b4be1a68 100644 --- a/middleman-core/lib/middleman-core/core_extensions/external_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/external_helpers.rb @@ -2,17 +2,12 @@ module Middleman module CoreExtensions # Load helpers in `helpers/` class ExternalHelpers < Extension - def initialize(app, options_hash={}, &block) - super - - # Setup a default helpers paths - app.config.define_setting :helpers_dir, 'helpers', 'Directory to autoload helper modules from' - app.config.define_setting :helpers_filename_glob, '**.rb', 'Glob pattern for matching helper ruby files' - app.config.define_setting :helpers_filename_to_module_name_proc, proc { |filename| - basename = File.basename(filename, File.extname(filename)) - basename.camelcase - }, 'Proc implementing the conversion from helper filename to module name' - end + define_setting :helpers_dir, 'helpers', 'Directory to autoload helper modules from' + define_setting :helpers_filename_glob, '**.rb', 'Glob pattern for matching helper ruby files' + define_setting :helpers_filename_to_module_name_proc, proc { |filename| + basename = File.basename(filename, File.extname(filename)) + basename.camelcase + }, 'Proc implementing the conversion from helper filename to module name' def after_configuration helpers_path = File.join(app.root, app.config[:helpers_dir]) diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb index cf024d7d..c5655dfe 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/core_extensions/show_exceptions.rb b/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb index b6407100..fec4f7bf 100644 --- a/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb +++ b/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb @@ -3,13 +3,7 @@ require 'rack/showexceptions' # Support rack/showexceptions during development module Middleman::CoreExtensions class ShowExceptions < ::Middleman::Extension - def initialize(app, options_hash={}, &block) - super - - return if app.config.defines_setting? :show_exceptions - - app.config.define_setting :show_exceptions, ENV['TEST'] ? false : true, 'Whether to catch and display exceptions' - end + define_setting :show_exceptions, ENV['TEST'] ? false : true, 'Whether to catch and display exceptions' def ready app.use ::Rack::ShowExceptions if !app.build? && app.config[:show_exceptions] diff --git a/middleman-core/lib/middleman-core/extension.rb b/middleman-core/lib/middleman-core/extension.rb index 5fd80a76..a94a9e12 100644 --- a/middleman-core/lib/middleman-core/extension.rb +++ b/middleman-core/lib/middleman-core/extension.rb @@ -135,6 +135,23 @@ module Middleman config.define_setting(key, default, description, options) end + # @api private + # @return [Middleman::Configuration::ConfigurationManager] The defined global options for this extension. + def global_config + @_global_config ||= ::Middleman::Configuration::ConfigurationManager.new + end + + # Add an global option to this extension. + # @see Middleman::Configuration::ConfigurationManager#define_setting + # @example + # option :compress, false, 'Whether to compress the output' + # @param [Symbol] key The name of the option + # @param [Object] default The default value for the option + # @param [String] description A human-readable description of what the option does + def define_setting(key, default=nil, description=nil, options={}) + global_config.define_setting(key, default, description, options) + end + # Short-hand for simple Sitemap manipulation # @example A generator which returns an array of resources # resources :make_resources diff --git a/middleman-core/lib/middleman-core/extension_manager.rb b/middleman-core/lib/middleman-core/extension_manager.rb index 4e2040eb..cc297b38 100644 --- a/middleman-core/lib/middleman-core/extension_manager.rb +++ b/middleman-core/lib/middleman-core/extension_manager.rb @@ -9,6 +9,8 @@ module Middleman @app = app @activated = {} + ::Middleman::Extensions.load_settings(@app) + manager = self { diff --git a/middleman-core/lib/middleman-core/extensions.rb b/middleman-core/lib/middleman-core/extensions.rb index 42fbdb2d..c295efe3 100644 --- a/middleman-core/lib/middleman-core/extensions.rb +++ b/middleman-core/lib/middleman-core/extensions.rb @@ -120,6 +120,18 @@ module Middleman app.extensions.activate descriptor[:name] end end + + def load_settings(app) + registered.each do |name, _| + begin + ext = load(name) + unless ext.global_config.all_settings.empty? + app.config.load_settings(ext.global_config.all_settings) + end + rescue LoadError + end + end + end end end end diff --git a/middleman-core/lib/middleman-core/renderers/less.rb b/middleman-core/lib/middleman-core/renderers/less.rb index a2f94a0c..715033e7 100644 --- a/middleman-core/lib/middleman-core/renderers/less.rb +++ b/middleman-core/lib/middleman-core/renderers/less.rb @@ -4,12 +4,11 @@ module Middleman module Renderers # Sass renderer class Less < ::Middleman::Extension + define_setting :less, {}, 'LESS compiler options' + def initialize(app, options={}, &block) super - # Default less options - app.config.define_setting :less, {}, 'LESS compiler options' - # Tell Tilt to use it as well (for inline sass blocks) ::Tilt.register 'less', LocalLoadingLessTemplate ::Tilt.prefer(LocalLoadingLessTemplate) diff --git a/middleman-core/lib/middleman-core/renderers/markdown.rb b/middleman-core/lib/middleman-core/renderers/markdown.rb index 6a285a89..e8acb45a 100644 --- a/middleman-core/lib/middleman-core/renderers/markdown.rb +++ b/middleman-core/lib/middleman-core/renderers/markdown.rb @@ -2,14 +2,8 @@ module Middleman module Renderers # Markdown renderer class Markdown < ::Middleman::Extension - # Once registered - def initialize(app, options={}, &block) - super - - # Set our preference for a markdown engine - app.config.define_setting :markdown_engine, :kramdown, 'Preferred markdown engine' - app.config.define_setting :markdown_engine_prefix, ::Tilt, 'The parent module for markdown template engines' - end + define_setting :markdown_engine, :kramdown, 'Preferred markdown engine' + define_setting :markdown_engine_prefix, ::Tilt, 'The parent module for markdown template engines' # Once configuration is parsed def after_configuration diff --git a/middleman-core/lib/middleman-core/renderers/sass.rb b/middleman-core/lib/middleman-core/renderers/sass.rb index 4e1efe0a..f71f8a9d 100644 --- a/middleman-core/lib/middleman-core/renderers/sass.rb +++ b/middleman-core/lib/middleman-core/renderers/sass.rb @@ -1,9 +1,17 @@ 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' + define_setting :sass_assets_paths, [], 'Paths to extra SASS/SCSS files' + define_setting :sass_source_maps, nil, 'Whether to inline sourcemap into Sass' + # Setup extension def initialize(app, options={}, &block) super @@ -12,15 +20,6 @@ module Middleman app.files.ignore :sass_cache, :source, /(^|\/)\.sass-cache\// - opts = { output_style: :nested } - opts[:line_comments] = false if ENV['TEST'] - - # Default sass options - app.config.define_setting :sass, opts, 'Sass engine options' - - app.config.define_setting :sass_assets_paths, [], 'Paths to extra SASS/SCSS files' - app.config.define_setting :sass_source_maps, app.development?, 'Whether to inline sourcemap into Sass' - # Tell Tilt to use it as well (for inline sass blocks) ::Tilt.register 'sass', SassPlusCSSFilenameTemplate ::Tilt.prefer(SassPlusCSSFilenameTemplate) @@ -75,7 +74,7 @@ module Middleman ctx = @context more_opts = { - load_paths: ::Sass.load_paths | ctx.config[:sass_assets_paths], + load_paths: ::Sass.load_paths | ctx.app.config[:sass_assets_paths], filename: eval_file, line: line, syntax: syntax, @@ -85,7 +84,7 @@ module Middleman ) } - if ctx.config[:sass_source_maps] + if ctx.app.config[:sass_source_maps] || (ctx.app.config[:sass_source_maps].nil? && ctx.app.development?) more_opts[:source_map_file] = '.' more_opts[:source_map_embed] = true more_opts[:source_map_contents] = true diff --git a/middleman-core/lib/middleman-core/renderers/stylus.rb b/middleman-core/lib/middleman-core/renderers/stylus.rb index 19bc0f17..c116aa3f 100644 --- a/middleman-core/lib/middleman-core/renderers/stylus.rb +++ b/middleman-core/lib/middleman-core/renderers/stylus.rb @@ -4,11 +4,7 @@ require 'stylus/tilt' module Middleman module Renderers class Stylus < ::Middleman::Extension - def initialize(app, options={}, &block) - super - - app.config.define_setting :styl, {}, 'Stylus config options' - end + define_setting :styl, {}, 'Stylus config options' end end end diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb index 0b3d0967..c1dc1cd3 100644 --- a/middleman-core/lib/middleman-core/util/data.rb +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -5,98 +5,102 @@ require 'middleman-core/util' require 'middleman-core/contracts' require 'backports/2.1.0/array/to_h' -module Middleman::Util::Data - include Contracts +module Middleman + module Util + module Data + include Contracts - module_function + module_function - # 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) - return [{}, nil] if Middleman::Util.binary?(full_path) + # 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) + return [{}, nil] if Middleman::Util.binary?(full_path) - # Avoid weird race condition when a file is renamed - begin - content = File.read(full_path) - rescue EOFError, IOError, Errno::ENOENT - return [{}, nil] - end + # Avoid weird race condition when a file is renamed + begin + content = File.read(full_path) + rescue EOFError, IOError, Errno::ENOENT + return [{}, nil] + end - start_delims, stop_delims = frontmatter_delims - .values - .flatten(1) - .transpose - .map(&Regexp.method(:union)) + start_delims, stop_delims = frontmatter_delims + .values + .flatten(1) + .transpose + .map(&Regexp.method(:union)) - match = / - \A(?:[^\r\n]*coding:[^\r\n]*\r?\n)? - (?#{start_delims})[ ]*\r?\n - (?.*?)[ ]*\r?\n? - ^(?#{stop_delims})[ ]*\r?\n? - \r?\n? - (?.*) - /mx.match(content) || {} + match = / + \A(?:[^\r\n]*coding:[^\r\n]*\r?\n)? + (?#{start_delims})[ ]*\r?\n + (?.*?)[ ]*\r?\n? + ^(?#{stop_delims})[ ]*\r?\n? + \r?\n? + (?.*) + /mx.match(content) || {} - unless match[:frontmatter] - case known_type - when :yaml - return [parse_yaml(content, full_path), nil] - when :json - return [parse_json(content, full_path), nil] + unless match[:frontmatter] + case known_type + when :yaml + return [parse_yaml(content, full_path), nil] + when :json + return [parse_json(content, full_path), nil] + end + end + + case [match[:start], match[:stop]] + when *frontmatter_delims[:yaml] + [ + parse_yaml(match[:frontmatter], full_path), + match[:additional_content] + ] + when *frontmatter_delims[:json] + [ + parse_json("{#{match[:frontmatter]}}", full_path), + match[:additional_content] + ] + else + [ + {}, + content + ] + end end - end - case [match[:start], match[:stop]] - when *frontmatter_delims[:yaml] - [ - parse_yaml(match[:frontmatter], full_path), - match[:additional_content] - ] - when *frontmatter_delims[:json] - [ - parse_json("{#{match[:frontmatter]}}", full_path), - match[:additional_content] - ] - else - [ - {}, - content - ] - end - end + # Parse YAML frontmatter out of a string + # @param [String] content + # @return [Hash] + Contract String, Pathname, Bool => Hash + def parse_yaml(content, full_path) + symbolize_recursive(YAML.load(content) || {}) + rescue StandardError, Psych::SyntaxError => error + warn "YAML Exception parsing #{full_path}: #{error.message}" + {} + end - # Parse YAML frontmatter out of a string - # @param [String] content - # @return [Hash] - Contract String, Pathname, Bool => Hash - def parse_yaml(content, full_path) - symbolize_recursive(YAML.load(content) || {}) - rescue StandardError, Psych::SyntaxError => error - warn "YAML Exception parsing #{full_path}: #{error.message}" - {} - end + # Parse JSON frontmatter out of a string + # @param [String] content + # @return [Hash] + Contract String, Pathname => Hash + def parse_json(content, full_path) + symbolize_recursive(JSON.parse(content) || {}) + rescue StandardError => error + warn "JSON Exception parsing #{full_path}: #{error.message}" + {} + end - # Parse JSON frontmatter out of a string - # @param [String] content - # @return [Hash] - Contract String, Pathname => Hash - def parse_json(content, full_path) - symbolize_recursive(JSON.parse(content) || {}) - rescue StandardError => error - warn "JSON Exception parsing #{full_path}: #{error.message}" - {} - end - - def symbolize_recursive(value) - case value - when Hash - value.map { |k, v| [k.to_sym, symbolize_recursive(v)] }.to_h - when Array - value.map { |v| symbolize_recursive(v) } - else - value + def symbolize_recursive(value) + case value + when Hash + value.map { |k, v| [k.to_sym, symbolize_recursive(v)] }.to_h + when Array + value.map { |v| symbolize_recursive(v) } + else + value + end + end end end end From 5f8beba4b37c4fa8b9be4a6dc92927df3be3857c Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 13 Jan 2016 17:16:36 -0800 Subject: [PATCH 039/178] 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 040/178] 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 041/178] 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 042/178] 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 043/178] 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 044/178] 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 045/178] 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 046/178] 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 047/178] 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 048/178] 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 049/178] 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 050/178] 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 051/178] 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 052/178] 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 053/178] 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 054/178] 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 055/178] 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 056/178] 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 057/178] 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 058/178] 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 059/178] 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 060/178] 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 061/178] 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 062/178] 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 063/178] 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 064/178] 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 065/178] 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 066/178] 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 067/178] 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?('