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/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 a4415ab8..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 @@ -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/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-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 fb1ab93f..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 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/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/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index ad2d95c0..0367c64a 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -74,7 +74,7 @@ module Middleman end end - class BlockIgnoreDescriptor + class BlockIgnoreDescriptor < IgnoreDescriptor def ignored?(match_path) block.call(match_path) end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 9ff97478..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. @@ -208,6 +208,30 @@ module Middleman "#<#{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 d2f64a40..ced46227 100644 --- a/middleman-core/lib/middleman-core/sources.rb +++ b/middleman-core/lib/middleman-core/sources.rb @@ -56,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 @@ -172,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 88d75f3f..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)) @@ -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/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/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