From 83c8f9a2ce526a113db18074378f78ef71000b22 Mon Sep 17 00:00:00 2001 From: Egor Date: Sat, 2 Feb 2013 00:26:58 +0400 Subject: [PATCH 01/22] Fix huge files regression (for undetected mime) Note that binary_bytes is an array of bytes that never never appears in text. Array taken from encoding.c source from 'file' utility (http://www.darwinsys.com/file/). --- middleman-core/lib/middleman-core/util.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 46854994..fad57ca3 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -24,7 +24,14 @@ module Middleman ext = ".#{ext}" unless ext.to_s[0] == ?. mime = ::Rack::Mime.mime_type(ext, nil) - return false unless mime + unless mime + binary_bytes = [0, 1, 2, 3, 4, 5, 6, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31] + s = File.read(filename, File.stat(filename).blksize) || '' + s.each_byte do |c| + return true if binary_bytes.include?(c) + end + return false + end return false if mime.start_with?('text/') return false if mime.include?('xml') return false if mime.include?('json') From 4e884144784eac4930992fe7b47ac65cc2ed2cea Mon Sep 17 00:00:00 2001 From: Egor Vakhromtsev Date: Wed, 6 Feb 2013 12:14:24 +0400 Subject: [PATCH 02/22] blksize was replaced with fixed value because windows issues --- 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 fad57ca3..0444be7a 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -26,7 +26,7 @@ module Middleman mime = ::Rack::Mime.mime_type(ext, nil) unless mime binary_bytes = [0, 1, 2, 3, 4, 5, 6, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31] - s = File.read(filename, File.stat(filename).blksize) || '' + s = File.read(filename, 4096) || '' s.each_byte do |c| return true if binary_bytes.include?(c) end From c9290c6b11d1c0164ce516e092a2a8b7bb1fad8b Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 6 Feb 2013 13:19:09 -0800 Subject: [PATCH 03/22] Allow frontmatter to be parsed on templates outside the project root --- .../middleman-core/core_extensions/front_matter.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 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 cf64f37a..366cb0d7 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -1,3 +1,5 @@ +require 'pathname' + # Extensions namespace module Middleman::CoreExtensions @@ -128,7 +130,12 @@ module Middleman::CoreExtensions # @param [String] path # @return [Array] def frontmatter_and_content(path) - full_path = File.expand_path(File.join(@app.source_dir, path)) + full_path = if Pathname(path).relative? + File.join(@app.source_dir, path) + else + path + end + data = {} content = nil @@ -156,7 +163,7 @@ module Middleman::CoreExtensions end def normalize_path(path) - path.sub(@app.source_dir, "").sub(/^\//, "") + path.sub(%r{^#{@app.source_dir}\/}, "") end # Update the main sitemap resource list From de7e62176600dafcc54c69d3b18e76e1ee8988e1 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Fri, 8 Feb 2013 00:05:34 -0800 Subject: [PATCH 04/22] Revert the more-flexible Thor dependency since it breaks bundle install for JRuby and we will need to update Padrino when it gets upgraded anyway --- middleman-core/middleman-core-x86-mingw32.gemspec | 2 +- middleman-core/middleman-core.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-core/middleman-core-x86-mingw32.gemspec b/middleman-core/middleman-core-x86-mingw32.gemspec index 1ec32454..c91e80c9 100644 --- a/middleman-core/middleman-core-x86-mingw32.gemspec +++ b/middleman-core/middleman-core-x86-mingw32.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| s.add_dependency("rack-test", ["~> 0.6.1"]) # CLI - s.add_dependency("thor", [">= 0.15.4", "~> 0.15"]) + s.add_dependency("thor", [">~ 0.15.4"]) # Helpers s.add_dependency("activesupport", ["~> 3.2.6"]) diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 4eb1aed0..f268f2f5 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| s.add_dependency("rack-test", ["~> 0.6.1"]) # CLI - s.add_dependency("thor", [">= 0.15.4", "~> 0.15"]) + s.add_dependency("thor", [">~ 0.15.4"]) # Helpers s.add_dependency("activesupport", ["~> 3.2.6"]) From 1af96fe305d95930f3728b1091d8cae45373e130 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 10:28:55 -0800 Subject: [PATCH 05/22] Fix gemspecs --- middleman-core/middleman-core-x86-mingw32.gemspec | 2 +- middleman-core/middleman-core.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-core/middleman-core-x86-mingw32.gemspec b/middleman-core/middleman-core-x86-mingw32.gemspec index c91e80c9..d1779828 100644 --- a/middleman-core/middleman-core-x86-mingw32.gemspec +++ b/middleman-core/middleman-core-x86-mingw32.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| s.add_dependency("rack-test", ["~> 0.6.1"]) # CLI - s.add_dependency("thor", [">~ 0.15.4"]) + s.add_dependency("thor", ["~> 0.15.4"]) # Helpers s.add_dependency("activesupport", ["~> 3.2.6"]) diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index f268f2f5..c366daa3 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| s.add_dependency("rack-test", ["~> 0.6.1"]) # CLI - s.add_dependency("thor", [">~ 0.15.4"]) + s.add_dependency("thor", ["~> 0.15.4"]) # Helpers s.add_dependency("activesupport", ["~> 3.2.6"]) From 7020bdce1a0db4152e19b7284c9e0e3fe1df7555 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 12:44:37 -0800 Subject: [PATCH 06/22] Failing test for #584 "i18n fails when default locale is not english" --- middleman-more/features/i18n_preview.feature | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/middleman-more/features/i18n_preview.feature b/middleman-more/features/i18n_preview.feature index 81360e23..bfc591ef 100644 --- a/middleman-more/features/i18n_preview.feature +++ b/middleman-more/features/i18n_preview.feature @@ -103,6 +103,51 @@ Feature: i18n Preview Then I should see "Como Esta?" When I go to "/spanish/hola.html" Then I should see "Hola World" + + Scenario: Running localize with a non-English mount config + Given a fixture app "i18n-test-app" + And a file named "config.rb" with: + """ + activate :i18n, :mount_at_root => :es + """ + Given the Server is running at "i18n-test-app" + When I go to "/en/index.html" + Then I should see "Howdy" + When I go to "/en/hello.html" + Then I should see "Hello World" + When I go to "/" + Then I should see "Como Esta?" + When I go to "/hola.html" + Then I should see "Hola World" + When I go to "/hello.html" + Then I should see "File Not Found" + When I go to "/es/index.html" + Then I should see "File Not Found" + When I go to "/es/hola.html" + Then I should see "File Not Found" + + Scenario: Running localize with a non-English lang subset + Given a fixture app "i18n-test-app" + And a file named "config.rb" with: + """ + activate :i18n, :langs => :es + """ + Given the Server is running at "i18n-test-app" + When I go to "/en/index.html" + Then I should see "File Not Found" + When I go to "/en/hello.html" + Then I should see "File Not Found" + When I go to "/" + Then I should see "Como Esta?" + When I go to "/hola.html" + Then I should see "Hola World" + When I go to "/hello.html" + Then I should see "File Not Found" + When I go to "/es/index.html" + Then I should see "File Not Found" + When I go to "/es/hola.html" + Then I should see "File Not Found" + Scenario: Running localize with the no mount config Given a fixture app "i18n-test-app" From afc62d5a26cf362751edbdff040288ad203283d7 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 12:34:30 -0800 Subject: [PATCH 07/22] i18n tweaks --- middleman-more/lib/middleman-more/core_extensions/i18n.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/middleman-more/lib/middleman-more/core_extensions/i18n.rb b/middleman-more/lib/middleman-more/core_extensions/i18n.rb index 534f4ad8..4f84b2b8 100644 --- a/middleman-more/lib/middleman-more/core_extensions/i18n.rb +++ b/middleman-more/lib/middleman-more/core_extensions/i18n.rb @@ -43,7 +43,7 @@ module Middleman @mount_at_root = @options.has_key?(:mount_at_root) ? @options[:mount_at_root] : langs.first if !@app.build? - logger.info "== Locales: #{langs.join(", ")}" + logger.info "== Locales: #{langs.join(", ")} (Default #{@mount_at_root})" end # Don't output localizable files @@ -79,7 +79,9 @@ module Middleman end def langs - @options[:langs] || begin + if @options[:langs] + Array(@options[:langs]).map(&:to_sym) + else Dir[File.join(@app.root, @locales_glob)].map { |file| File.basename(file).sub(/\.yml$/, "").sub(/\.rb$/, "") }.sort.map(&:to_sym) From fbc4d7e9c7ded08266bcc192efe5f58ad6c10ba6 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 12:40:43 -0800 Subject: [PATCH 08/22] Handle non-english default languages. Fixes #584 --- .../middleman-more/core_extensions/i18n.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/middleman-more/lib/middleman-more/core_extensions/i18n.rb b/middleman-more/lib/middleman-more/core_extensions/i18n.rb index 4f84b2b8..57eee442 100644 --- a/middleman-more/lib/middleman-more/core_extensions/i18n.rb +++ b/middleman-more/lib/middleman-more/core_extensions/i18n.rb @@ -52,15 +52,20 @@ module Middleman @app.sitemap.provides_metadata_for_path do |url| if d = get_localization_data(url) lang, page_id = d - instance_vars = Proc.new { - ::I18n.locale = lang - @lang = lang - @page_id = page_id - } - { :blocks => [instance_vars] } else - {} + # Default to the @mount_at_root lang + page_id = nil + lang = @mount_at_root end + + instance_vars = Proc.new do + ::I18n.locale = lang + @lang = lang + @page_id = page_id + end + + locals = { :lang => lang, :page_id => page_id } + { :blocks => [instance_vars], :locals => locals } end @app.sitemap.register_resource_list_manipulator( From 0f2dc821381000462419c46e848669e4a4e8d41b Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 15:12:35 -0800 Subject: [PATCH 09/22] Add vendor.yml to exclude our fixtures from GitHub language stats --- vendor.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 vendor.yml diff --git a/vendor.yml b/vendor.yml new file mode 100644 index 00000000..417247e2 --- /dev/null +++ b/vendor.yml @@ -0,0 +1,2 @@ +- fixtures +- templates From ed119bed7ba118e7404ee5385f7c9890d2f9cf52 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 10:15:25 -0800 Subject: [PATCH 10/22] Support .yaml files for i18n --- middleman-more/lib/middleman-more/core_extensions/i18n.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/middleman-more/lib/middleman-more/core_extensions/i18n.rb b/middleman-more/lib/middleman-more/core_extensions/i18n.rb index 57eee442..e4d5c696 100644 --- a/middleman-more/lib/middleman-more/core_extensions/i18n.rb +++ b/middleman-more/lib/middleman-more/core_extensions/i18n.rb @@ -26,9 +26,9 @@ module Middleman def initialize(app, options={}) @app = app - @locales_glob = File.join(app.locales_dir, "**", "*.{rb,yml}") + @locales_glob = File.join(app.locales_dir, "**", "*.{rb,yml,yaml}") - regex = @locales_glob.sub(/\./, '\.').sub(File.join("**", "*"), ".*").sub(/\//, '\/').sub("{rb,yml}", "rb|yml") + regex = @locales_glob.sub(/\./, '\.').sub(File.join("**", "*"), ".*").sub(/\//, '\/').sub("{rb,yml,yaml}", "rb|ya?ml") @locales_regex = %r{^#{regex}} @maps = {} @@ -88,7 +88,7 @@ module Middleman Array(@options[:langs]).map(&:to_sym) else Dir[File.join(@app.root, @locales_glob)].map { |file| - File.basename(file).sub(/\.yml$/, "").sub(/\.rb$/, "") + File.basename(file).sub(/\.ya?ml$/, "").sub(/\.rb$/, "") }.sort.map(&:to_sym) end end From 923697b5178a5ddf456327188a6361f82a029802 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 00:20:37 -0800 Subject: [PATCH 11/22] Micro-optimizations around string comparisons --- .../lib/middleman-core/cli/build.rb | 2 +- .../middleman-core/core_extensions/data.rb | 4 ++-- .../core_extensions/file_watcher.rb | 3 ++- .../core_extensions/rendering.rb | 2 +- .../lib/middleman-core/preview_server.rb | 2 +- middleman-core/lib/middleman-core/sitemap.rb | 8 ++++---- .../lib/middleman-core/sitemap/store.rb | 6 +++--- middleman-core/lib/middleman-core/util.rb | 8 +++++++- .../core_extensions/default_helpers.rb | 19 +++++++++---------- .../middleman-more/core_extensions/i18n.rb | 3 ++- .../extensions/automatic_image_sizes.rb | 2 +- 11 files changed, 33 insertions(+), 26 deletions(-) diff --git a/middleman-core/lib/middleman-core/cli/build.rb b/middleman-core/lib/middleman-core/cli/build.rb index 0e08dbdc..26680123 100644 --- a/middleman-core/lib/middleman-core/cli/build.rb +++ b/middleman-core/lib/middleman-core/cli/build.rb @@ -233,7 +233,7 @@ module Middleman::Cli paths = ::Middleman::Util.all_files_under(@destination) @cleaning_queue += paths.select do |path| - !path.to_s.match(/\/\./) || path.to_s.match(/\.htaccess|\.htpasswd/) + path.to_s !~ /\/\./ || path.to_s =~ /\.(htaccess|htpasswd)/ end end diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index 360d953f..22f91778 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -25,11 +25,11 @@ module Middleman # parsing config.rb def initialize self.files.changed DataStore.matcher do |file| - self.data.touch_file(file) if file.match(%r{^#{self.data_dir}\/}) + self.data.touch_file(file) if file.start_with?("#{self.data_dir}/") end self.files.deleted DataStore.matcher do |file| - self.data.remove_file(file) if file.match(%r{^#{self.data_dir}\/}) + self.data.remove_file(file) if file.start_with?("#{self.data_dir}/") end super 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 44eb2e31..14c5b214 100644 --- a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb +++ b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb @@ -145,7 +145,8 @@ module Middleman # @param [Pathname] path # @return [Boolean] def ignored?(path) - IGNORE_LIST.any? { |r| path.to_s.match(r) } + path = path.to_s + IGNORE_LIST.any? { |r| path =~ r } end # Notify callbacks for a file given an array of callbacks diff --git a/middleman-core/lib/middleman-core/core_extensions/rendering.rb b/middleman-core/lib/middleman-core/core_extensions/rendering.rb index 83c5d737..f700e329 100644 --- a/middleman-core/lib/middleman-core/core_extensions/rendering.rb +++ b/middleman-core/lib/middleman-core/core_extensions/rendering.rb @@ -408,7 +408,7 @@ module Middleman # Find the path by searching or using the cache request_path = request_path.to_s cache.fetch(:resolve_template, request_path, options) do - relative_path = request_path.sub(%r{^/}, "") + relative_path = Util.strip_leading_slash(request_path) on_disk_path = File.expand_path(relative_path, self.source_dir) # By default, any engine will do diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 5f53c5ed..6308f4f2 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -185,7 +185,7 @@ module Middleman paths.any? do |path| match_against.any? do |matcher| - path.match(matcher) + path =~ matcher end end end diff --git a/middleman-core/lib/middleman-core/sitemap.rb b/middleman-core/lib/middleman-core/sitemap.rb index b50652b9..b3c75568 100644 --- a/middleman-core/lib/middleman-core/sitemap.rb +++ b/middleman-core/lib/middleman-core/sitemap.rb @@ -25,18 +25,18 @@ module Middleman # Setup callbacks which can exclude paths from the sitemap app.set :ignored_sitemap_matchers, { # dotfiles and folders in the root - :root_dotfiles => proc { |file| file.match(%r{^\.}) }, + :root_dotfiles => proc { |file| file.start_with?('.') }, # Files starting with an dot, but not .htaccess :source_dotfiles => proc { |file| - file.match(%r{/\.}) && !file.match(%r{/\.htaccess|\.htpasswd}) + file =~ %r{/\.} && file !~ %r{/\.(htaccess|htpasswd)} }, # Files starting with an underscore, but not a double-underscore - :partials => proc { |file| file.match(%r{/_}) && !file.match(%r{/__}) }, + :partials => proc { |file| file =~ %r{/_} && file !~ %r{/__} }, :layout => proc { |file| - file.match(%r{^source/layout\.}) || file.match(%r{^source/layouts/}) + file.start_with?('source/layout.') || file.start_with?('source/layouts/') } } diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index eb78088c..30f59789 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -108,7 +108,7 @@ module Middleman blank_metadata = { :options => {}, :locals => {}, :page => {}, :blocks => [] } provides_metadata.inject(blank_metadata) do |result, (callback, matcher)| - next result if !matcher.nil? && !source_file.match(matcher) + next result if matcher && !source_file.match(matcher) metadata = callback.call(source_file) @@ -146,9 +146,9 @@ module Middleman @_cached_metadata[request_path] = provides_metadata_for_path.inject(blank_metadata) do |result, (callback, matcher)| case matcher when Regexp - next result unless request_path.match(matcher) + next result unless request_path =~ matcher when String - next result unless File.fnmatch("/" + matcher.sub(%r{^/}, ''), "/#{request_path}") + next result unless File.fnmatch("/" + Util.strip_leading_slash(matcher), "/#{request_path}") end metadata = callback.call(request_path) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 0444be7a..00a28e2b 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -83,7 +83,13 @@ module Middleman # @return [String] def self.normalize_path(path) # The tr call works around a bug in Ruby's Unicode handling - path.sub(/^\//, "").tr('','') + path.sub(%r{^/}, "").tr('','') + end + + # This is a separate method from normalize_path in case we + # change how we normalize paths + def self.strip_leading_slash(path) + path.sub(%r{^/}, "") end # Extract the text of a Rack response as a string. diff --git a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb index 4b30967c..80233244 100644 --- a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb +++ b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb @@ -64,7 +64,7 @@ module Middleman # 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_path) - path = path.gsub(File.extname(path), ".#{asset_ext}") + path = path.sub(/#{File.extname(path)}$/, ".#{asset_ext}") yield path if sitemap.find_resource_by_path(path) end @@ -74,11 +74,11 @@ module Middleman # @return [String] def page_classes path = current_path.dup - path << index_file if path.match(%r{/$}) - path = path.gsub(%r{^/}, '') + path << index_file if path.end_with?('/') + path = Util.strip_leading_slash(path) classes = [] - parts = path.split('.')[0].split('/') + parts = path.split('.').first.split('/') parts.each_with_index { |path, i| classes << parts.first(i+1).join('_') } classes.join(' ') @@ -90,19 +90,18 @@ module Middleman # @param [String] source The path to the file # @return [String] def asset_path(kind, source) - return source if source =~ /^http/ + return source if source.to_s.include?('//') asset_folder = case kind when :css then css_dir when :js then js_dir when :images then images_dir else kind.to_s end - source = source.to_s.gsub(/\s/, '') + source = source.to_s.tr(' ', '') ignore_extension = (kind == :images) # don't append extension - source << ".#{kind}" unless ignore_extension or source =~ /\.#{kind}/ - if source =~ %r{^/} # absolute path - asset_folder = "" - end + source << ".#{kind}" unless ignore_extension || source.end_with?(".#{kind}") + asset_folder = "" if source.start_with?('/') # absolute path + asset_url(source, asset_folder) end diff --git a/middleman-more/lib/middleman-more/core_extensions/i18n.rb b/middleman-more/lib/middleman-more/core_extensions/i18n.rb index e4d5c696..1ab2c019 100644 --- a/middleman-more/lib/middleman-more/core_extensions/i18n.rb +++ b/middleman-more/lib/middleman-more/core_extensions/i18n.rb @@ -28,6 +28,7 @@ module Middleman @app = app @locales_glob = File.join(app.locales_dir, "**", "*.{rb,yml,yaml}") + # File.fnmatch doesn't support brackets: {rb,yml} regex = @locales_glob.sub(/\./, '\.').sub(File.join("**", "*"), ".*").sub(/\//, '\/').sub("{rb,yml,yaml}", "rb|ya?ml") @locales_regex = %r{^#{regex}} @@ -78,7 +79,7 @@ module Middleman end def on_file_changed(file) - if @locales_regex.match(file) + if @locales_regex =~ file ::I18n.reload! end end diff --git a/middleman-more/lib/middleman-more/extensions/automatic_image_sizes.rb b/middleman-more/lib/middleman-more/extensions/automatic_image_sizes.rb index 58e52f71..a83ca4cc 100644 --- a/middleman-more/lib/middleman-more/extensions/automatic_image_sizes.rb +++ b/middleman-more/lib/middleman-more/extensions/automatic_image_sizes.rb @@ -38,7 +38,7 @@ module Middleman params[:alt] ||= "" real_path = path - real_path = File.join(images_dir, real_path) unless real_path =~ %r{^/} + real_path = File.join(images_dir, real_path) unless real_path.start_with?('/') full_path = File.join(source_dir, real_path) if File.exists? full_path From 559265140d0f2cdb41d7ee9cc75c6cce9f49d66d Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 27 Oct 2012 11:47:06 -0700 Subject: [PATCH 12/22] Stub out rspec tests for public APIs: Rack and Sitemap for now --- gem_rake_helper.rb | 23 +++++++++++++++++-- .../spec/middleman-core/sitemap_spec.rb | 0 middleman-core/spec/spec_helper.rb | 0 .../spec/middleman-more/future_spec.rb | 0 middleman-more/spec/spec_helper.rb | 0 middleman/spec/middleman/future_spec.rb | 0 middleman/spec/spec_helper.rb | 0 7 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 middleman-core/spec/middleman-core/sitemap_spec.rb create mode 100644 middleman-core/spec/spec_helper.rb create mode 100644 middleman-more/spec/middleman-more/future_spec.rb create mode 100644 middleman-more/spec/spec_helper.rb create mode 100644 middleman/spec/middleman/future_spec.rb create mode 100644 middleman/spec/spec_helper.rb diff --git a/gem_rake_helper.rb b/gem_rake_helper.rb index 6353f05b..f9585479 100644 --- a/gem_rake_helper.rb +++ b/gem_rake_helper.rb @@ -1,6 +1,5 @@ require 'rubygems' unless defined?(Gem) require 'rake' -require 'cucumber/rake/task' require 'yard' require 'bundler' @@ -16,7 +15,9 @@ class Bundler::GemHelper end end -Cucumber::Rake::Task.new(:test, 'Run features that should pass') do |t| +require 'cucumber/rake/task' + +Cucumber::Rake::Task.new do |t| exempt_tags = ["--tags ~@wip"] exempt_tags << "--tags ~@nojava" if RUBY_PLATFORM == "java" exempt_tags << "--tags ~@encoding" unless Object.const_defined?(:Encoding) @@ -25,6 +26,24 @@ Cucumber::Rake::Task.new(:test, 'Run features that should pass') do |t| t.cucumber_opts = "--color #{exempt_tags.join(" ")} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" end +Cucumber::Rake::Task.new(:cucumber_wip) do |t| + exempt_tags = ["--tags @wip"] + exempt_tags << "--tags ~@nojava" if RUBY_PLATFORM == "java" + exempt_tags << "--tags ~@encoding" unless Object.const_defined?(:Encoding) + + t.cucumber_opts = "--color #{exempt_tags.join(" ")} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" +end + +require 'rspec/core/rake_task' +desc "Run RSpec" +RSpec::Core::RakeTask.new do |spec| + spec.pattern = 'spec/**/*_spec.rb' + spec.rspec_opts = ['--color', '--format nested'] +end + +desc "Run tests, both RSpec and Cucumber" +task :test => [:spec, :cucumber] + YARD::Rake::YardocTask.new task :default => :test diff --git a/middleman-core/spec/middleman-core/sitemap_spec.rb b/middleman-core/spec/middleman-core/sitemap_spec.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman-core/spec/spec_helper.rb b/middleman-core/spec/spec_helper.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman-more/spec/middleman-more/future_spec.rb b/middleman-more/spec/middleman-more/future_spec.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman-more/spec/spec_helper.rb b/middleman-more/spec/spec_helper.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman/spec/middleman/future_spec.rb b/middleman/spec/middleman/future_spec.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman/spec/spec_helper.rb b/middleman/spec/spec_helper.rb new file mode 100644 index 00000000..e69de29b From 76d09a49649378e65e041c0761e69f054c943d3d Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 9 Feb 2013 15:37:08 -0800 Subject: [PATCH 13/22] Pathname issues when combining relative assets and cache buster --- middleman-more/lib/middleman-more/extensions/relative_assets.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-more/lib/middleman-more/extensions/relative_assets.rb b/middleman-more/lib/middleman-more/extensions/relative_assets.rb index 7e457cd4..0bb0a777 100644 --- a/middleman-more/lib/middleman-more/extensions/relative_assets.rb +++ b/middleman-more/lib/middleman-more/extensions/relative_assets.rb @@ -36,7 +36,7 @@ module Middleman path else current_dir = Pathname('/' + current_resource.destination_path) - Pathname(path).relative_path_from(current_dir.dirname) + Pathname(path).relative_path_from(current_dir.dirname).to_s end end end From 700b844e67ac8df69728910aae5aca7478984f44 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 9 Feb 2013 15:45:45 -0800 Subject: [PATCH 14/22] Add a spec for testing Middleman::Util#binary? --- Rakefile | 9 ++++++++- middleman-core/lib/middleman-core/util.rb | 3 +++ .../spec/middleman-core/binary_spec.rb | 15 +++++++++++++++ .../spec/middleman-core/binary_spec/middleman | Bin 0 -> 25282 bytes .../middleman-core/binary_spec/middleman.png | Bin 0 -> 25282 bytes .../spec/middleman-core/binary_spec/plain.txt | 1 + .../spec/middleman-core/binary_spec/stars.svgz | Bin 0 -> 33861 bytes .../spec/middleman-core/binary_spec/unicode | 1 + .../spec/middleman-core/binary_spec/unicode.txt | 1 + 9 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 middleman-core/spec/middleman-core/binary_spec.rb create mode 100644 middleman-core/spec/middleman-core/binary_spec/middleman create mode 100644 middleman-core/spec/middleman-core/binary_spec/middleman.png create mode 100644 middleman-core/spec/middleman-core/binary_spec/plain.txt create mode 100644 middleman-core/spec/middleman-core/binary_spec/stars.svgz create mode 100644 middleman-core/spec/middleman-core/binary_spec/unicode create mode 100644 middleman-core/spec/middleman-core/binary_spec/unicode.txt diff --git a/Rakefile b/Rakefile index 630c02ff..1801ea15 100644 --- a/Rakefile +++ b/Rakefile @@ -87,6 +87,13 @@ task :test do end end +desc "Run specs for all middleman gems" +task :spec do + GEM_PATHS.each do |g| + sh "cd #{File.join(ROOT, g)} && #{Gem.ruby} -S rake spec" + end +end + # desc "Rune cane for all middleman gems" # task :cane do # GEM_PATHS.each do |g| @@ -95,4 +102,4 @@ end # end desc "Run tests for all middleman gems" -task :default => :test \ No newline at end of file +task :default => :test diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 00a28e2b..0bee9661 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -10,6 +10,9 @@ require "thor" # Core Pathname library used for traversal require "pathname" +require "tilt" +require "rack/mime" + module Middleman module Util diff --git a/middleman-core/spec/middleman-core/binary_spec.rb b/middleman-core/spec/middleman-core/binary_spec.rb new file mode 100644 index 00000000..ad04efb7 --- /dev/null +++ b/middleman-core/spec/middleman-core/binary_spec.rb @@ -0,0 +1,15 @@ +require 'middleman-core/util' + +describe "Middleman::Util#binary?" do + %w(plain.txt unicode.txt unicode stars.svgz).each do |file| + it "recognizes #{file} as not binary" do + Middleman::Util.binary?(File.join(File.dirname(__FILE__), "binary_spec/#{file}")).should be_false + end + end + + %w(middleman.png middleman).each do |file| + it "recognizes #{file} as binary" do + Middleman::Util.binary?(File.join(File.dirname(__FILE__), "binary_spec/#{file}")).should be_true + end + end +end diff --git a/middleman-core/spec/middleman-core/binary_spec/middleman b/middleman-core/spec/middleman-core/binary_spec/middleman new file mode 100644 index 0000000000000000000000000000000000000000..c685e564378b038c44e51ec98454af7237d3412a GIT binary patch literal 25282 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 a7#`i-@whYe`D6wL1_n=8KbLh*2~7ZtE++T@ literal 0 HcmV?d00001 diff --git a/middleman-core/spec/middleman-core/binary_spec/middleman.png b/middleman-core/spec/middleman-core/binary_spec/middleman.png new file mode 100644 index 0000000000000000000000000000000000000000..c685e564378b038c44e51ec98454af7237d3412a GIT binary patch literal 25282 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 a7#`i-@whYe`D6wL1_n=8KbLh*2~7ZtE++T@ literal 0 HcmV?d00001 diff --git a/middleman-core/spec/middleman-core/binary_spec/plain.txt b/middleman-core/spec/middleman-core/binary_spec/plain.txt new file mode 100644 index 00000000..649adbeb --- /dev/null +++ b/middleman-core/spec/middleman-core/binary_spec/plain.txt @@ -0,0 +1 @@ +Some plain text diff --git a/middleman-core/spec/middleman-core/binary_spec/stars.svgz b/middleman-core/spec/middleman-core/binary_spec/stars.svgz new file mode 100644 index 0000000000000000000000000000000000000000..a54ce7ff12235e21ea2452f9dcb8ad0bd5d291b7 GIT binary patch literal 33861 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 VzwQ5R|NrtoyOxxc)1l>z3;-Jt-2MOn literal 0 HcmV?d00001 diff --git a/middleman-core/spec/middleman-core/binary_spec/unicode b/middleman-core/spec/middleman-core/binary_spec/unicode new file mode 100644 index 00000000..13dc1361 --- /dev/null +++ b/middleman-core/spec/middleman-core/binary_spec/unicode @@ -0,0 +1 @@ +明日がある。 diff --git a/middleman-core/spec/middleman-core/binary_spec/unicode.txt b/middleman-core/spec/middleman-core/binary_spec/unicode.txt new file mode 100644 index 00000000..13dc1361 --- /dev/null +++ b/middleman-core/spec/middleman-core/binary_spec/unicode.txt @@ -0,0 +1 @@ +明日がある。 From ae7f75e5cc860b3555c384d8da20dad0ed572977 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 9 Feb 2013 15:53:21 -0800 Subject: [PATCH 15/22] Relative Assets shouldn't return a Pathname sometimes, the rest of the code expects Strings --- middleman-more/features/cache_buster.feature | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/middleman-more/features/cache_buster.feature b/middleman-more/features/cache_buster.feature index 7c094f7f..11040ba5 100644 --- a/middleman-more/features/cache_buster.feature +++ b/middleman-more/features/cache_buster.feature @@ -25,3 +25,18 @@ Feature: Generate mtime-based query string for busting browser caches When I go to "/cache-buster.html" Then I should see "site.css?" Then I should see "blank.gif?" + + Scenario: Rendering css with the feature and relative_assets enabled + Given "relative_assets" feature is "enabled" + Given "cache_buster" feature is "enabled" + And the Server is running at "cache-buster-app" + When I go to "/stylesheets/relative_assets.css" + Then I should see "blank.gif?" + + Scenario: Rendering html with the feature and relative_assets enabled + Given "relative_assets" feature is "enabled" + Given "cache_buster" feature is "enabled" + 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 From b94be9ed932d8669b54bb4d6ac6fd523c60bf7bb Mon Sep 17 00:00:00 2001 From: Jon Rowe Date: Sun, 10 Feb 2013 21:49:32 +1100 Subject: [PATCH 16/22] Removed outdated information. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems the wiki is no longer publicly accessible. Linking to it confuses people. --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 61866dc9..e7cc690d 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,7 @@ A full set of in-depth instructional guides are available on the official websit http://middlemanapp.com/ -The community maintains its own collection of tips and tricks in the GitHub wiki: - - https://github.com/middleman/middleman/wiki - -Finally, up-to-date generated code documentation is available on RubyDoc: +Additionally, up-to-date generated code documentation is available on RubyDoc: http://rubydoc.info/github/middleman/middleman # Community From 3bdbc11db29c8ef88eaebf5f91274e90748761eb Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sun, 10 Feb 2013 12:05:07 -0800 Subject: [PATCH 17/22] Change the behavior of before_render and after_render hooks from #761. This changes the before_render and after_render hooks so that the callbacks given to them each get to modify the template source / the rendered output in turn, instead of having to modify them in-place. It also changes the arguments provided to the callbacks - now, they are given the source/output, the template path, the locals hash, and the Tilt template *class*, wheras previously they were given the source/output and the Tilt template *instance*. The locals hash is there in case pron case hooks want to pay attention to the locals in some way. The before_render hook is also run before compiling the template and caching it, which should prevent weird data mismatches and save some template compilation effort. --- .../middleman-core/core_extensions/rendering.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/rendering.rb b/middleman-core/lib/middleman-core/core_extensions/rendering.rb index f700e329..f61079ef 100644 --- a/middleman-core/lib/middleman-core/core_extensions/rendering.rb +++ b/middleman-core/lib/middleman-core/core_extensions/rendering.rb @@ -246,15 +246,26 @@ module Middleman options = opts.merge(options_for_ext(extension)) options[:outvar] ||= '@_out_buf' + template_class = Tilt[path] + # Allow hooks to manipulate the template before render + self.class.callbacks_for_hook(:before_render).each do |callback| + newbody = callback.call(body, path, locs, template_class) + body = newbody if newbody # Allow the callback to return nil to skip it + end + # Read compiled template from disk or cache template = cache.fetch(:compiled_template, options, body) do ::Tilt.new(path, 1, options) { body } end # Render using Tilt - run_hook :before_render, template.data, template - content = template.render(context, locs, &block) - run_hook :after_render, content, template + content = template.render(context, path, locs, &block) + + # Allow hooks to manipulate the result after render + self.class.callbacks_for_hook(:after_render).each do |callback| + content = callback.call(content, locs, template_class) + end + return content ensure # Reset stored buffer From 6fa6c021c00195ebe8655c5ec89d2364d1e61dff Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Fri, 8 Feb 2013 22:22:33 -0800 Subject: [PATCH 18/22] Refactor out a url_for method --- .../core_extensions/default_helpers.rb | 138 ++++++++++-------- 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb index 80233244..6ecedcf0 100644 --- a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb +++ b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb @@ -105,6 +105,78 @@ module Middleman asset_url(source, asset_folder) end + # 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. + def url_for(path_or_resource, options={}) + # Handle Resources and other things which define their own url method + url = path_or_resource.respond_to?(:url) ? path_or_resource.url : path_or_resource + + begin + uri = URI(url) + rescue URI::InvalidURIError + # Nothing we can do with it, it's not really a URI + return url + end + + relative = options.delete(:relative) + raise "Can't use the relative option with an external URL" if relative && uri.host + + # Allow people to turn on relative paths for all links with + # set :relative_links, true + # but still override on a case by case basis with the :relative parameter. + effective_relative = relative || false + effective_relative = true if relative.nil? && relative_links + + # Try to find a sitemap resource corresponding to the desired path + this_resource = current_resource # store in a local var to save work + if path_or_resource.is_a?(Sitemap::Resource) + resource = path_or_resource + resource_url = url + elsif this_resource && uri.path + # Handle relative urls + url_path = Pathname(uri.path) + current_source_dir = Pathname('/' + this_resource.path).dirname + url_path = current_source_dir.join(url_path) if url_path.relative? + resource = sitemap.find_resource_by_path(url_path.to_s) + resource_url = resource.url if resource + end + + if resource + # Switch to the relative path between this_resource and the given resource + # if we've been asked to. + if effective_relative + # Output urls relative to the destination path, not the source path + current_dir = Pathname('/' + this_resource.destination_path).dirname + relative_path = Pathname(resource_url).relative_path_from(current_dir).to_s + + # Put back the trailing slash to avoid unnecessary Apache redirects + if resource_url.end_with?('/') && !relative_path.end_with?('/') + relative_path << '/' + end + + uri.path = relative_path + else + uri.path = 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 + if query = options.delete(:query) + uri.query = query.respond_to?(:to_param) ? query.to_param : query.to_s + end + + # Support a :fragment or :anchor option just like Padrino + fragment = options.delete(:anchor) || options.delete(:fragment) + uri.fragment = fragment.to_s if fragment + + # Finally make the URL back into a string + uri.to_s + end + # Overload the regular link_to to be sitemap-aware - if you # reference a source path, either absolutely or relatively, # you'll get that resource's nice URL. Also, there is a @@ -124,69 +196,9 @@ module Middleman if url = args[url_arg_index] options = args[options_index] || {} - relative = options.delete(:relative) - - # Handle Resources, which define their own url method - if url.respond_to? :url - url = args[url_arg_index] = url.url - end - - if url.include? '://' - raise "Can't use the relative option with an external URL" if relative - elsif current_resource - # Handle relative urls - current_source_dir = Pathname('/' + current_resource.path).dirname - - begin - uri = URI(url) - url_path = uri.path - rescue - end - - if url_path - path = Pathname(url_path) - url_path = current_source_dir.join(path).to_s if path.relative? - - resource = sitemap.find_resource_by_path(url_path) - - # Allow people to turn on relative paths for all links with config[:relative_links] = true - # but still override on a case by case basis with the :relative parameter. - effective_relative = relative || false - if relative.nil? && relative_links - effective_relative = true - end - - if resource - if effective_relative - resource_url = resource.url - - # Output urls relative to the destination path, not the source path - current_dir = Pathname('/' + current_resource.destination_path).dirname - new_url = Pathname(resource_url).relative_path_from(current_dir).to_s - - # Put back the trailing slash to avoid unnecessary Apache redirects - if resource_url.end_with?('/') && !new_url.end_with?('/') - new_url << '/' - end - else - new_url = resource.url - end - - uri.path = new_url - - args[url_arg_index] = uri.to_s - else - raise "No resource exists at #{url}" if relative - end - end - end - - # Support a :query option that can be a string or hash - if query = options.delete(:query) - uri = URI(args[url_arg_index]) - uri.query = query.respond_to?(:to_param) ? query.to_param : query.to_s - args[url_arg_index] = uri.to_s - end + + # Transform the url through our magic url_for method + args[url_arg_index] = url_for(url, options) end super(*args, &block) From ba035882fe1baad59e548ddec181e68b37cd8bfb Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Fri, 8 Feb 2013 22:40:27 -0800 Subject: [PATCH 19/22] Test for url_for --- .../features/helpers_url_for.feature | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 middleman-more/features/helpers_url_for.feature diff --git a/middleman-more/features/helpers_url_for.feature b/middleman-more/features/helpers_url_for.feature new file mode 100644 index 00000000..c2b5a5a8 --- /dev/null +++ b/middleman-more/features/helpers_url_for.feature @@ -0,0 +1,152 @@ +Feature: url_for helper + + Scenario: url_for produces relative links + Given a fixture app "indexable-app" + And an empty file named "config.rb" + And a file named "source/url_for.html.erb" with: + """ + absolute: <%= url_for "/needs_index.html", :relative => true %> + relative: <%= url_for "needs_index.html", :relative => true %> + """ + And a file named "source/url_for/sub.html.erb" with: + """ + absolute: <%= url_for "/needs_index.html", :relative => true %> + relative: <%= url_for "../needs_index.html", :relative => true %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for.html" + Then I should see 'absolute: needs_index.html' + Then I should see 'relative: needs_index.html' + When I go to "/url_for/sub.html" + Then I should see 'absolute: ../needs_index.html' + Then I should see 'relative: ../needs_index.html' + + Scenario: url_for relative works with strip_index_file + Given a fixture app "indexable-app" + And a file named "config.rb" with: + """ + set :relative_links, true + set :strip_index_file, true + helpers do + def menu_items(path='url_for.html') + sitemap.find_resource_by_destination_path(path).children + end + end + """ + And a file named "source/url_for.html.erb" with: + """ + <% menu_items.each do |item| %> + "<%= url_for(item.url) %>" + "<%= url_for(item) %>" + <% end %> + """ + And a file named "source/url_for/sub.html.erb" with: + """ + <% menu_items.each do |item| %> + "<%= url_for(item.url) %>" + "<%= url_for(item) %>" + <% end %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for.html" + Then I should see '"url_for/sub.html"' + Then I should not see "/url_for/sub.html" + When I go to "/url_for/sub.html" + Then I should see '"sub.html"' + Then I should not see "/url_for/sub.html" + + Scenario: url_for produces relative links when :relative_links is set to true + Given a fixture app "indexable-app" + And a file named "config.rb" with: + """ + set :relative_links, true + """ + And a file named "source/url_for.html.erb" with: + """ + absolute: <%= url_for "/needs_index.html" %> + relative: <%= url_for "needs_index.html", :relative => false %> + unknown: <%= url_for "foo.html" %> + """ + And a file named "source/url_for/sub.html.erb" with: + """ + absolute: <%= url_for "/needs_index.html" %> + relative: <%= url_for "../needs_index.html" %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for.html" + Then I should see 'absolute: needs_index.html' + Then I should see 'relative: /needs_index.html' + Then I should see 'unknown: foo.html' + When I go to "/url_for/sub.html" + Then I should see 'absolute: ../needs_index.html' + Then I should see 'relative: ../needs_index.html' + + Scenario: url_for knows about directory indexes + Given a fixture app "indexable-app" + And a file named "source/url_for.html.erb" with: + """ + absolute: <%= url_for "/needs_index.html", :relative => true %> + relative: <%= url_for "needs_index.html", :relative => true %> + """ + And a file named "source/url_for/sub.html.erb" with: + """ + absolute: <%= url_for "/needs_index.html", :relative => true %> + relative: <%= url_for "../needs_index.html", :relative => true %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for/" + Then I should see 'absolute: ../needs_index/' + Then I should see 'relative: ../needs_index/' + When I go to "/url_for/sub/" + Then I should see 'absolute: ../../needs_index/' + Then I should see 'relative: ../../needs_index/' + + Scenario: url_for can take a Resource + Given a fixture app "indexable-app" + And a file named "source/url_for.html.erb" with: + """ + "<%= url_for sitemap.find_resource_by_path("/needs_index.html") %>" + """ + And the Server is running at "indexable-app" + When I go to "/url_for/" + Then I should see '"/needs_index/"' + + Scenario: Setting http_prefix + Given a fixture app "indexable-app" + And a file named "config.rb" with: + """ + set :http_prefix, "/foo" + """ + And a file named "source/url_for.html.erb" with: + """ + <%= url_for "/needs_index.html" %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for.html" + Then I should see '/foo/needs_index.html' + + Scenario: url_for preserves query string and anchor and isn't messed up by them + Given a fixture app "indexable-app" + And a file named "source/url_for.html.erb" with: + """ + Needs Index Anchor <%= url_for "/needs_index.html#foo" %> + Needs Index Query <%= url_for "/needs_index.html?foo" %> + Needs Index Query and Anchor <%= url_for "/needs_index.html?foo#foo" %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for/" + Then I should see 'Needs Index Anchor /needs_index/#foo' + Then I should see 'Needs Index Query /needs_index/?foo' + Then I should see 'Needs Index Query and Anchor /needs_index/?foo#foo' + + Scenario: url_for accepts a :query option that appends a query string + Given a fixture app "indexable-app" + And a file named "source/url_for.html.erb" with: + """ + Needs Index String <%= url_for "/needs_index.html", :query => "foo" %> + Needs Index Hash <%= url_for "/needs_index.html", :query => { :foo => :bar } %> + """ + And the Server is running at "indexable-app" + When I go to "/url_for/" + Then I should see 'Needs Index String /needs_index/?foo' + Then I should see 'Needs Index Hash /needs_index/?foo=bar' From 3a3d5bbe3b2a4bae065e8504c360571bf5c5ff77 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Fri, 8 Feb 2013 23:00:29 -0800 Subject: [PATCH 20/22] Override form_tag to use url_for. Fixes #739 --- .../features/helpers_form_tag.feature | 26 +++++++++++++++++++ .../core_extensions/default_helpers.rb | 7 +++++ 2 files changed, 33 insertions(+) create mode 100644 middleman-more/features/helpers_form_tag.feature diff --git a/middleman-more/features/helpers_form_tag.feature b/middleman-more/features/helpers_form_tag.feature new file mode 100644 index 00000000..643ca18a --- /dev/null +++ b/middleman-more/features/helpers_form_tag.feature @@ -0,0 +1,26 @@ +Feature: form_tag helper + + Scenario: form_tag produces relative links + Given a fixture app "indexable-app" + And an empty file named "config.rb" + And a file named "source/form_tag.html.erb" with: + """ + absolute: <% form_tag "/needs_index.html#absolute", :relative => true do %> + <% end %> + relative: <% form_tag "needs_index.html#relative", :relative => true do %> + <% end %> + """ + And a file named "source/form_tag/sub.html.erb" with: + """ + absolute: <% form_tag "/needs_index.html#absolute", :relative => true do %> + <% end %> + relative: <% form_tag "../needs_index.html#relative", :relative => true do %> + <% end %> + """ + And the Server is running at "indexable-app" + When I go to "/form_tag.html" + Then I should see 'action="needs_index.html#absolute"' + Then I should see 'action="needs_index.html#relative"' + When I go to "/form_tag/sub.html" + Then I should see 'action="../needs_index.html#absolute"' + Then I should see 'action="../needs_index.html#relative"' diff --git a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb index 6ecedcf0..e980b922 100644 --- a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb +++ b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb @@ -203,6 +203,13 @@ module Middleman super(*args, &block) end + + # Modified Padrino form_for that uses Middleman's url_for + # to transform the URL. + def form_tag(url, options={}, &block) + url = url_for(url, options) + super + end end end end From 42320ade8dfa641021653f82aa008a756343150a Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Wed, 6 Feb 2013 00:26:21 -0800 Subject: [PATCH 21/22] Force svgz to be binary --- middleman-core/lib/middleman-core/util.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 0bee9661..710b86ca 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -23,6 +23,7 @@ module Middleman # @return [Boolean] def self.binary?(filename) ext = File.extname(filename) + return true if ext == '.svgz' return false if Tilt.registered?(ext.sub('.','')) ext = ".#{ext}" unless ext.to_s[0] == ?. From e4b52022380690c1b1c70068c106b3cca93964eb Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Wed, 6 Feb 2013 00:16:30 -0800 Subject: [PATCH 22/22] Provide some helpful error messages when link_to is used improperly --- .../lib/middleman-more/core_extensions/default_helpers.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb index e980b922..2da4d171 100644 --- a/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb +++ b/middleman-more/lib/middleman-more/core_extensions/default_helpers.rb @@ -194,8 +194,13 @@ module Middleman url_arg_index = block_given? ? 0 : 1 options_index = block_given? ? 1 : 2 + if block_given? && args.size > 2 + raise ArgumentError.new("Too many arguments to link_to(url, options={}, &block)") + end + if url = args[url_arg_index] options = args[options_index] || {} + raise ArgumentError.new("Options must be a hash") unless options.is_a?(Hash) # Transform the url through our magic url_for method args[url_arg_index] = url_for(url, options)