diff --git a/.rubocop.yml b/.rubocop.yml index dbd74993..c92b709f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -67,3 +67,5 @@ Style/MultilineBlockChain: Enabled: false Style/SpecialGlobalVars: Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false diff --git a/.travis.yml b/.travis.yml index e6bc197b..ac5a7f06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,6 @@ rvm: - ruby-head - 2.3.1 - 2.2.4 - - 2.1 - - 2.0 os: - linux # - osx diff --git a/CHANGELOG.md b/CHANGELOG.md index a6494a17..148aa2e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ master === +# 4.1.13 + +* Change how config options are passed to Thor. Removes new Thor warnings from #2017 + +# 4.1.12 + +* Fix broken `ignore { |p| true }` form. + +# 4.1.11 + +* Upgrade to Rack 2. + # 4.1.10 * Fix unicode issues in URL deeplinks. diff --git a/Gemfile b/Gemfile index f14eb3b1..db4043a0 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,12 @@ gem 'byebug' gem 'aruba', '~> 0.7.4', require: false gem 'rspec', '~> 3.0', require: false gem 'cucumber', '~> 2.0', require: false +gem 'addressable', '~> 2.4.0', require: false + +# Pry tools +gem 'pry' +gem 'pry-stack_explorer' +gem 'pry-rescue' # Optional middleman dependencies, included for tests gem 'haml', '>= 4.0.5', require: false @@ -18,7 +24,7 @@ gem 'kramdown', '~> 1.2', require: false gem 'slim', '>= 2.0', require: false gem 'liquid', '>= 2.6', require: false gem 'stylus', '>= 1.0', require: false -gem 'sinatra', '>= 1.4', require: false +gem 'sinatra', '>= 2.0.0.beta2', require: false gem 'redcarpet', '>= 3.1', require: false # Dns server to test preview server @@ -26,7 +32,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 +gem 'phantomjs', '~> 2.1.1.0', require: false # For less, note there is no compatible JS runtime for windows gem 'therubyrhino', '>= 2.0', platforms: :jruby diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..6d2dc0e0 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,9 @@ +## Expected behavior and actual behavior + +## Steps to reproduce the problem (from a clean middleman installation) + +## Additional information + +- Ruby version: +- Middleman version: +- OS version: diff --git a/middleman-cli/bin/middleman b/middleman-cli/bin/middleman index 46fa5889..8b381a08 100755 --- a/middleman-cli/bin/middleman +++ b/middleman-cli/bin/middleman @@ -25,12 +25,10 @@ module Middleman::Cli if setting.default.is_a?(String) || setting.default.is_a?(NilClass) base.class_option setting.key, type: :string, - default: :undefined, desc: setting.description elsif setting.default.is_a?(TrueClass) || setting.default.is_a?(FalseClass) base.class_option setting.key, type: :boolean, - default: :undefined, desc: setting.description end end diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index df871ce2..9e521dde 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -29,7 +29,7 @@ module Middleman::Cli default: false, desc: 'Print debug messages' class_option :instrument, - type: :string, + type: :boolean, default: false, desc: 'Print instrument messages' class_option :profile, @@ -64,7 +64,7 @@ module Middleman::Cli config[:mode] = :build config[:show_exceptions] = false config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum| - sum[k] = v unless v == :undefined + sum[k] = v end end diff --git a/middleman-cli/lib/middleman-cli/server.rb b/middleman-cli/lib/middleman-cli/server.rb index 479f53bd..85e75a9f 100644 --- a/middleman-cli/lib/middleman-cli/server.rb +++ b/middleman-cli/lib/middleman-cli/server.rb @@ -17,7 +17,7 @@ module Middleman::Cli default: false, desc: 'Print debug messages' class_option :instrument, - type: :string, + type: :boolean, default: false, desc: 'Print instrument messages' class_option :profile, diff --git a/middleman-cli/middleman-cli.gemspec b/middleman-cli/middleman-cli.gemspec index f2719efc..e9447a9c 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 = '>= 2.0.0' + s.required_ruby_version = '>= 2.2.0' # CLI s.add_dependency('thor', ['>= 0.17.0', '< 2.0']) diff --git a/middleman-core/features/asset_host.feature b/middleman-core/features/asset_host.feature index 646f1154..0433b61b 100644 --- a/middleman-core/features/asset_host.feature +++ b/middleman-core/features/asset_host.feature @@ -25,7 +25,8 @@ Feature: Alternate between multiple asset hosts And a file named "config.rb" with: """ activate :asset_host, host: Proc.new { |asset| - "http://assets%d.example.com" % (asset.hash % 4) + hash = Digest::MD5.digest(asset).bytes.map!(&:ord).reduce(&:+) + "http://assets%d.example.com" % (hash % 4) } """ And the Server is running diff --git a/middleman-core/features/page-id.feature b/middleman-core/features/page-id.feature index 63dd6fad..74d08cb5 100644 --- a/middleman-core/features/page-id.feature +++ b/middleman-core/features/page-id.feature @@ -3,14 +3,60 @@ Feature: Page IDs Scenario: link_to works with blocks (erb) Given the Server is running at "page-id-app" When I go to "/index.html" - Then I should see "I am: index.html" + Then I should see "I am: index" And I should see "URL1: /fm.html" And I should see "URL2: /2.html" And I should see 'URL3: Hi' And I should see 'URL4: Sym' + And I should see 'URL5: Imp' + And I should see 'URL6: Foldern' + And I should see 'URL7: Feed' When I go to "/fm.html" Then I should see "I am: frontmatter" + When I go to "/implicit.html" + Then I should see "I am: implicit" + When I go to "/feed.xml" + Then I should see "I am: feed.xml" + When I go to "/folder/foldern.html" + Then I should see "I am: folder/foldern" + + When I go to "/1.html" + Then I should see "I am: page1" + When I go to "/2.html" + Then I should see "I am: page2" + When I go to "/3.html" + Then I should see "I am: page3" + + When I go to "/overwrites/from-default.html" + Then I should see "I am: something-else" + + When I go to "/overwrites/from-frontmatter.html" + Then I should see "I am: from_frontmatter" + + Scenario: Override page ID derivation with a proc + Given a fixture app "page-id-app" + And app "page-id-app" is using config "proc" + And the Server is running at "page-id-app" + + When I go to "/index.html" + Then I should see "I am: index.html-foo" + And I should see "URL1: /fm.html" + And I should see "URL2: /2.html" + And I should see 'URL3: Hi' + And I should see 'URL4: Sym' + And I should see 'URL8: Imp' + And I should see 'URL9: Foldern' + And I should see 'URL10: Feed' + + When I go to "/fm.html" + Then I should see "I am: frontmatter" + When I go to "/implicit.html" + Then I should see "I am: implicit.html-foo" + When I go to "/feed.xml" + Then I should see "I am: feed.xml-foo" + When I go to "/folder/foldern.html" + Then I should see "I am: folder/foldern.html-foo" When I go to "/1.html" Then I should see "I am: page1" diff --git a/middleman-core/fixtures/page-id-app/config-proc.rb b/middleman-core/fixtures/page-id-app/config-proc.rb new file mode 100644 index 00000000..03070f0e --- /dev/null +++ b/middleman-core/fixtures/page-id-app/config-proc.rb @@ -0,0 +1,7 @@ +%w(1 2 3).each do |n| + proxy "/#{n}.html", "/index.html", id: "page#{n}" +end + +page "/overwrites/*", id: :"something-else" + +config[:page_id_generator] = ->(path){ path + "-foo" } diff --git a/middleman-core/fixtures/page-id-app/source/feed.xml.erb b/middleman-core/fixtures/page-id-app/source/feed.xml.erb new file mode 100644 index 00000000..a27800bd --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/feed.xml.erb @@ -0,0 +1 @@ +I am: <%= current_resource.page_id %> diff --git a/middleman-core/fixtures/page-id-app/source/folder/foldern.html.erb b/middleman-core/fixtures/page-id-app/source/folder/foldern.html.erb new file mode 100644 index 00000000..a27800bd --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/folder/foldern.html.erb @@ -0,0 +1 @@ +I am: <%= current_resource.page_id %> diff --git a/middleman-core/fixtures/page-id-app/source/implicit.html.erb b/middleman-core/fixtures/page-id-app/source/implicit.html.erb new file mode 100644 index 00000000..a27800bd --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/implicit.html.erb @@ -0,0 +1 @@ +I am: <%= current_resource.page_id %> diff --git a/middleman-core/fixtures/page-id-app/source/index.html.erb b/middleman-core/fixtures/page-id-app/source/index.html.erb index 8f2997b6..6060bc3f 100644 --- a/middleman-core/fixtures/page-id-app/source/index.html.erb +++ b/middleman-core/fixtures/page-id-app/source/index.html.erb @@ -4,3 +4,11 @@ URL1: <%= url_for "frontmatter" %> URL2: <%= url_for "page2" %> URL3: <%= link_to "Hi", "page3" %> URL4: <%= link_to "Sym", :"something-else" %> +URL5: <%= link_to "Imp", :implicit %> +URL6: <%= link_to "Foldern", "folder/foldern" %> +URL7: <%= link_to "Feed", "feed.xml" %> + +<%# If custom proc %> +URL8: <%= link_to "Imp", "implicit.html-foo" %> +URL9: <%= link_to "Foldern", "folder/foldern.html-foo" %> +URL10: <%= link_to "Feed", "feed.xml-foo" %> diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 918f65ee..52b31c92 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -203,6 +203,7 @@ module Middleman 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' + define_setting :watcher_wait_for_delay, 0.5, 'The Listen watcher delay between calls when changes exist' # Delegate convenience methods off to their implementations def_delegator :"::Middleman::Logger", :singleton, :logger @@ -344,11 +345,11 @@ module Middleman # Clean up missing Tilt exts def prune_tilt_templates! - ::Tilt.mappings.each_key do |key| + ::Tilt.default_mapping.lazy_map.each_key do |key| begin ::Tilt[".#{key}"] rescue LoadError, NameError - ::Tilt.mappings.delete(key) + ::Tilt.default_mapping.lazy_map.delete(key) end end end 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 82df8f73..6fd16ae9 100644 --- a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb +++ b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb @@ -28,10 +28,7 @@ module Middleman super # Setup source collection. - @sources = ::Middleman::Sources.new(app, - disable_watcher: app.config[:watcher_disable], - force_polling: app.config[:watcher_force_polling], - latency: app.config[:watcher_latency]) + @sources = ::Middleman::Sources.new(app) # Add default ignores. IGNORES.each do |key, value| @@ -55,6 +52,13 @@ module Middleman # @return [void] Contract Any def after_configuration + @watcher.update_config( + disable_watcher: app.config[:watcher_disable], + force_polling: app.config[:watcher_force_polling], + latency: app.config[:watcher_latency], + wait_for_delay: app.config[:watcher_wait_for_delay] + ) + if @original_source_dir != app.config[:source] @watcher.update_path(app.config[:source]) end diff --git a/middleman-core/lib/middleman-core/extensions/minify_css.rb b/middleman-core/lib/middleman-core/extensions/minify_css.rb index 2701b8f2..aca9c60b 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_css.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_css.rb @@ -72,7 +72,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension end if minified - headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s + headers['Content-Length'] = minified.bytesize.to_s response = [minified] end diff --git a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb index 22719e83..714d0645 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb @@ -64,7 +64,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension end if minified - headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s + headers['Content-Length'] = minified.bytesize.to_s response = [minified] end diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index a3e8b193..26a38dc7 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -3,8 +3,8 @@ require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/module/delegation' require 'middleman-core/contracts' -::Tilt.mappings.delete('html') # WTF, Tilt? -::Tilt.mappings.delete('csv') +::Tilt.default_mapping.lazy_map.delete('html') +::Tilt.default_mapping.lazy_map.delete('csv') module Middleman class FileRenderer @@ -123,8 +123,8 @@ module Middleman # Find all the engines which handle this extension in tilt. Look for # config variables of that name and merge it extension_class = ::Middleman::Util.tilt_class(ext) - ::Tilt.mappings.each do |mapping_ext, engines| - next unless engines.include? extension_class + + ::Tilt.default_mapping.extensions_for(extension_class).each do |mapping_ext| engine_options = @app.config[mapping_ext.to_sym] || {} options.merge!(engine_options) end diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index b70e9c99..1a3d220e 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -143,7 +143,7 @@ module Middleman app = ::Middleman::Application.new do config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum| - sum[k] = v unless v == :undefined + sum[k] = v end ready do @@ -160,6 +160,9 @@ module Middleman path: root, only: match_against + # Hack around bower_components in root. + watcher.listener.ignore(/^bower_components/) + # Hack around node_modules in root. watcher.listener.ignore(/^node_modules/) @@ -204,7 +207,7 @@ module Middleman end def possible_from_cli(key, config) - if @cli_options[key] && @cli_options[key] != :undefined + if @cli_options[key] @cli_options[key] else config[key] diff --git a/middleman-core/lib/middleman-core/rack.rb b/middleman-core/lib/middleman-core/rack.rb index 293a2e43..640dbad9 100644 --- a/middleman-core/lib/middleman-core/rack.rb +++ b/middleman-core/lib/middleman-core/rack.rb @@ -133,9 +133,15 @@ module Middleman # Immediately send static file def send_file(resource, env) - file = ::Rack::File.new nil - file.path = resource.file_descriptor[:full_path] - response = file.serving(env) + file = ::Rack::File.new nil + path = resource.file_descriptor[:full_path] + if !file.respond_to?(:path=) + request = ::Rack::Request.new(env) + response = file.serving(request, path) + else + file.path = path + response = file.serving(env) + end status = response[0] 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 diff --git a/middleman-core/lib/middleman-core/renderers/redcarpet.rb b/middleman-core/lib/middleman-core/renderers/redcarpet.rb index 1542489c..b2171f22 100644 --- a/middleman-core/lib/middleman-core/renderers/redcarpet.rb +++ b/middleman-core/lib/middleman-core/renderers/redcarpet.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/module/attribute_accessors' module Middleman module Renderers - class RedcarpetTemplate < ::Tilt::RedcarpetTemplate::Redcarpet2 + class RedcarpetTemplate < ::Tilt::RedcarpetTemplate # because tilt has decided to convert these # in the wrong direction ALIASES = { diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index dfa80304..0367c64a 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -14,16 +14,31 @@ module Middleman Contract Or[String, Regexp, Proc] => RespondTo[:execute_descriptor] def ignore(path=nil, &block) @app.sitemap.invalidate_resources_not_ignored_cache! - IgnoreDescriptor.new(path, block) + + if path.is_a? Regexp + RegexpIgnoreDescriptor.new(path) + elsif path.is_a? String + path_clean = ::Middleman::Util.normalize_path(path) + + if path_clean.include?('*') # It's a glob + GlobIgnoreDescriptor.new(path_clean) + else + StringIgnoreDescriptor.new(path_clean) + end + elsif block + BlockIgnoreDescriptor.new(nil, block) + else + IgnoreDescriptor.new(path, block) + end end 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) + if ignored?(r.normalized_path) r.ignore! - elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor[:relative_path].to_s) + elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor.normalized_relative_path) # This allows files to be ignored by their source file name (with template extensions) r.ignore! end @@ -33,27 +48,38 @@ module Middleman end def ignored?(match_path) - match_path = ::Middleman::Util.normalize_path(match_path) + raise NotImplementedError + end + end - if path.is_a? Regexp - match_path =~ path - elsif path.is_a? String - path_clean = ::Middleman::Util.normalize_path(path) + class RegexpIgnoreDescriptor < IgnoreDescriptor + def ignored?(match_path) + match_path =~ path + end + end - 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 - block.call(match_path) + class GlobIgnoreDescriptor < IgnoreDescriptor + def ignored?(match_path) + if defined?(::File::FNM_EXTGLOB) + ::File.fnmatch(path, match_path, ::File::FNM_EXTGLOB) + else + ::File.fnmatch(path, match_path) end end end + + class StringIgnoreDescriptor < IgnoreDescriptor + def ignored?(match_path) + match_path == path + end + end + + class BlockIgnoreDescriptor < IgnoreDescriptor + def ignored?(match_path) + block.call(match_path) + end + 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 b11e02eb..42098ae8 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -47,7 +47,7 @@ module Middleman ) if should_ignore - d = ::Middleman::Sitemap::Extensions::Ignores::IgnoreDescriptor.new(target) + d = ::Middleman::Sitemap::Extensions::Ignores::StringIgnoreDescriptor.new(target) d.execute_descriptor(app, resources) end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 22b13498..f3619873 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -87,7 +87,7 @@ module Middleman Contract Or[Symbol, String, Fixnum] def page_id - metadata[:page][:id] || destination_path + metadata[:page][:id] || make_implicit_page_id(destination_path) end # Merge in new metadata specific to this resource. @@ -197,10 +197,41 @@ module Middleman options[:content_type] || ::Rack::Mime.mime_type(ext, nil) end + # The normalized source path of this resource (relative to the source directory, + # without template extensions) + # @return [String] + def normalized_path + @normalized_path ||= ::Middleman::Util.normalize_path @path + end + def to_s "#<#{self.class} path=#{@path}>" end alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s + + protected + + # Makes a page id based on path (when not otherwise given) + # + # Removes .html extension and potential leading slashes or dots + # eg. "foo/bar/baz.foo.html" => "foo/bar/baz.foo" + Contract String => String + def make_implicit_page_id(path) + @id ||= begin + if prok = @app.config[:page_id_generator] + return prok.call(path) + end + + basename = if ext == ".html" + File.basename(path, ext) + else + File.basename(path) + end + + # Remove leading dot or slash if present + File.join(File.dirname(path), basename).gsub(/^\.?\//, '') + end + end end class StringResource < Resource diff --git a/middleman-core/lib/middleman-core/sources.rb b/middleman-core/lib/middleman-core/sources.rb index f0d3cc91..ced46227 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -8,6 +8,10 @@ module Middleman ::Middleman::Sources.file_cache[full_path] ||= {} ::Middleman::Sources.file_cache[full_path][version] ||= ::File.read(full_path) end + + def normalized_relative_path + @normalized_relative_path ||= ::Middleman::Util.normalize_path relative_path.to_s + end end # Sources handle multiple on-disk collections of files which make up @@ -52,15 +56,13 @@ module Middleman # @param [Hash] options Global options. # @param [Array] watchers Default watchers. Contract IsA['Middleman::Application'], Maybe[Hash], Maybe[Array] => Any - def initialize(app, options={}, watchers=[]) + def initialize(app, _options={}, watchers=[]) @app = app @watchers = watchers @sorted_watchers = @watchers.dup.freeze ::Middleman::Sources.file_cache = {} - @options = options - # Set of procs wanting to be notified of changes @on_change_callbacks = ::Hamster::Vector.empty @@ -168,7 +170,7 @@ module Middleman # @return [Middleman::Sources] Contract Symbol => ::Middleman::Sources def by_type(type) - self.class.new @app, @options, watchers.select { |d| d.type == type } + self.class.new @app, nil, watchers.select { |d| d.type == type } end # Get all files for this collection of watchers. diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 07d7ff62..8e3a3550 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -75,9 +75,10 @@ module Middleman @ignored = options.fetch(:ignored, proc { false }) @only = Array(options.fetch(:only, [])) - @disable_watcher = app.build? || @parent.options.fetch(:disable_watcher, false) - @force_polling = @parent.options.fetch(:force_polling, false) - @latency = @parent.options.fetch(:latency, nil) + @disable_watcher = app.build? + @force_polling = false + @latency = nil + @wait_for_delay = nil @listener = nil @@ -95,13 +96,20 @@ module Middleman def update_path(directory) @directory = Pathname(File.expand_path(directory, app.root)) - stop_listener! if @listener - - update([], @files.values.map { |source_file| source_file[:full_path] }) + without_listener_running do + update([], @files.values.map { |source_file| source_file[:full_path] }) + end poll_once! + end - listen! unless @disable_watcher + def update_config(options={}) + without_listener_running do + @disable_watcher = options.fetch(:disable_watcher, false) + @force_polling = options.fetch(:force_polling, false) + @latency = options.fetch(:latency, nil) + @wait_for_delay = options.fetch(:wait_for_delay, nil) + end end # Stop watching. @@ -160,10 +168,10 @@ module Middleman config = { force_polling: @force_polling, - wait_for_delay: 0.5 } - config[:latency] = @latency.to_i if @latency + config[:wait_for_delay] = @wait_for_delay.try(:to_f) || 0.5 + config[:latency] = @latency.to_f if @latency @listener = ::Listen.to(@directory.to_s, config, &method(:on_listener_change)) @@ -199,7 +207,7 @@ module Middleman Contract ArrayOf[Pathname] def poll_once! updated = ::Middleman::Util.all_files_under(@directory.to_s, &method(:should_not_recurse?)) - removed = @files.keys.reject { |p| updated.include?(p) } + removed = @files.keys - updated result = update(updated, removed) @@ -343,5 +351,20 @@ module Middleman @only.any? { |reg| file[:relative_path].to_s =~ reg } end end + + private + + def without_listener_running + listener_running = @listener && @listener.processing? + + stop_listener! if listener_running + + yield + + if listener_running + poll_once! + listen! + end + end end end diff --git a/middleman-core/lib/middleman-core/template_renderer.rb b/middleman-core/lib/middleman-core/template_renderer.rb index 0dcf2af8..8100a56d 100644 --- a/middleman-core/lib/middleman-core/template_renderer.rb +++ b/middleman-core/lib/middleman-core/template_renderer.rb @@ -64,9 +64,7 @@ module Middleman extension_class = ::Middleman::Util.tilt_class(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 + preferred_engines += ::Tilt.default_mapping.extensions_for(extension_class) end preferred_engines << '*' diff --git a/middleman-core/lib/middleman-core/util/paths.rb b/middleman-core/lib/middleman-core/util/paths.rb index 2814cfc9..2e229392 100644 --- a/middleman-core/lib/middleman-core/util/paths.rb +++ b/middleman-core/lib/middleman-core/util/paths.rb @@ -1,7 +1,7 @@ # Core Pathname library used for traversal require 'pathname' require 'uri' -require 'addressable' +require 'addressable/uri' require 'memoist' require 'tilt' @@ -152,7 +152,8 @@ module Middleman def url_for(app, path_or_resource, options={}) if path_or_resource.is_a?(String) || path_or_resource.is_a?(Symbol) r = app.sitemap.find_resource_by_page_id(path_or_resource) - path_or_resource = r if r + + path_or_resource = r ? r : path_or_resource.to_s end # Handle Resources and other things which define their own url method diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index 6f3f1228..7b1bf403 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.10'.freeze unless const_defined?(:VERSION) + VERSION = '4.1.14'.freeze unless const_defined?(:VERSION) end diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index f5509c72..38df7be7 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -16,12 +16,12 @@ 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 = '>= 2.0.0' + s.required_ruby_version = '>= 2.2.0' # Core s.add_dependency('bundler', ['~> 1.1']) - s.add_dependency('rack', ['>= 1.4.5', '< 2.0']) - s.add_dependency('tilt', ['~> 1.4.1']) + s.add_dependency('rack', ['>= 1.4.5', '< 3']) + s.add_dependency('tilt', ['~> 2.0']) s.add_dependency('erubis') s.add_dependency('fast_blank') s.add_dependency('parallel') @@ -29,7 +29,7 @@ Gem::Specification.new do |s| s.add_dependency('dotenv') # Helpers - s.add_dependency('activesupport', ['~> 4.2']) + s.add_dependency('activesupport', ['>= 4.2', '< 5.1']) s.add_dependency('padrino-helpers', ['~> 0.13.0']) s.add_dependency("addressable", ["~> 2.3"]) s.add_dependency('memoist', ['~> 0.14']) diff --git a/middleman-core/spec/middleman-core/util_spec.rb b/middleman-core/spec/middleman-core/util_spec.rb index a852521d..9c429145 100644 --- a/middleman-core/spec/middleman-core/util_spec.rb +++ b/middleman-core/spec/middleman-core/util_spec.rb @@ -220,7 +220,7 @@ describe Middleman::Util do it "does not loop infinitely when file name is a possible templating engine" do expect do - Timeout::timeout(0.5) do + Timeout::timeout(3.0) do result = Middleman::Util.step_through_extensions("markdown.scss") expect(result).to eq "markdown" end diff --git a/middleman/middleman.gemspec b/middleman/middleman.gemspec index 06dd3144..a172005f 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 = '>= 2.0.0' + s.required_ruby_version = '>= 2.2.0' s.add_dependency('middleman-core', Middleman::VERSION) s.add_dependency('middleman-cli', Middleman::VERSION)